Package: ppxf
pPXF: Full Spectrum Fitting with Photometry for Stars and GalaxiesThispPXFpackage contains a Python implementation of the Penalized
PiXel-Fitting (pPXF) method. It uses full-spectrum fitting with photometry
(SED) to extract the stellar and gas kinematics, as well as the stellar population of
stars and galaxies. The method was originally described inCappellari & Emsellem (2004)and was substantially upgraded in subsequent years and particularly inCappellari (2017)and with the inclusion of photometry and linear constraints inCappellari (2023).ContentsAttributionInstallationUsage ExamplespPXF PurposeCalling SequenceInput ParametersOptional KeywordsOutput ParametersHow to Set the Kinematic Penalty KeywordProblems with Your First Fit?LicenseChangelogAttributionIf you use this software for your research, please cite at leastCappellari (2023),
or additionally somepPXFpapers above. The BibTeX entry for the paper is:@ARTICLE{Cappellari2023,
    author = {{Cappellari}, M.},
    title = "{Full spectrum fitting with photometry in PPXF: stellar population
        versus dynamical masses, non-parametric star formation history and
        metallicity for 3200 LEGA-C galaxies at redshift $z\approx0.8$}",
    journal = {MNRAS},
    eprint = {2208.14974},
    year = 2023,
    volume = 526,
    pages = {3273-3300},
    doi = {10.1093/mnras/stad2597}
}Installationinstall with:pip install ppxfWithout write access to the globalsite-packagesdirectory, use:pip install --user ppxfTo upgradepPXFto the latest version use:pip install --upgrade ppxfUsage ExamplesTo learn how to use thepPXFpackage, copy, modify and run
the example programs in theppxf/examplesdirectory.
It can be found within the mainppxfpackage installation folder
insidesite-packages.
The detailed documentation is contained in the docstring of the fileppxf.py, or onPyPior as PDF
fromhttps://purl.org/cappellari/software.Examples as Jupyter Notebooks are also available on myGitHub repository.pPXF PurposeExtract the galaxy stellar and gas kinematics, stellar population and gas
emission by fitting a set of templates to an observed spectrum, or to a
combination of a spectrum and photometry (SED), via full-spectrum fitting.
It uses the Penalized PiXel-Fitting (pPXF) method originally described inCappellari & Emsellem (2004)and substantially upgraded in subsequent years and particularly inCappellari (2017)and with the inclusion of photometry and linear constraints inCappellari (2023).The following key optional features are also available:An optimal template, positive linear combination of different input
templates, can be fitted together with the kinematics.One can enforce smoothness on the template weights during the fit. This
is useful to attach a physical meaning to the weights e.g. in terms of
the star formation history of a galaxy.One can fit multiple kinematic components for both the stars and the
gas emission lines. Both the stellar and gas LOSVD can be penalized and
can be described by a general Gauss-Hermite series.One can fit simultaneously a spectrum and a set of photometric
measurements (SED fitting).Any parameter of the LOSVD (e.g. sigma) for any kinematic component can
either be fitted or held fixed to a given value, while other parameters
are fitted. Alternatively, parameters can be constrained to lie
within given limits or tied by nonlinear equalities to other parameters.One can enforce linear equality/inequality constraints on either the
template weights or the kinematic parameters.Additive and/or multiplicative polynomials can be included to adjust
the continuum shape of the template to the observed spectrum.Iterative sigma clipping can be used to clean the spectrum.It is possible to fit a mirror-symmetric LOSVD to two spectra at the
same time. This is useful for spectra taken at point-symmetric spatial
positions with respect to the center of an equilibrium stellar system.One can include sky spectra in the fit, to deal with cases where the
sky dominates the observed spectrum and an accurate sky subtraction is
critical.One can model the attenuation curve for an arbitrary number of dust
components and for user-provided attenuation curves.The covariance matrix can be input instead of the error spectrum, to
account for correlated errors in the spectral pixels.One can specify the weights fraction between two kinematics components,
e.g. to model bulge and disk contributions.One can use templates with higher resolution than the galaxy, to
improve the accuracy of the LOSVD extraction at low dispersion.Calling Sequencefromppxf.ppxfimportppxfpp=ppxf(templates,galaxy,noise,velscale,start,bias=None,bounds=None,clean=False,component=0,constr_templ=None,constr_kinem=None,degree=4,dust=None,fixed=None,fraction=None,ftol=1e-4,gas_component=None,gas_names=None,gas_reddening=None,gas_reddening_func=None,global_search=False,goodpixels=None,lam=None,lam_temp=None,linear=False,linear_method='lsq_box',mask=None,method='capfit',mdegree=0,moments=2,phot=None,plot=False,quiet=False,reddening=None,reddening_func=None,reg_dim=None,reg_ord=2,regul=0,sigma_diff=0,sky=None,templates_rfft=None,tied=None,trig=False,velscale_ratio=1,vsyst=0,x0=None)print(pp.sol)# print best-fitting kinematics (V, sigma, h3, h4)pp.plot()# Plot best fit with gas lines and photometryExample programs are in theppxf/examplesdirectory.
It can be found within the mainppxfpackage installation folder
insidesite-packages.Examples as Jupyter Notebooks are also available on myGitHub repository.Input Parameterstemplates: array_like with shape (n_pixels_temp, n_templates)Vector containing a single log-rebinned spectral template, or an array
of shape(n_pixels_temp, n_templates)containing different
log-rebinned  stellar or gas emission spectral templates to be optimized
during the fit of thegalaxyspectrum. It has to ben_pixels_temp >= galaxy.size.To apply linear regularization to theweightsvia the keywordregul,templatesshould be an array of shape2-dim:(n_pixels_temp, n_age),3-dim:(n_pixels_temp, n_age, n_metal)4-dim:(n_pixels_temp, n_age, n_metal, n_alpha)depending on the number of population variables one wants to study.
This can be useful to try to attach a physical meaning to the outputweights, in term of the galaxy star formation history and chemical
composition distribution.
In that case the templates may represent single stellar population SSP
models and should be arranged in sequence of increasing age,
metallicity or alpha (or alternative population parameters) along the
second, third or fourth dimension of the array respectively.IMPORTANT: The templates must be normalized to unity order of
magnitude, to avoid numerical instabilities.When studying stellar population, the relative fluxes of the templates
are important. For this reason one must scale all templates by a scalar.
This can be done with a command like:templates /= np.median(templates)When using individual stars as templates, the relative fluxes are
generally irrelevant and one can normalize each template independently.
This can be done with a command like:templates /= np.median(templates, 0)galaxy: array_like with shape (n_pixels,)Vector containing the log-rebinned spectrum of the galaxy to be
measured. Both the templates and the galaxy spectra have to be
logarithmically rebinned and the continuum shouldnotbe
subtracted. The rebinning may be performed with thelog_rebinroutine inppxf.ppxf_util. The units of the spectrum flux are
arbitrary. One can use e.g.erg/(scm^2 A)orerg/(scm^2 pixel)as long as the same are used fortemplates. But see the note at
the end of this section.For high redshift galaxies, it is generally easier to bring the spectra
close to the restframe wavelength, before doing thepPXFfit. This
can be done by dividing the observed wavelength by(1 + z), wherezis a rough estimate of the galaxy redshift. There is no need to
modify the spectrum in any way, given that a red shift corresponds to a
linear shift of the log-rebinned spectrum. One just needs to compute
the wavelength range in the rest-frame and adjust the instrumental
resolution of the galaxy observations. See Section 2.4 ofCappellari (2017)for details.galaxycan also be an array of shape(n_pixels, 2)containing
two spectra to be fitted, at the same time, with a
reflection-symmetric LOSVD. This is useful for spectra taken at
point-symmetric spatial positions with respect to the center of an
equilibrium stellar system. For a discussion of the usefulness of
this two-sided fitting see e.g. Section 3.6 ofRix & White (1992).IMPORTANT: (1) For the two-sided fitting thevsystkeyword has to
be used. (2) Make sure the spectra are rescaled to be not too many
order of magnitude different from unity, to avoid numerical
instability. E.g. units oferg/(scm^2 A)may cause problems!noise: array_like with shape (n_pixels,)Vector containing the1*sigmauncertainty (per spectral pixel) in
thegalaxyspectrum, or covariance matrix describing the correlated
uncertainties in the galaxy spectrum. Of course this vector/matrix must
have the same units as the galaxy spectrum.The overall normalization of thenoisedoes not affect the location
of thechi2minimum. For this reason one can measure reliable
kinematics even when the noise is not accurately know.Ifgalaxyis an array of shape(n_pixels, 2)array,
thennoisehas to be an array with the same shape.Whennoisehas shape(n_pixels, n_pixels)it is assumed to
contain the covariance matrix with elementscov(i, j). When the
errors in the spectrum are uncorrelated it is mathematically equivalent
to input inpPXFan error vectornoise=errvecor a(n_pixels, n_pixels)diagonal matrixnoise =np.diag(errvec**2)(note squared!).IMPORTANT: the penalty term of thepPXFmethod is based on therelativechange of the fit residuals. For this reason, the penalty
will work as expected even if the normalization of thenoiseis
arbitrary. SeeCappellari & Emsellem (2004)for details. If no
reliable noise is available this keyword can just be set to:noise = np.ones_like(galaxy)  # Same uncertainty for all pixelsvelscale: floatVelocity scale of the spectra in km/s per pixel. It has to be the
same for both the galaxy and the template spectra.
An exception is when thevelscale_ratiokeyword is used, in which
case one can inputtemplateswith smallervelscalethangalaxy.velscaleis preciselydefinedinpPXFbyvelscale = c*np.diff(np.log(lambda)), which is approximatelyvelscale ~c*np.diff(lambda)/lambda.
See Section 2.3 ofCappellari (2017)for details.start:Vector, or list/array of vectors[start1, start2,...], with the
initial estimate for the LOSVD parameters.When LOSVD parameters are not held fixed, each vector only needs to
containstart = [velStart, sigmaStart]the initial guess for the
velocity and the velocity dispersion in km/s. The starting values for
h3-h6 (if they are fitted) are all set to zero by default.
In other words, whenmoments=4:start = [velStart, sigmaStart]is interpreted as:start = [velStart, sigmaStart, 0, 0]When the LOSVD for some kinematic components is held fixed (seefixedkeyword), all values for[Vel, Sigma, h3,h4,...]can be
provided.Unless a good initial guess is available, it is recommended to set the
startingsigma >= 3*velscalein km/s (i.e. 3 pixels). In fact, when
the sigma is very low, and far from the true solution, thechi^2of
the fit becomes weakly sensitive to small variations in sigma (seepPXFpaper). In some instances, the near-constancy ofchi^2may
cause premature convergence of the optimization.In the case of two-sided fitting a good starting value for the velocity
isvelStart = 0.0(in this casevsystwill generally be
nonzero). Alternatively on should keep in mind thatvelStartrefers
to the first input galaxy spectrum, while the second will have velocity-velStart.With multiple kinematic componentsstartmust be a list of starting
values, one for each different component.EXAMPLE: We want to fit two kinematic components. We fit 4 moments for
the first component and 2 moments for the second one as follows:component = [0, 0, ... 0, 1, 1, ... 1]
moments = [4, 2]
start = [[V1, sigma1], [V2, sigma2]]Optional Keywordsbias: float, optionalWhenmoments > 2, this parameter biases the(h3, h4,...)measurements towards zero (Gaussian LOSVD) unless their inclusion
significantly decreases the error in the fit. Set this tobias=0not to bias the fit: the solution (including[V, sigma]) will be
noisier in that case. This parameter is ignored ifmoments <= 2.
The defaultbiasshould provide acceptable results in most cases,
but it would be safe to test it with Monte Carlo simulations as
described in the section “How to Set the Kinematic Penalty Keyword”
near the end of the documentation. This keyword precisely corresponds
to the parameterlambdain theCappellari & Emsellem (2004)paper.
Note that the penalty depends on therelativechange of the fit
residuals, so it is insensitive to proper scaling of thenoisevector. A nonzerobiascan be safely used even without a reliablenoisespectrum, or with equal weighting for all pixels.bounds:Lower and upper bounds for every kinematic parameter. This is an array,
or list of arrays, with the same dimensions asstart, except for
the last dimension, which is 2. In practice, for every element ofstartone needs to specify a pair of values[lower, upper].EXAMPLE: We want to fit two kinematic components, with 4 moments for
the first component and 2 for the second (e.g. stars and gas). In this
case:moments = [4, 2]
start_stars = [V1, sigma1, 0, 0]
start_gas = [V2, sigma2]
start = [start_stars, start_gas]then we can specify boundaries for each kinematic parameter as:bounds_stars = [[V1_lo, V1_up], [sigma1_lo, sigma1_up],
                [-0.3, 0.3], [-0.3, 0.3]]
bounds_gas = [[V2_lo, V2_up], [sigma2_lo, sigma2_up]]
bounds = [bounds_stars, bounds_gas]component:When fitting more than one kinematic component, this keyword should
contain the component number of each input template. In principle,
every template can belong to a different kinematic component.EXAMPLE: We want to fit the first 50 templates to component 0 and the
last 10 templates to component 1. In this case:component = [0]*50 + [1]*10which, in Python syntax, is equivalent to:component = [0, 0, ... 0, 1, 1, ... 1]This keyword is especially useful when fitting both emissions (gas) and
absorption (stars) templates simultaneously (see the example for themomentskeyword).constr_kinem: dictionary, optionalIt enforces linear constraints on the kinematic parameters during the
fit. This is specified by the following dictionary, whereA_ineqandA_eqare arrays (haveA.ndim = 2), whileb_ineqandb_eqare vectors (haveb.ndim = 1). Either the_eqor the_ineqkeys can be omitted if not needed:constr_kinem = {"A_ineq": A_ineq, "b_ineq": b_ineq, "A_eq": A_eq, "b_eq": b_eq}The resulting pPXF kinematics solution will satisfy the following
linear matrix inequalities and/or equalities:params = np.ravel(pp.sol)  # Unravel for multiple components
A_ineq @ params <= b_ineq
A_eq @ params == b_eqIMPORTANT: the starting guessstartmust satisfy the constraints,
or in other words, it must lie in the feasible region.Inequalities can be used e.g. to force one kinematic component to have
larger velocity or dispersion than another one. This is useful e.g.
when extracting two stellar kinematic components or when fitting both
narrow and broad components of gas emission lines.EXAMPLES: We want to fit two kinematic components, with two moments for
both the first and second component. In this case:moments = [2, 2]
start = [[V1, sigma1], [V2, sigma2]]then we can set the constraintsigma1 >= 3*sigma2as follows:A_ineq = [[0, -1, 0, 3]]  # 0*V1 - 1*sigma1 + 0*V2 + 3*sigma2 <= 0
b_ineq = [0]
constr_kinem = {"A_ineq": A_ineq, "b_ineq": b_ineq}We can set the constraintsigma1 >= sigma2 + 2*velscaleas follows:A_ineq = [[0, -1, 0, 1]]  # -sigma1 + sigma2 <= -2*velscale
b_ineq = [-2]             # kinem. in pixels (-2 --> -2*velscale)!
constr_kinem =  {"A_ineq": A_ineq, "b_ineq": b_ineq}We can set both the constraintsV1 >= V2andsigma1 >= sigma2 + 2*velscaleas follows:A_ineq = [[-1, 0, 1, 0],   # -V1 + V2 <= 0
          [0, -1, 0, 1]]   # -sigma1 + sigma2 <= -2*velscale
b_ineq = [0, -2]           # kinem. in pixels (-2 --> -2*velscale)!
constr_kinem =  {"A_ineq": A_ineq, "b_ineq": b_ineq}We can constrain the velocity dispersion of the second kinematic
component to differ less than 10% from that of the first componentsigma1/1.1 <= sigma2 <= sigma1*1.1as follows:A_ineq = [[0, 1/1.1, 0, -1],   # +sigma1/1.1 - sigma2 <= 0
          [0, -1.1,  0,  1]]   # -sigma1*1.1 + sigma2 <= 0
b_ineq = [0, 0]
constr_kinem =  {"A_ineq": A_ineq, "b_ineq": b_ineq}EXAMPLE: We want to fit three kinematic components, with four moments
for the first and two for the rest. In this case:moments = [4, 2, 2]
start = [[V1, sigma1, 0, 0], [V2, sigma2], [V3, sigma3]]then we can set the constraintssigma3 >= sigma1 + 2*velscaleandV1 <= V2 <= V3as follows:A_ineq = [[0, 1, 0, 0,  0, 0,  0, -1],  # sigma1 - sigma3 <= -2*velscale
          [1, 0, 0, 0, -1, 0,  0,  0],  # V1 - V2 <= 0
          [0, 0, 0, 0,  1, 0, -1,  0]]  # V2 - V3 <= 0
b_ineq = [-2, 0, 0]           # kinem. in pixels (-2 --> -2*velscale)!
constr_kinem =  {"A_ineq": A_ineq, "b_ineq": b_ineq}NOTE: When possible, it is more efficient to set equality constraints
using thetiedkeyword, instead of settingA_eqandb_eqinconstr_kinem.constr_templ: dictionary, optionalIt enforces linear constraints on the template weights during the fit.
This is specified by the following dictionary, whereA_ineqandA_eqare arrays (haveA.ndim = 2), whileb_ineqandb_eqare vectors (haveb.ndim = 1). Either the_eqor the_ineqkeys can be omitted if not needed:constr_templ = {"A_ineq": A_ineq, "b_ineq": b_ineq, "A_eq": A_eq, "b_eq": b_eq}The resulting pPXF solution will satisfy the following linear matrix
inequalities and/or equalities:A_ineq @ pp.weights <= b_ineq
A_eq @ pp.weights == b_eqInequality can be used e.g. to constrain the fluxes of emission lines
to lie within prescribed ranges. Equalities can be used e.g. to force
the weights for different kinematic components to contain prescribed
fractions of the total weights.EXAMPLES: We are fitting a spectrum using four templates, the first two
templates belong to one kinematic component and the rest to the other.
NOTE: This 4-templates example is for illustration, but in real
applications one will use many more than two templates per component!
This implies we have:component=[0, 0, 1, 1]then we can set the equality constraint that the sum of the weights of
the first kinematic component is a givenfractionof the total:pp.weights[component == 0].sum()/pp.weights.sum() == fractionas follows [see equation 30 ofCappellari (2017)]:A_eq = [[fraction - 1, fraction - 1, fraction, fraction]]
b_eq = [0]
constr_templ = {"A_eq": A_eq, "b_eq": b_eq}An identical result can be obtained in this case using the legacyfractionkeyword, butconstr_templadditionally allows for
general linear constraints for multiple kinematic components.Similarly, we can set the inequality constraint that the total weights
of each of the two kinematic components is larger thanfraction:fraction <= pp.weights[component == 0].sum()/pp.weights.sum()
fraction <= pp.weights[component == 1].sum()/pp.weights.sum()as follows:A_ineq = [[fraction - 1, fraction - 1, fraction, fraction],
          [fraction, fraction, fraction - 1, fraction - 1]]
b_ineq = [0, 0]
constr_templ = {"A_ineq": A_ineq, "b_ineq": b_ineq}We can constrain the ratio of the first two templates weights to lie in
the intervalratio_min <=w[0]/w[1]<= ratio_maxas follows:A_ineq = [[-1, ratio_min, 0, 0],    # -w[0] + ratio_min*w[1] <= 0
          [1, -ratio_max, 0, 0]]    # +w[0] - ratio_max*w[1] <= 0
b_ineq = [0, 0]
constr_templ = {"A_ineq": A_ineq, "b_ineq": b_ineq}If we have six templates for three kinematics components:component=[0, 0, 1, 1, 2, 2]we can set the fractions for the first two components to befraction1andfraction2(of the total weights) respectively as follows
(the third components will be1 - fraction1 - fraction2):A_eq = [[fraction1 - 1, fraction1 - 1, fraction1, fraction1, fraction1, fraction1],
        [fraction2, fraction2, fraction2 - 1, fraction2 - 1, fraction2, fraction2]]
b_eq = [0, 0]
constr_templ = {"A_eq": A_eq, "b_eq": b_eq}clean: bool, optionalSet this keyword to use the iterative sigma clipping method described
in Section 2.1 ofCappellari et al. (2002).
This is useful to remove from the fit unmasked bad pixels, residual gas
emissions or cosmic rays.IMPORTANT: This is recommendedonlyif a reliable estimate of thenoisespectrum is available. See also note below for.chi2.degree: int, optionalDegree of theadditiveLegendre polynomial used to correct the
template continuum shape during the fit (default: 4). This uses the
standard mathematical definition where e.g.degree=2is a
quadratic polynomial. Setdegree=-1not to include any additive
polynomial.dust: list of dictionaries, optionalEach element of the list is a dictionary specifying the parameters
for the attenuation curve to be applied to a given set of templates.
Each dictionary can contain the following keys (only"start"and"component"are required). The meaning is similar to the same
parameters in thepPXFcall, but these are specific to the dust:dust_1 = {"bounds":..., "component":..., "fixed":..., "func":..., "start":...}
dust_2 = {"bounds":..., "component":..., "fixed":..., "func":..., "start":...}
...
dust_n = {"bounds":..., "component":..., "fixed":..., "func":..., "start":...}

dust = [dust_1, dust_2, ..., dust_n]bounds: array_like with shape (n_start, 2) -
Lower and upper bounds for every dust attenuation parameter of the
givendust_jcomponent. For every element ofdust_j["start"]one needs to specify a pair of values[lower, upper].component: array_like with shape (n_templates,) -
Boolean vector, of the same size as the kinematiccomponent, set
toTruefor the templates that should be attenuated by thedust_jcomponent.fixed: array_like with shape (n_start,) -
Boolean vector set toTruewhere adust_jattenuation parameter
has to be held fixed with the value given indust_j["start"]. This is
an array, or list, with the same dimensions asdust_j["start"].func: callable, optional -
function specifying the attenuation curve for thedust_jcomponent.
It must accept as input the same number of parameters as given indust_j["start"]. If this is not given,pPXFuses the 4-parameters
dust formulas given inCappellari (2023)implemented in the functionattenuationin the fileppxf.py.start: array_like with shape (n_start,) -
Contains the starting values for the attenuation parameters ofdust_j.EXAMPLE: We want to model two dust components, one for the gas emission
lines and another for the rest. For the gas we use a 1-parameterCalzetti et al. (2000)attenuation curve, while for the rest we
use the default attenuation curve inCappellari (2023), but we
only use the first two parameters(A_V, delta). In this case,
thedustkeyword would be:gas_component = component > 0   # assuming stars = 0 and gas = 1
dust_gas = {"start": [0.1], "bounds": [[0, 8]], "component": gas_component}
dust_stars = {"start": [0.1, -0.1], "bounds": [[0, 4], [-1, 0.4]], "component": ~gas_component}
dust = [dust_gas, dust_stars]fixed:Boolean vector set toTruewhere a given kinematic parameter has to
be held fixed with the value given instart. This is an array, or
list, with the same dimensions asstart.EXAMPLE: We want to fit two kinematic components, with 4 moments for
the first component and 2 for the second. In this case:moments = [4, 2]
start = [[V1, sigma1, h3, h4], [V2, sigma2]]then we can held fixed e.g. the sigma (only) of both components using:fixed = [[0, 1, 0, 0], [0, 1]]NOTE: Setting a negativemomentsfor a kinematic component is
entirely equivalent to settingfixed = 1for all parameters of the
given kinematic component. In other words:moments = [-4, 2]is equivalent to:moments = [4, 2]
fixed = [[1, 1, 1, 1], [0, 0]]fraction: float, optionalThis keyword allows one to fix the ratio between the first two
kinematic components. This is a scalar defined as follows:fraction = np.sum(weights[component == 0])
         / np.sum(weights[component < 2])This is useful e.g. to try to kinematically decompose bulge and disk.The remaining kinematic components (component > 1) are left free,
and this allows, for example, to still include gas emission line
components.
More general linear constraints, for multiple kinematic components at
the same time, can be specified using the more general and flexibleconstr_templkeyword.ftol: float, optionalFractional tolerance for stopping the non-linear minimization (default
1e-4).gas_component:Boolean vector, of the same size ascomponent, set toTruewhere the givencomponentdescribes a gas emission line. If given,pPXFprovides thepp.gas_fluxandpp.gas_flux_errorin
output.EXAMPLE: In the common situation wherecomponent = 0are stellar
templates and the rest are gas emission lines, one will set:gas_component = component > 0This keyword is also used to plot the gas lines with a different color.gas_names:String array specifying the names of the emission lines (e.g.gas_names=["Hbeta","[OIII]",...], one per gas line. The length of
this vector must match the number of nonzero elements ingas_component. This vector is only used bypPXFto print the
line names on the console.gas_reddening: float, optionalSet this keyword to an initial estimate of the gas reddeningA_V >= 0to fit a positive gas reddening together with the kinematics and
the templates. This reddening is applied only to the gas templates,
namely to the templates with the corresponding element ofgas_component=True. The typical use of this keyword is when using a
single template for all the Balmer lines, with assumed intrinsic ratios
for the lines. In this way the gas fit becomes sensitive to reddening.
The fit assumes by default the extinction curve ofCalzetti et al. (2000)but any other prescription can be passed via thereddening_funckeyword.
By defaultgas_reddening=Noneand this parameter is not fitted.NOTE: This keyword is obsolete. I recommend using the more flexible and
generaldustkeyword instead.global_search: bool or dictionary, optionalSet toTrueto perform a global optimization of the nonlinear
parameters (kinematics) before starting the usual local optimizer.
Alternatively, one can pass via this keyword a dictionary of options
for the functionscipy.optimize.differential_evolution.
Default options areglobal_search={'tol':0.1, 'disp': 1}.Thefixedandtiedkeywords, as well asconstr_kinemare
properly supported when usingglobal_searchand one is encouraged
to use them to reduce parameters degeneracies.NOTE: This option is computationally intensive and completely
unnecessary in most situations. It shouldonlybe used in special
situations where there are obvious multiple localchi2minima. An
example is when fitting multiple stellar or gas kinematic components
with well-resolved velocity differences.IMPORTANT: when using this keyword it is recommendednotto use
multiplicative polynomials but only additive ones to avoid
unnecessarily long computation times. After converging to a global
solution, if desired one can repeat thepPXFfit with
multiplicative polynomials but without settingglobal_search.goodpixels: array_like of int with shape (n_pixels,), optionalInteger vector containing the indices of the good pixels in thegalaxyspectrum (in increasing order). Only these spectral pixels
are included in the fit.lam: array_like with shape (n_pixels,), optionalVector with therestframewavelength in Angstroms of every pixel in
the inputgalaxyspectrum. This keyword is required when using the
keywordsreddening,gas_reddeningordust.If one uses myppxf_util.log_rebinroutine to rebin the spectrum
before thepPXFfit, the wavelength can be obtained as:from ppxf.ppxf_util import log_rebin
specNew, ln_lam, velscale = log_rebin(lamRange, galaxy)
lam = np.exp(ln_lam)Whenlamis given, the wavelength is shown in the best-fitting
plot, instead of the pixels.lam_temp: array_like with shape (n_pixels_temp,), optionalVector with therestframewavelength in Angstroms of every pixel in
the inputtemplatesspectra.When both the wavelength of the templateslam_tempand of the
galaxylamare given, the templates are automatically truncated to
the minimal range required, for the adopted input velocity guess. In
this case it is unnecessary to use thevsystkeyword.Ifphotis also given, the final plot will include a best fitting
spectrum estimated using the fulltemplate, before truncation,
together with the photometric values and the truncated best fit to thegalaxyspectrum. This is useful to see the underlying best fitting
spectrum, in the wavelength range where only photometry (SED) was
fitted.linear: bool, optionalSet toTrueto keepallnonlinear parameters fixed andonlyperform a linear fit for the templates and additive polynomials
weights. The output solution is a copy of the input one and the errors
are zero.linear_method: {‘nnls’, ‘lsq_box’, ‘lsq_lin’, ‘cvxopt’} optionalMethod used for the solution of the linear least-squares subproblem to
fit for the templates weights (default ‘lsq_box’ fast box-constrained).The computational speed of the four alternative linear methods depends
on the size of the problem, with the default ‘lsq_box’ generally being
the fastest without linear inequality constraints. Note that ‘lsq_lin’
is included inppxf, while ‘cvxopt’ is an optional external
package. The ‘nnls’ option (the only one before v7.0) is generally
slower and for this reason is now deprecated.The inequality constraints inconstr_templare only supported
withlinear_method='lsq_lin'orlinear_method='cvxopt'.mask: array_like of bool with shape (n_pixels,), optionalBoolean vector of lengthgalaxy.sizespecifying withTruethe
pixels that should be included in the fit. This keyword is just an
alternative way of specifying thegoodpixels.mdegree: int, optionalDegree of themultiplicativeLegendre polynomial (with a mean of 1)
used to correct the continuum shape during the fit (default: 0). The
zero degree multiplicative polynomial (i.e. constant) is always
included in the fit as it corresponds to the multiplicative weights
assigned to the templates. Note that the computation time is longer
with multiplicative polynomials than with the samedegreeof
additive polynomials.method: {‘capfit’, ‘trf’, ‘dogbox’, ‘lm’}, optional.Algorithm to perform the non-linear minimization step.
The default ‘capfit’ is a novel linearly-constrained non-linear
least-squares optimization program, which combines the Sequential
Quadratic Programming and the Levenberg-Marquardt methods.
For a description of the other methods (‘trf’, ‘dogbox’, ‘lm’), see the
documentation ofscipy.optimize.least_squares.The use of linear constraints withconstr_kinemis only supported
with the defaultmethod='capfit'.moments:Order of the Gauss-Hermite moments to fit. Set this keyword to 4 to
fit[h3, h4]and to 6 to fit[h3, h4, h5, h6]. Note that in all
cases the G-H moments are fitted (non-linearly)togetherwith[V, sigma].Ifmoments=2ormomentsis not set then only[V, sigma]are
fitted.Ifmomentsis negative then the kinematics of the givencomponentare kept fixed to the input values.
NOTE: Setting a negativemomentsfor a kinematic component is
entirely equivalent to settingfixed = 1for all parameters of the
given kinematic component.EXAMPLE: We want to keep fixedcomponent = 0, which has a LOSVD
described by[V, sigma, h3, h4]and is modelled with 100 spectral
templates; At the same time, we fit[V, sigma]forcomponent = 1, which is described by 5 templates (this situation
may arise when fitting stellar templates with pre-determined stellar
kinematics, while fitting the gas emission).
We should give in input topPXFthe following parameters:component = [0]*100 + [1]*5   # --> [0, 0, ... 0, 1, 1, 1, 1, 1]
moments = [-4, 2]
start = [[V, sigma, h3, h4], [V, sigma]]phot: dictionary, optionalDictionary of parameters used to fit photometric data (SED fitting)
together with a spectrum. This is defined as follows:phot = {"templates": phot_templates, "galaxy": phot_galaxy,
        "noise": phot_noise, "lam": phot_lam}The keys of this dictionary are analogue to thepPXFparametersgalaxy,templates,noiseandlamfor the spectra.
However, the ones in this dictionary contain photometric data instead
of spectra and will generally consist just a few values (one per
photometric band) instead of thousands of elements like the spectra.
Specifically:phot_templates: array_like with shape (n_phot, n_templates) -
Mean flux of the templates in the observed photometric bands. This
array has the same number of dimension as thetemplatesinput
parameter. The same description applies. The only difference is that
the first dimension isn_photinstead ofn_pixels_temp. This
array can have 2-4 dimensions and all dimensions must match those of
the spectraltemplates, except for the first dimension. These
templates must have the same units and normalization as the spectraltemplates. If the spectral templates cover the ranges of the
photometric bands, and filter responsesrespare available, the
mean fluxes for each template can be computed as (e.g. equation A11
ofBessell & Murphy 2012):phot_template = Integrate[template*resp(lam)*lam, {lam, -inf, inf}]
              / Integrate[resp(lam)*lam, {lam, -inf, inf}]One can use the functionppxf_util.photometry_from_spectraas
an illustration of how to compute thephot_templates. This
function can be easily modified to include any additional filter.Alternatively, the fluxes may be tabulated by the authors of the SSP
models, for the same model parameters as the spectral SSP templates.
However, this can only be used for redshiftz ~ 0.phot_galaxy: array_like with shape (n_phot) - Observed
photometric measurements for the galaxy in linear flux units. These
values must be matched to the same spatial aperture used for the
spectra and they must have the same units (e.g.erg/(scm^2 A)).
This means that these values must be like the average fluxes one
would measure on the fitted galaxy spectrum if it was sufficiently
extended. One can think of these photometric values as some special
extra pixels to be added to the spectrum. The difference is that they
are not affected by the polynomials nor by the kinematics.phot_noise: array_like with shape (n_phot) -
Vector containing the1*sigmauncertainty of each photometric
measurement inphot_galaxy. One can change the normalization of
these uncertainties to vary the relative influence of the photometric
measurements versus the spectral fits.phot_lam: array_like with shape (n_phot) or (n_phot, n_templates)
- Meanrestframewavelength for each photometric band inphot_galaxy. This is only used to estimate reddening of each
band and to produce the plots. It can be computed from the system
response functionrespas (e.g. equation A17 ofBessell & Murphy 2012):phot_lam = Integrate[resp(lam)*lam^2, {lam, -inf, inf}]
         / Integrate[resp(lam)*lam, {lam, -inf, inf}]If spectral templates are available over the full extent of the
photometric bands, then one can compute a more accurate effective
wavelength for each template separately. In this casephot_lammust have the same dimensions asphot_templates.
For each templates the effective wavelength can be computed as
(e.g. equation A21 ofBessell & Murphy 2012):phot_lam = Integrate[template*resp(lam)*lam^2, {lam, -inf, inf}]
         / Integrate[template*resp(lam)*lam, {lam, -inf, inf}]plot: bool, optionalSet this keyword to plot the best fitting solution and the residuals
at the end of the fit.One can also call separately the class functionpp.plot()after the
call topp =ppxf(...).quiet: bool, optionalSet this keyword to suppress verbose output of the best fitting
parameters at the end of the fit.reddening: float, optionalSet this keyword to an initial estimate of the stellar reddeningA_V >= 0to fit a positive stellar reddening together with the
kinematics and the templates. This reddening is applied only to the
stellar templates (both spectral and photometric ones), namely to the
templates with the corresponding element ofgas_component=False, or
to all templates, ifgas_componentis not set. The fit assumes by
default the extinction curve ofCalzetti et al. (2000)but any other
prescription can be passed via thereddening_funckeyword.
By defaultreddening=Noneand this parameter is not fitted.NOTE: This keyword is obsolete. I recommend using the more flexible and
generaldustkeyword instead.regul: float, optionalIf this keyword is nonzero, the program applies first or second-order
linear regularization to theweightsduring thepPXFfit.
Regularization is done in one, two or three dimensions depending on
whether the array oftemplateshas two, three or four dimensions
respectively.
Largeregulvalues correspond to smootherweightsoutput. When
this keyword is nonzero the solution will be a trade-off between the
smoothness ofweightsand goodness of fit.Section 3.5 ofCappellari (2017)describes regularization.When fitting multiple kinematiccomponentthe regularization is
applied only to the firstcomponent = 0, while additional
components are not regularized. This is useful when fitting stellar
population together with gas emission lines. In that case, the SSP
spectral templates must be given first and the gas emission templates
are given last. In this situation, one has to use thereg_dimkeyword (below), to givepPXFthe dimensions of the population
parameters (e.g.n_age,n_metal,n_alpha). A usage example
is given in the fileppxf_example_population_gas_sdss.py.The effect of the regularization scheme is the following:Withreg_ord=1it enforces the numerical first derivatives
between neighbouring weights (in the 1-dim case) to be equal tow[j] - w[j+1] = 0with an errorDelta = 1/regul.Withreg_ord=2it enforces the numerical second derivatives
between neighbouring weights (in the 1-dim case) to be equal tow[j-1]- 2*w[j] + w[j+1] = 0with an errorDelta = 1/regul.It may be helpful to defineregul = 1/Deltaand think ofDeltaas the regularization error.IMPORTANT:Deltaneeds to be smaller but of the same order of
magnitude of the typicalweightsto play an effect on the
regularization. One quick way to achieve this is:Divide the fulltemplatesarray by a scalar in such a way that
the typical template has a median of one:templates /= np.median(templates)Do the same for the input galaxy spectrum:galaxy /= np.median(galaxy)In this situation, a sensible guess forDeltawill be a few
percent (e.g.Delta=0.01-->regul=100).Alternatively, for a more rigorous definition of the parameterregul:Perform an unregularized fit (regul=0) and then rescale the
inputnoisespectrum so that:Chi^2/DOF = Chi^2/goodPixels.size = 1.This is achieved by rescaling the inputnoisespectrum as:noise = noise*np.sqrt(Chi**2/DOF) = noise*np.sqrt(pp.chi2);Increasereguland iteratively redo thepPXFfit until theChi^2increases from the unregularized valueChi^2 = goodPixels.sizebyDeltaChi^2 = np.sqrt(2*goodPixels.size).The derived regularization corresponds to the maximum one still
consistent with the observations and the derived star formation history
will be the smoothest (minimum curvature or minimum variation) that is
still consistent with the observations.reg_dim: tuple, optionalWhen using regularization with more than one kinematic component (using
thecomponentkeyword), the regularization is only applied to the
first one (component=0). This is useful to fit the stellar
population and gas emissions together.In this situation, one has to use thereg_dimkeyword, to givepPXFthe dimensions of the population parameters (e.g.n_age,n_metal,n_alpha). One should create the initial array of
population templates like e.g.templates[n_pixels, n_age, n_metal, n_alpha]and define:reg_dim = templates.shape[1:]   # = [n_age, n_metal, n_alpha]The array of stellar templates is then reshaped into a 2-dim array as:templates = templates.reshape(templates.shape[0], -1)and the gas emission templates are appended as extra columns at the
end. An usage example is given inppxf_example_population_gas_sdss.py.When using regularization with a single component (thecomponentkeyword is not used, or contains identical values), the number of
population templates along different dimensions (e.g.n_age,n_metal,n_alpha) is inferred from the dimensions of thetemplatesarray and this keyword is not necessary.reg_ord: int, optionalOrder of the derivative that is minimized by the regularization.
The following two rotationally-symmetric estimators are supported:reg_ord=1: minimizes the integral over the weights of the squared
gradient:Grad[w] @ Grad[w].reg_ord=2: minimizes the integral over the weights of the squared
curvature:Laplacian[w]**2.sigma_diff: float, optionalQuadratic difference in km/s defined as:sigma_diff**2 = sigma_inst**2 - sigma_temp**2between the instrumental dispersion of the galaxy spectrum and the
instrumental dispersion of the template spectra.This keyword is useful when the templates have higher resolution than
the galaxy and they were not convolved to match the instrumental
dispersion of the galaxy spectrum. In this situation, the convolution
is done bypPXFwith increased accuracy, using an analytic Fourier
Transform.sky:vector containing the spectrum of the sky to be included in the fit, or
array of dimensionssky[n_pixels, nSky]containing different sky
spectra to add to the model of the observedgalaxyspectrum. Theskyhas to be log-rebinned as thegalaxyspectrum and needs to
have the same number of pixels.The sky is generally subtracted from the data before thepPXFfit.
However, for observations very heavily dominated by the sky spectrum,
where a very accurate sky subtraction is critical, it may be usefulnotto subtract the sky from the spectrum, but to include it in the
fit using this keyword.templates_rfft:When callingpPXFmany times with an identical set of templates,
one can use this keyword to pass the real FFT of the templates,
computed in a previouspPXFcall, stored in thepp.templates_rfftattribute. This keyword mainly exists to show
that there is no need for it…IMPORTANT: Use this keyword only if you understand what you are doing!tied:A list of string expressions. Each expression “ties” the parameter to
other free or fixed parameters.  Any expression involving constants and
the parameter arrayp[j]are permitted. Since they are totally
constrained, tied parameters are considered to be fixed; no errors are
computed for them.This is an array, or list of arrays, with the same dimensions asstart. In practice, for every element ofstartone needs to
specify either an empty string''implying that the parameter is
free, or a string expression involving some of the variablesp[j],
wherejrepresents the index of the flattened list of kinematic
parameters.EXAMPLE: We want to fit three kinematic components, with 4 moments for
the first component and 2 moments for the second and third (e.g. stars
and two gas components). In this case:moments = [4, 2, 2]
start = [[V1, sigma1, 0, 0], [V2, sigma2], [V3, sigma3]]then we can force the equality constraintV2 = V3as follows:tied = [['', '', '', ''], ['', ''], ['p[4]', '']]  # p[6] = p[4]or we can force the equality constraintsigma2 = sigma3as
follows:tied = [['', '', '', ''], ['', ''], ['', 'p[5]']]  # p[7] = p[5]One can also use more general formulas. For example one could constrainV3 = (V1 +V2)/2as well assigma1 = sigma2as follows:# p[5] = p[1]
# p[6] = (p[0] + p[4])/2
tied = [['', '', '', ''], ['', 'p[1]'], ['(p[0] + p[4])/2', '']]NOTE: One could in principle use thetiedkeyword to completely tie
the LOSVD of two kinematic components. However, this same effect is
more efficient achieved by assigning them to the same kinematic
component using thecomponentkeyword.trig:Settrig=Trueto use trigonometric series as an alternative to
Legendre polynomials, for both the additive and multiplicative
polynomials. Whentrig=Truethe fitted series below hasN = degree/2orN = mdegree/2:poly = A_0 + sum_{n=1}^{N} [A_n*cos(n*th) + B_n*sin(n*th)]IMPORTANT: The trigonometric series has periodic boundary conditions.
This is sometimes a desirable property, but this expansion is not as
flexible as the Legendre polynomials.velscale_ratio: int, optionalInteger. Gives the integerratio >= 1between thevelscaleof
thegalaxyand thetemplates. When this keyword is used, the
templates are convolved by the LOSVD at their native resolution, and
only subsequently are integrated over the pixels and fitted togalaxy. This keyword is generally unnecessary and mostly useful for
testing.Note that in realistic situations the uncertainty in the knowledge and
variations of the intrinsic line-spread function becomes the limiting
factor in recovering the LOSVD well belowvelscale.vsyst: float, optionalReference velocity inkm/s(default 0). The input initial guess and
the output velocities are measured with respect to this velocity. This
keyword can be used to account for the difference in the starting
wavelength of the templates and the galaxy spectrum as follows:vsyst = c*np.log(wave_temp[0]/wave_gal[0])As alternative to using this keyword, one can pass the wavelengthslamandlam_tempof both thegalaxyandtemplatesspectra. In that casevsystis computed automatically and should
not be given.The value assigned to this keyword iscrucialfor the two-sided
fitting. In this casevsystcan be determined from a previous
normal one-sided fit to the galaxy velocity profile. After that initial
fit,vsystcan be defined as the measured velocity at the galaxy
center. More accuratelyvsystis the value which has to be
subtracted to obtain a nearly anti-symmetric velocity profile at the
two opposite sides of the galaxy nucleus.IMPORTANT: this value is generallydifferentfrom the systemic
velocity one can get from the literature. Do not try to use that!Output ParametersStored as attributes of thepPXFclass:.apoly:Vector with the best fitting additive polynomial..bestfit:Vector with the best fitting model for the galaxy spectrum.
This is a linear combination of the templates, convolved with the best
fitting LOSVD, multiplied by the multiplicative polynomials and
with subsequently added polynomial continuum terms or sky components..chi2:The reducedchi^2(namelychi^2/DOF) of the fit, whereDOF = pp.dof(approximatelyDOF ~ pp.goodpixels.size).IMPORTANT: ifChi^2/DOFis not ~1 it means that the errors are not
properly estimated, or that the template is bad and it isnotsafe to
set thecleankeyword..dust:List of dictionaries, one for each fitted j-th dust component. For
each dictionary,dust_j["sol"]contains the best-fitting
parameter of the attenuation curve of that dust component. The other
field of the dictionary are copied from the input to the keyworddust..error:This variable contains a vector offormaluncertainty (1*sigma)
for the fitted parameters in the output vectorsol.
They are computed from the estimated covariance matrix of the standard
errors in the fitted parameters assuming it is diagonal at the minimum.
This option can be used when speed is essential, to obtain an order of
magnitude estimate of the uncertainties, but westronglyrecommend to
run bootstrapping simulations to obtain more reliable errors. In fact,
these errors can be severely underestimated in the region where the
penalty effect is most important (sigma < 2*velscale).These errors are meaningless unlessChi^2/DOF ~ 1. However if oneassumesthat the fit is good, a corrected estimate of the errors is:error_corr = error*sqrt(chi^2/DOF) = pp.error*sqrt(pp.chi2).IMPORTANT: when running Monte Carlo simulations to determine the error,
the penalty (bias) should be set to zero, or better to a very small
value. See Section 3.4 ofCappellari & Emsellem (2004)for an
explanation..gas_bestfit:Ifgas_component is not None, this attribute returns the
best-fitting gas emission-lines spectrum alone.
The best-fitting stellar spectrum alone can be computed asstars_bestfit = pp.bestfit - pp.gas_bestfit.gas_bestfit_templates:Ifgas_component is not None, this attribute returns the individual
best-fitting gas emission-lines templates as columns of an array.
Note thatpp.gas_bestfit = pp.gas_bestfit_templates.sum(1).gas_flux:Vector with the integrated flux (in counts) of all lines set asTruein the inputgas_componentkeyword. This is the flux of
individual gas templates, which may include multiple lines.
This implies that, if a gas template describes a doublet, the flux is
that of both lines. If the Balmer series is input as a single template,
this is the flux of the entire series.The returned fluxes are not corrected in any way and in particular, no
reddening correction is applied. In other words, the returned.gas_fluxshould be unchanged, within the errors, regardless of
whether reddening or multiplicative polynomials were fitted bypPXFor not.IMPORTANT:pPXFmakes no assumptions about the input flux units:
The returned.gas_fluxhas the same units and values one would
measure (with lower accuracy) by summing the pixels values, within the
given gas lines, on the continuum-subtracted input galaxy spectrum.
This implies that, if the spectrum is in units oferg/(scm^2 A),
the.gas_fluxreturned bypPXFshould be multiplied by the
pixel size in Angstrom at the line wavelength to obtain the integrated
line flux in units oferg/(scm^2).NOTE: If there is no gas reddening and each input gas template was
normalized tosum = 1, thenpp.gas_flux = pp.weights[pp.gas_component].When a gas template is identically zero within the fitted region, thenpp.gas_flux = pp.gas_flux_error = np.nan. The corresponding
components ofpp.gas_zero_templateare set toTrue. Thesenp.nanvalues are set at the end of the calculation to flag the
undefined values. These flags generally indicate that some of the gas
templates passed topPXFconsist of gas emission lines that fall
outside the fitted wavelength range or within a masked spectral region.
Thesenp.nandonotindicate numerical issues with the actualpPXFcalculation and the rest of thepPXFoutput is reliable..gas_flux_error:Formaluncertainty (1*sigma) for the quantitypp.gas_flux, in
the same units as the gas fluxes.This error is approximate as it ignores the covariance between the gas
flux and any non-linear parameter. Bootstrapping can be used for more
accurate errors.These errors are meaningless unlessChi^2/DOF ~ 1. However if oneassumesthat the fit is good, a corrected estimate of the errors is:gas_flux_error_corr = gas_flux_error*sqrt(chi^2/DOF)
                    = pp.gas_flux_error*sqrt(pp.chi2)..gas_mpoly:vector with the best-fitting gas reddening curve..gas_reddening:Best fittingA_Vvalue if thegas_reddeningkeyword is set.
This is especially useful when the Balmer series is input as a single
template with an assumed theoretically predicted decrement e.g. usingemission_lines(...,tie_balmer=True)inppxf.ppxf_utilto
compute the gas templates..gas_zero_template:vector of sizegas_component.sum()set toTruewhere
the gas template was identically zero within the fitted region.
For those gas componentspp.gas_flux = pp.gas_flux_error = np.nan.
These flags generally indicate that some of the gas templates passed topPXFconsist of gas emission lines that fall outside the fitted
wavelength range or within a masked spectral region..goodpixels:Integer vector containing the indices of the good pixels in the fit.
This vector is a copy of the inputgoodpixelsifclean = Falseotherwise it will be updated by removing the detected outliers..matrix:Predictionmatrix[n_pixels, degree + n_templates + n_sky]of the
linear system.pp.matrix[n_pixels, : degree]contains the additive polynomials ifdegree >= 0.pp.matrix[n_pixels, degree : degree + n_templates]contains the
stellar/gas templates convolved by the LOSVD, and multiplied by the
multiplicative polynomials ifmdegree > 0..mpoly:Best fitting multiplicative polynomial (or reddening curve whenreddeningis set)..mpolyweights:This is largely superseded by the.mpolyattribute above.Whenmdegree > 0this contains in output the coefficients of the
multiplicative Legendre polynomials of order1,2,...mdegree.
The polynomial can be explicitly evaluated as:from numpy.polynomial import legendre
x = np.linspace(-1, 1, len(galaxy))
mpoly = legendre.legval(x, np.append(1, pp.mpolyweights))Whentrig = Truethe polynomial is evaluated as:mpoly = pp.trigval(x, np.append(1, pp.mpolyweights)).phot_bestfit: array_like with shape (n_phot)Whenphotis given, then this attribute contains the best fitting
fluxes in the photometric bands given as input inphot_galaxy..plot: functionCall the method functionpp.plot()after the call topp =ppxf(...)to produce a plot of the best fit. This is an
alternative to callingpp =ppxf(...,plot=True).Use the commandpp.plot(gas_clip=True)to scale the plot based on
the stellar continuum alone, while allowing for the gas emission lines
to go outside the plotting region. This is useful to inspect the fit
to the stellar continuum, in the presence of strong gas emission lines.
This has effect only ifgas_component is not None.Use the commandpp.plot(...,spec=True)to include the galaxy
spectrum in the plot andpp.plot(...,phot=True)to include the
photometric measurements. For example, when fitting spectra and
photometry together, one can usepp.plot(phot=True, spec=False)to plot the photometry alone andpp.plot(phot=False, spec=True)to plot the spectrum alone. By default both the spectrum and photometry
are included in a single plot..polyweights:This is largely superseded by the.apolyattribute above.Whendegree >= 0contains the weights of the additive Legendre
polynomials of order0,1,...degree. The best-fitting additive
polynomial can be explicitly evaluated as:from numpy.polynomial import legendre
x = np.linspace(-1, 1, len(galaxy))
apoly = legendre.legval(x, pp.polyweights)Whentrig=Truethe polynomial is evaluated as:apoly = pp.trigval(x, pp.polyweights)When doing a two-sided fitting (see help forgalaxyparameter), the
additive polynomials are allowed to be different for the left and right
spectrum. In that case, the output weights of the additive polynomials
alternate between the first (left) spectrum and the second (right)
spectrum..reddening:Best fittingA_Vvalue if thereddeningkeyword is set..sol:Vector containing in output the parameters of the kinematics.Ifmoments=2this contains[Vel, Sigma]Ifmoments=4this contains[Vel, Sigma, h3, h4]Ifmoments=Nthis contains[Vel, Sigma,h3,...hN]When fitting multiple kinematiccomponent,pp.solcontains a
list with the solution for all different components, one after the
other, sorted bycomponent:pp.sol = [sol1,sol2,...].Velis the velocity,Sigmais the velocity dispersion,h3 - h6are the Gauss-Hermite coefficients. The model parameters
are fitted simultaneously.IMPORTANT: The precise relation between the outputpPXFvelocity
and redshift isVel = c*np.log(1 + z). See Section 2.3 ofCappellari (2017)for a detailed explanation.These are the default safety limits on the fitting parameters
(they can be changed using theboundskeyword):Velis constrained to be+/-2000km/s from the input guessvelscale/100 < Sigma < 1000km/s-0.3< [h3, h4,...]< 0.3(extreme value for real galaxies)In the case of two-sided LOSVD fitting the output values refer to the
first input galaxy spectrum, while the second spectrum will have by
construction kinematics parameters[-Vel,Sigma,-h3,h4,-h5,h6].
Ifvsystis nonzero (as required for two-sided fitting), then the
output velocity is measured with respect tovsyst..status:Contains the output status of the optimization. Positive values
generally represent success (the meaning ofstatusis defined as inscipy.optimize.least_squares)..weights:Receives the value of the weights by which each template was
multiplied to best fit the galaxy spectrum. The optimal template can be
computed with an array-vector multiplication:bestemp = templates @ weightsThese.weightsdo not include the weights of the additive
polynomials which are separately stored inpp.polyweights.When theskykeyword is usedweights[:n_templates]contains the
weights for the templates, whileweights[n_templates:]gives the
ones for the sky. In that case the best-fitting galaxy template and sky
are given by:bestemp = templates @ weights[:n_templates]
bestsky = sky @ weights[n_templates:]When doing a two-sided fitting (see help forgalaxyparameter)togetherwith theskykeyword, the sky weights are allowed to be
different for the left and right spectrum. In that case the output sky
weights alternate between the first (left) spectrum and the second
(right) spectrum.How to Set the Kinematic Penalty KeywordThebiaskeyword is only used ifmoments > 2, otherwise it is ignored.ThepPXFroutine can give sensible quick results with the defaultbiasparameter, however, like in any penalized/filtered/regularized
method, the optimal amount of penalization generally depends on the problem
under study.The general rule here is that the penalty should leave the line-of-sight
velocity-distribution (LOSVD) virtually unaffected, when it is well sampled
and the signal-to-noise ratio (S/N) is sufficiently high.EXAMPLE: If you expect a LOSVD with up to a highh4 ~ 0.2and your
adopted penalty (bias) biases the solution towards a much lowerh4 ~ 0.1, even when the measuredsigma > 3*velscaleand the S/N is
high, then you aremisusingthepPXFmethod!THE RECIPE: The following is a simple practical recipe for a sensible
determination of the penalty inpPXF:Choose a minimum(S/N)_minlevel for your kinematics extraction and
spatially bin your data so that there are no spectra below(S/N)_min;Perform a fit of your kinematicswithoutpenalty (keywordbias=0).
The solution will be noisy and may be affected by spurious solutions,
however, this step will allow you to check the expected average ranges
in the Gauss-Hermite parameters[h3, h4]for the galaxy under study;Perform a Monte Carlo simulation of your spectra, following e.g. the
includedppxf_example_montecarlo_simulation.pyroutine. Adopt asS/Nin the simulation the chosen value(S/N)_minand as input[h3, h4]the maximum representative values measured in the
non-penalizedpPXFfit of the previous step;Choose as the penalty (bias) thelargestvalue such that, forsigma > 3*velscale, the average difference delta between the output[h3, h4]and the input[h3, h4]is well within (e.g.delta ~ rms/3) the rms scatter of the simulated values (see an
example in Fig. 2 ofEmsellem et al. 2004).Problems with Your First Fit?Common problems with your firstpPXFfit are caused by incorrect
wavelength ranges or different velocity scales between galaxy and
templates. To quickly detect these problems try to overplot the (log
rebinned) galaxy and the template just before calling thepPXFprocedure.You can use something like the following Python lines while adjusting the
smoothing window and the pixels shift. If you cannot get a rough match
by eye it means something is wrong and it is unlikely thatpPXF(or any other program) will find a good match:importnumpyasnpimportmatplotlib.pyplotaspltfromscipyimportndimagesigma=2# Velocity dispersion in pixelsshift=-20# Velocity shift in pixelstemplate=np.roll(ndimage.gaussian_filter1d(template,sigma),shift)plt.plot(galaxy,'k')plt.plot(template*np.median(galaxy)/np.median(template),'r')LicenseOther/Proprietary LicenseCopyright (c) 2001-2024 Michele CappellariThis software is provided as is with no warranty. You may use it for
non-commercial purposes and modify it for personal or internal use, as long
as you include this copyright and disclaimer in all copies. You may not
redistribute the code.ChangelogV9.1.1: MC, Oxford, 18 January 2024Improvedsps_util.mass_to_light: Now it can calculate the stellar
mass-to-light ratio (M*/L) for any stellar population synthesis (SPS)
model, any filter, and any redshift, using the output weights frompPXF.
No need for pre-computed tables anymore.Addedppxf_util.solar_mag: A new function to get the absolute solar
magnitude in any photometric band, at any redshift, in either the AB or Vega
magnitude system.V9.0.2: MC, Oxford, 30 November 2023ppxf: Fixed bug in the automatic truncation of the template wavelength,
when usingboundstogether withlamandlam_temp.V9.0.1: MC, Oxford, 12 November 2023Replacedmiles_utilwithsps_util, a versatile and flexible function
that supports various stellar population synthesis (SPS) models. Currently, I
distribute (with permission) theE-MILES(Vazdekis+2016),GALAXEV(Bruzual & Charlot 2003) andfsps(Conroy+2009,2010) stellar population
templates. One can now change SPS by just modifying the filename.IMPORTANT: I no longer include the SPS models in thepPXFpackage, due to
file size constraints. One must download the SPS templates separately after
thepPXFinstallation, as demonstrated in all thepPXFexamples.I adapted all examples included in the package to use the newsps_util.ppxf.plot: New keywordlam_flamto plotlam*f(lam) = nu*f(nu).ppxf_util.synthetic_photometry: Converted from a function to a class.
Added.lam_pivattribute to compute the pivot wavelength of each filter.ppxf_util.varsmooth: Specialized faster convolution if sigma is a scalar.
while using the analytic Fourier transform to deal with undersampling.ppxf: Raised an error ifphotinput is not finite.V8.2.6: MC, Oxford, 6 July 2023capfit: Relaxed tolerance when checking initial guess feasibility.ppxf_util: Fixed program stop ingaussian_filter1dwhensig=0.
Thanks to Jesse Van de Sande (sydney.edu.au) for the report.V8.2.4: MC, Oxford, 12 May 2023ppxf: Fixed incorrectly switching tomethod='linear'when requesting
to fit stellar reddening alone, while all other parameters are fixed. Thanks
to Jong Chul Lee (kasi.re.kr) for a clear example of reproducing the bug.V8.2.3: MC, Oxford, 5 January 2023ppxf: Fixed program stop when fitting both sky spectra and gas emission
lines. Many thanks to Adarsh Ranjan (kasi.re.kr) for a clear example
of reproducing the problem and for the bug fix.ppxf: Raise an error ifvelscaleis not a scalar. Updated example
procedures. This fixes a program stop due to a change in NumPy 1.24.ppxf_util: Changedlog_rebinto returnvelscaleas a scalar.New example procedureppxf_example_gas_sdss_tied.pyto illustrate the
use of thetiedandconstr_kinemkeywords.V8.2.2: MC, Oxford, 11 October 2022ppxf: Fixed program stop withtiedorfixedkeywords and
nonlinear variables in addition to the kinematics. Thanks to Tobias Looser
(cam.ac.uk) for the report and fix.V8.2.1: MC, Oxford, 3 September 2022ppxf: New keyworddustwhich allows one to associate different
general attenuation functions to different sets of templates. This is useful
for example to apply three different attenuation functions to the young and
old stellar templates and to the gas emission lines respectively.ppxf: UsesA_Vinstead ofE(B-V)to parametrize attenuation, when
using the now-obsolete keywordsreddeningandgas_reddening.ppxf: New default functionattenuation(). However, one can now use
general attenuation functions with an arbitrary number of bound or fixed
parameters.ppxf: New internal functionsset_lam_input,set_gas_input,set_dust_input,set_phot_inputto organize the code.ppxf: Improved vertical scaling of default plots.ppxf: New keywordspp.plot(spec=True, phot=True)to plot only the
photometric or spectroscopic best fits respectively.ppxf_util: New functionvarsmoothfor Gaussian convolution with a
variable sigma. Unlike the similargaussian_filter1d, this new function
uses FFT and the analytic Fourier Transform of a Gaussian, likeppxf.ppxf_util: Included additional gas emission lines inemission_lines().capfit: Usescipy.optimize.linprog(method='highs')to find feasible
starting point inlsq_lin. This eliminates possible program stops in
certain situations with linearly dependent constraints.capfit: Set defaultlinear_method='lsq_lin'. This removes the need
to installcvxoptwhen usingconstr_kineminpPXF.V8.1.0: MC, Oxford, 10 June 2022ppxf: More accurate determination of the range for truncating the
templates when passing bothlam_tempandlam.ppxf: Check forlamorlam_tempconsistency withvelscaleand
return an error if they do not match.ppxf: Use micrometre units and denser tick labels for the logarithmic
wavelength axis.ppxf_util.synthetic_photometry: moved frommiles_utiland made it
independent of the stellar library. Adopted the same filter file format as
EAZY, FAST, HyperZ… for interoperability.
Allow passing a file with user-defined filter response functions.ppxf_util.log_rebin: Support irregularly sampled input wavelength.ppxf_util.gaussian_filter1d: New keywordmode='constant'ormode='wrap'.Updatedppxf_example_population_photometry.pyV8.0.2: MC, Oxford, 28 March 2022ppxf: Allow fitting photometric measurements (SED fitting) together with
a spectrum. This is implemented via the new keywordphotpassing a
dictionary of parameters.ppxf: plot photometric fit together with spectrum when fitting
photometry.ppxf: New keywordlam_tempto input the templates wavelength. When
this is given, together with the galaxy wavelengthlam, the templates are
automatically truncated to an optimal wavelength range, and it becomes
unnecessary to use the keywordvsyst.ppxf: Warning iftemplatesare> 2xlonger thangalaxy.ppxf: When fitting photometry one can input extended template spectra to
overplot the extrapolated best-fit spectrum together with the photometry.New demo file on photometric fittingppxf_example_population_photometry.py.miles_util.photometry_from_table: New example function to illustrate the
generation of the input photometric templates for thephotkeyword, using
tabulated SSP model magnitudes.miles_util.photometry_from_spectra: New example function to illustrate
the generation of photometric templates from the spectra using filter
responses.Replaced MILES spectral models of Vazdekis et al. (2010) with E-MILES models
of Vazdekis et al. (2016). Thanks to Alexandre Vazdekis (iac.es) for the
permission.Adapted allpPXFexamples to use the E-MILES templates.miles_util.miles: changed names of output wavelength.ln_lam_tempto
make clear they represent natural logarithms.miles_util.miles: setFWHM_gal=Noneto skip templates convolution.ppxf: Optionally performs global optimization of the non-linear
parameters. This is implemented via the new keywordglobal_search.ppxf: Allow the use of multiplicative polynomials together with
reddening.ppxf: Plot individual gas emission components in addition to their sum.ppxf: Updated docstring documentation for the new features.capfit: Completely removed tied/fixed variables from the optimization and
constraints. This improves the conditioning of the Jacobian and further
strengthens the robustness of the optimization.miles_util: fixedfluxarray mismatch when usingage_rangeormetal_range. Thanks to Davide Bevacqua (inaf.it) for the report.ppxf: Fixed program stop when fitting gas with a template length that is
not a multiple ofvelscale_ratio.V7.4.5: MC, Oxford, 16 July 2021ppxf: New keywordpp.plot(clip_gas=True)to ignore the gas emission
lines while determining the plotting ranges for the best-fitting model.miles_util: New attribute.fluxto convert between light-weighted
and mass-weighted stellar population quantities. Updated the corresponding
documentation in the docstring.ppxf_example_population_gas_sdss: Show how to convert between light-weighted
and mass-weighted stellar population using the newmiles.fluxattribute.ppxf_util.log_rebin: support fast log rebinning of all columns of 2-dim arrays.V7.4.4: MC, Oxford, 10 February 2021ppxf: More robust matrix scaling when using linear equality constraints
inconstr_templwithlinear_method='lsq_box'. Thanks to Shravan Shetty
(pku.edu.cn) for a detailed report and for testing my fix.V7.4.3: MC, Oxford, 21 December 2020capfit: Newlinear_methodkeyword to select betweencvxoptorlsq_lin, when using linear constraints, for cases where the latter stops.
Thecvxoptpackage must be installed when setting that option.ppxf: Adapted to usecapfitwithlinear_method='cvxopt'when
enforcing linear constraints on the kinematics withconstr_kinem.ppxf: Included NOTE in the documentation ofconstr_kinem.
All changes above were after detailed reports by Kyle Westfall (ucolick.org).V7.4.2: MC, Oxford, 9 October 2020ppxf: Corrected typo in example in the documentation ofconstr_templ.ppxf: Check thatconstr_templandconstr_kinemare dictionaries.
Thanks to Davide Bevacqua (unibo.it) for the feedback.V7.4.1: MC, Oxford, 11 September 2020capfit: Fixed possible infinite loop inlsq_boxandlsq_lin.
Thanks to Shravan Shetty (pku.edu.cn) for the detailed report and to both
him and Kyle Westfall (ucolick.org) for testing the fix.capfit: Use NumPy rather than the SciPy version oflinalg.lstsqto
avoid a current SciPy bug in the default criterion for rank deficiency.capfit: Renamedcondkeyword torcondfor consistency with NumPy.capfit: Passedrcondkeyword tocov_errfunction.ppxf: removedrcondkeyword incapfitcall. Use default instead.V7.4.0: MC, Oxford, 20 August 2020capfit: New functionlsq_linimplementing a linear least-squares
linearly constrained algorithm supporting rank-deficient matrices and allowing
for a starting guess.capfit: Removed thelsqlinprocedure which is superseded bylsq_lin.capfit: Renamedlsqboxtolsq_boxand revised its interface.ppxf: Modified to use the newlsq_linand the updatedlsq_boxfunctions.ppxf: More examples for theconstr_templandconstr_kinemkeywords.Set redshiftz = 0when one uncomments the lines to bring the spectrum to
the rest-frame inppxf_example_kinematics_sdss.py. Thanks to
Vaidehi S. Paliya (desy.de) for pointing out the inconsistency in my example.V7.3.0: MC, Oxford, 10 July 2020capfit: New functionlsqboximplementing a fast linear least-squares
box-constrained (bounds) algorithm which allows for a starting guess.
While testing I also discovered a major mistake in the current implementation
ofscipy.optimize.lsq_linear(my fix was later included in Scipy 1.6).ppxf: The newlinear_method='lsqbox'andlinear_method='cvxopt'now use an initial guess for the solution, which significantly speeds up the
kinematic fit with multiple templates. As an example, my procedureppxf_example_population_gas_sdssis now about 4 times faster with the newlinear_method='lsqbox'than with the legacylinear_method='nnls'.ppxf: Added support for linear equality constraints on the templatesconstr_templand for using the keywordfractionwith bothlinear_method='lsqbox'andlinear_method='nnls'.Printdegreeandmdegreewith the final results.Setlinear=Trueautomatically if the fit has no free non-linear parameters,
to avoid a program stop. Thanks to Shravan Shetty (pku.edu.cn) for the report.V7.2.1: MC, Oxford, 12 June 2020capfit: New input keywordcondfor Jacobian rank tolerance.capfit: Usebvlsto solve quadratic subproblem with onlybounds.ppxf: Setcond=1e-7incapfitcall, when using linear constraints.
Thecapfitrelated changes were due to detailed feedback by Kyle Westfall
(ucolick.org), to deal with situations with degenerate Jacobians, like when
there is no stellar continuum and one uses multiplicative polynomials.ppxf: Clarified documentation for.gas_zero_templateand the
corresponding warning message, after feedback by Laura Salo (umn.edu).V7.2.0: MC, Oxford, 4 May 2020Allow forlinear_method='cvxopt'when the optionalcvxoptpackage
is installed.V7.1.0: MC, Oxford, 30 April 2020Introduced newppxfkeywordlinear_method, and corresponding changes
in the code, to select between the old (‘nnls’) and the new (‘lsqlin’)
approach to the solution of the linear least-squares subproblem inppxf.
Thanks to Sam Vaughan (sydney.edu.au) for a convincing minimal example
illustrating the usefulness of this keyword.V7.0.1: MC, Oxford, 8 April 2020Support.gas_zero_templateandfractiontogether with other
equality constraints.Includednp.pad(...mode='constant')for backward compatibility with
Numpy 1.16. Thanks to Shravan Shetty (KIAA-PKU) for the suggestion.Fixrebin()not retaining the dimensionality of an input column-vector.
This resulted in a program stop with a single gas template andvelscale_ratio > 1. Thanks to Zhiyuan Ji (astro.umass.edu) for a clear
example reproducing the bug.capfit: New keywordcondforlsqlin.capfit: Relaxed assertion for inconsistent inequalities inlsqlinto avoid false positives. Thanks to Kyle Westfall (UCO Lick) for a detailed
bug report.V7.0.0: MC, Oxford, 10 January 2020capfit: New general linear least-squares optimization functionlsqlinwhich is now used to solve the quadratic subproblem.capfit: Allow for linear inequality/equality constraintsA_ineq,b_ineqandA_eq,b_eq.ppxf: Use (faster)capfit.lsqlinfor the linear fit.ppxf: Use updatedcapfit.capfitfor the non-linear optimization.ppxf: Allow for linear equalities/inequalities for both the template
weights and the kinematic parameters with theconstr_templandconstr_kinemoptional keywords.ppxf: Newset_linear_constraintsfunction.ppxf: Updated documentation.V6.7.17: MC, Oxford, 14 November 2019capfit: Written complete documentation.capfit: Improved print formatting.capfit: Return.messageattribute.capfit: Improvedxtolconvergence test.capfit: Only accept final move ifchi2decreased.capfit: Strictly satisfy bounds during Jacobian computation.V6.7.16: MC, Oxford, 12 June 2019capfit: Use only free parameters forxtolconvergence test.capfit: Describe in words convergence status with nonzeroverbose.capfit: Fixed program stop whenabs_stepis undefined.capfit: Fixed ignoring optionalmax_nfev.V6.7.15: MC, Oxford, 7 February 2019Removed unusedreimport.Removed Scipy’snext_fast_lenusage due to an issue with odd padding size.
Thanks to Eric Emsellem (ESO) for a clear example illustrating this rare and
subtle bug.V6.7.14: MC, Oxford, 27 November 2018Print the usedtiedparameters equalities, if any.Return.ndofattribute.Do not removefixedortiedparameters from the DOF calculation.
Thanks to Joanna Woo (Univ. of Victoria) for the correction.Replacednormalize,min_age,max_ageandmetalkeywords withnorm_range,age_rangeandmetal_rangeinppxf.miles_util.miles.FixedclockDeprecationWarningin Python 3.7.V6.7.13: MC, Oxford, 20 September 2018Expanded documentation ofreddeningandgas_reddening.
Thanks to Nick Boardman (Univ. Utah) for the feedback.capfitnow raises an error if one tries to tie parameters to themselves.
Thanks to Kyle Westfall (Univ. Santa Cruz) for the suggestion.capfituses Python 3.6 f-strings.V6.7.12: MC, Oxford, 9 July 2018Allow forvelscaleandvsystto be Numpy arrays rather than scalars.Improved criterion for when the Balmer series is within the fitted wavelength
range inppxf.ppxf_util.emission_lines. Thanks to Sam Vaughan
(Univ. of Oxford) for the feedback.Includedwidthkeyword inppxf.ppxf_util.determine_goodpixels.
Thanks to George Privon (Univ. of Florida) for the suggestion.Expanded.gas_fluxdocumentation.V6.7.11: MC, Oxford, 5 June 2018Formattedppxf.pydocstring in reStructuredText.Removed CHANGELOG from the code and placed it in a separate file.Modifiedsetup.pyto show help and CHANGELOG on PyPi page.Includedppxf.__version__.V6.7.8: MC, Oxford, 21 May 2018Moved package to the Python Package Index (PyPi).Dropped legacy Python 2.7 support.V6.7.6: MC, Oxford, 16 April 2018Changed imports for the conversion of pPXF to a package.
Thanks to Joe Burchett (Santa Cruz) for the suggestion.V6.7.5: MC, Oxford, 10 April 2018Fixed syntax error under Python 2.7.V6.7.4: MC, Oxford, 16 February 2018Fixed bug inreddening_cal00(). It only affected NIR lam > 1000 nm.V6.7.3: MC, Oxford, 8 February 2018Plot wavelength in nm instead of Angstrom, following IAU rules.Ensures each element ofstartis not longer than itsmoments.Removed underscore from internal function names.Includedftolkeyword.V6.7.2: MC, Oxford, 30 January 2018Included dunder names as suggested by Peter Weilbacher (Potsdam).Fixed wrong.gas_reddeningwhenmdegree > 0.Improved formatting of the documentation.V6.7.1: MC, Oxford, 29 November 2017Removed import ofmisc.factorial, deprecated in Scipy 1.0.V6.7.0: MC, Oxford, 6 November 2017Allow users to input identically zero gas templates while still
producing a stable NNLS solution. In this case, warn the user and set
the .gas_zero_template attribute. This situation can indicate an input
bug or a gas line that entirely falls within a masked region.Correctedgas_flux_errornormalization, when input not normalized.Return.gas_bestfit,.gas_mpoly,.mpolyand.apolyattributes.Do not multiply gas emission lines by polynomials, instead allow forgas_reddening(useful with tied Balmer emission lines).Useaxvspanto visualize masked regions in the plot.Fixed program stop withlinearkeyword.Introducedreddening_funckeyword.V6.6.4: MC, Oxford, 5 October 2017Check for NaN ingalaxyand check allboundshave two elements.Allowstartto be either a list or an array or vectors.V6.6.3: MC, Oxford, 25 September 2017Reduced bounds on multiplicative polynomials and clipped to positive
values. Thanks to Xihan Ji (Tsinghua University) for providing an
example of slightly negative gas emission lines, when the spectrum
contains essentially just noise.Improved visualization of masked pixels.V6.6.2: MC, Oxford, 15 September 2017Fixed program stop with a 2-dim template array and regularization.
Thanks to Adriano Poci (Macquarie University) for the clear report and
the fix.V6.6.1: MC, Oxford, 4 August 2017Included note on.gas_fluxoutput units. Thanks to Xihan Ji
(Tsinghua University) for the feedback.V6.6.0: MC, Oxford, 27 June 2017Print and return gas fluxes and errors, if requested, with the newgas_componentandgas_nameskeywords.V6.5.0: MC, Oxford, 23 June 2017ReplacedMPFITwithcapfitfor a Levenberg-Marquardt method with
fixed or tied variables, which rigorously accounts for box constraints.V6.4.2: MC, Oxford, 2 June 2017Fixed removal of bounds in solution, introduced in V6.4.1.
Thanks to Kyle Westfall (Univ. Santa Cruz) for reporting this.Includedmethodkeyword to use Scipy’sleast_squares()as an alternative to MPFIT.Force float division in pixel conversion ofstartandbounds.V6.4.1: MC, Oxford, 25 May 2017linear_fit()does not return unused status anymore, for
consistency with the corresponding change tocap_mpfit.V6.4.0: MC, Oxford, 12 May 2017Introducedtiedkeyword to tie parameters during fitting.Included discussion of formal errors of.weights.V6.3.2: MC, Oxford, 4 May 2017Fixed possible program stop introduced in V6.0.7 and consequently
removed unnecessary function_templates_rfft(). Many thanks to
Jesus Falcon-Barroso for a very clear and useful bug report!V6.3.1: MC, Oxford, 13 April 2017Fixed program stop when fitting two galaxy spectra with
reflection-symmetric LOSVD.V6.3.0: MC, Oxford, 30 March 2017Includedreg_ordkeyword to allow for both first and second-order
regularization.V6.2.0: MC, Oxford, 27 March 2017Improved curvature criterion for regularization whendim > 1.V6.1.0: MC, Oxford, 15 March 2017Introducedtrigkeyword to use a trigonometric series as
alternative to Legendre polynomials.V6.0.7: MC, Oxford, 13 March 2017Usenext_fast_len()for optimalrfft()zero padding.Included keywordgas_componentin the.plot()method, to
distinguish gas emission lines in best-fitting plots.Improved plot of residuals for noisy spectra.Simplified regularization implementation.V6.0.6: MC, Oxford, 23 February 2017Addedlinear_fit()andnonlinear_fit()functions to better
clarify the code structure. Includedtemplates_rfftkeyword.Updated documentation. Some code simplifications.V6.0.5: MC, Oxford, 21 February 2017Consistently use new format_output() function both with/without
thelinearkeyword. Added.statusattribute. Changes suggested by
Kyle Westfall (Univ. Santa Cruz).V6.0.4: MC, Oxford, 30 January 2017Re-introducedlinearkeyword to only perform a linear fit and
skip the non-linear optimization.V6.0.3: MC, Oxford, 1 December 2016Return usualChi**2/DOFinstead of Biweight estimate.V6.0.2: MC, Oxford, 15 August 2016Improved formatting of printed output.V6.0.1: MC, Oxford, 10 August 2016Allowmomentsto be an arbitrary integer.Allow for scalarmomentswith multiple kinematic components.V6.0.0: MC, Oxford, 28 July 2016Compute the Fourier Transform of the LOSVD analytically:Major improvement in velocity accuracy whensigma < velscale.Removedoversamplekeyword, which is now unnecessary.Removed limit on velocity shift of templates.Simplified FFT zero padding. Updated documentation.V5.3.3: MC, Oxford 24 May 2016Fixed Python 2 compatibility. Thanks to Masato Onodera (NAOJ).V5.3.2: MC, Oxford, 22 May 2016Backward compatibility change: allowstartto be smaller thanmoments. After feedback by Masato Onodera (NAOJ).Updated documentation ofboundsandfixed.V5.3.1: MC, Oxford, 18 May 2016Use wavelength in the plot when available. Makeplot()a class function.
Changes suggested and provided by Johann Cohen-Tanugi (LUPM).V5.3.0: MC, Oxford, 9 May 2016Includedvelscale_ratiokeyword to pass a set of templates with
higher resolution than the galaxy spectrum.Changedoversamplekeyword to require integers, not Booleans.V5.2.0: MC, Baltimore, 26 April 2016Includedbounds,fixedandfractionkeywords.V5.1.18: MC, Oxford, 20 April 2016Fixed deprecation warning in Numpy 1.11. Changed order from 1 to 3
during oversampling. Warn if sigma is under-sampled.V5.1.17: MC, Oxford, 21 January 2016Expanded explanation of the relationship between output velocity and redshift.V5.1.16: MC, Oxford, 9 November 2015Fixed potentially misleading typo in documentation ofmoments.V5.1.15: MC, Oxford, 22 October 2015Updated documentation. Thanks to Peter Weilbacher (Potsdam) for
corrections.V5.1.14: MC, Oxford, 19 October 2015Fixed deprecation warning in Numpy 1.10.V5.1.13: MC, Oxford, 24 April 2015Updated documentation.V5.1.12: MC, Oxford, 25 February 2015Usecolor=instead ofc=to avoid a new Matplotlib 1.4 bug.V5.1.11: MC, Sydney, 5 February 2015Reverted change introduced in V5.1.2. Thanks to Nora Lu”tzgendorf
for reporting problems withoversample.V5.1.10: MC, Oxford, 14 October 2014Fixed bug in saving output introduced in the previous version.V5.1.9: MC, Las Vegas Airport, 13 September 2014Pre-compute FFT and oversampling of templates. This speeds up the
calculation for very long or highly oversampled spectra. Thanks to
Remco van den Bosch for reporting situations where this optimization
may be useful.V5.1.8: MC, Utah, 10 September 2014Fixed program stop withreddeningkeyword. Thanks to Masatao
Onodera for reporting the problem.V5.1.7: MC, Oxford, 3 September 2014Relaxed requirement on input maximum velocity shift.Minor reorganization of the code structure.V5.1.6: MC, Oxford, 6 August 2014Catch an additional input error. Updated documentation for Python.
Included templatesmatrixin output. Modified plotting colours.V5.1.5: MC, Oxford, 21 June 2014Fixed deprecation warning.V5.1.4: MC, Oxford, 25 May 2014Support both Python 2.7 and Python 3.V5.1.3: MC, Oxford, 7 May 2014Allow for an input covariance matrix instead of an error spectrum.V5.1.2: MC, Oxford, 6 May 2014Replaced REBIN with INTERPOLATE + /OVERSAMPLE keyword. This is
to account for the fact that the Line Spread Function of the observed
galaxy spectrum already includes pixel convolution. Thanks to Mike
Blanton for the suggestion.V5.1.1: MC, Dallas Airport, 9 February 2014Fixed typo in the documentation ofnnls_flags.V5.1.0: MC, Oxford, 9 January 2014Allow for a different LOSVD for each template. Templates can be stellar or
can be gas emission lines. A pPXF version adapted for multiple kinematic
components existed for years. It was updated in JAN/2012 for the paper by
Johnston et al. (2013, MNRAS). This version merges those changes with the
public pPXF version, making sure that all previous pPXF options are still
supported.V5.0.1: MC, Oxford, 12 December 2013Minor cleaning and corrections.V5.0.0: MC, Oxford, 6 December 2013Translated from IDL into Python and tested against the original version.V4.6.6: MC, Paranal, 8 November 2013Uses CAP_RANGE to avoid potential naming conflicts.V4.6.5: MC, Oxford, 15 November 2012Expanded documentation of REGUL keyword.V4.6.4: MC, Oxford, 9 December 2011Increased oversampling factor to 30x, when the /OVERSAMPLE keyword
is used. Updated corresponding documentation. Thanks to Nora
Lu”tzgendorf for test cases illustrating errors in the recovered
velocity when the sigma is severely undersampled.V4.6.3: MC, Oxford 25 October 2011Do not change TEMPLATES array in output when REGUL is nonzero.
From the feedback of Richard McDermid.V4.6.2: MC, Oxford, 17 October 2011Included option for 3D regularization and updated documentation of
REGUL keyword.V4.6.1: MC, Oxford, 29 July 2011Use Coyote Graphics (http://www.idlcoyote.com/) by David W. Fanning.
The required routines are now included in NASA IDL Astronomy Library.V4.6.0: MC, Oxford, 12 April 2011Important fix to /CLEAN procedure: bad pixels are now properly
updated during the 3sigma iterations.V4.5.0: MC, Oxford, 13 April 2010Dramatic speed up in the convolution of long spectra.V4.4.0: MC, Oxford, 18 September 2009Introduced Calzetti et al. (2000) ppxf_REDDENING_CURVE function to
estimate the reddening from the fit.V4.3.0: MC, Oxford, 4 Mach 2009Introduced REGUL keyword to perform linear regularization of WEIGHTS
in one or two dimensions.V4.2.3: MC, Oxford, 27 November 2008Corrected error message for too big velocity shift.V4.2.2: MC, Windhoek, 3 July 2008Added keyword POLYWEIGHTS.V4.2.1: MC, Oxford, 17 May 2008Use LA_LEAST_SQUARES (IDL 5.6) instead of SVDC when fitting a single
template. Please let me know if you need to use pPXF with an older IDL
version.V4.2.0: MC, Oxford, 15 March 2008Introduced optional fitting of SKY spectrum. Many thanks to
Anne-Marie Weijmans for testing.V4.1.7: MC, Oxford, 6 October 2007Updated documentation with an important note on penalty determination.V4.1.6: MC, Leiden, 20 January 2006Print the number of nonzero templates. Do not print outliers in /QUIET mode.V4.1.5: MC, Leiden, 10 February 2005Verify that GOODPIXELS is monotonic and does not contain duplicated
values. After feedback from Richard McDermid.V4.1.4: MC, Leiden, 12 January 2005Make sure input NOISE is a positive vector.V4.1.3: MC, Vicenza, 30 December 2004Updated documentation.V4.1.2: MC, Leiden, 11 November 2004Handle special case where a single template without additive
polynomials is fitted to the galaxy.V4.1.1: MC, Leiden, 21 September 2004Increased maximum number of iterations ITMAX in BVLS. Thanks to
Jesus Falcon-Barroso for reporting problems.Introduced error message when velocity shift is too big.Corrected output when MOMENTS=0.V4.1.0: MC, Leiden, 3 September 2004Corrected implementation of two-sided fitting of the LOSVD. Thanks
to Stefan van Dongen for reporting problems.V4.0.0: MC, Vicenza, 16 August 2004Introduced optional two-sided fitting assuming a reflection
symmetric LOSVD for two input spectra.V3.7.3: MC, Leiden, 7 August 2004Corrected bug: keyword ERROR was returned in pixels instead of km/s.Decreased lower limit on fitted dispersion. Thanks to Igor V. Chilingarian.V3.7.2: MC, Leiden, 28 April 2004Corrected program stop after fit when MOMENTS=2. The bug was introduced in V3.7.0.V3.7.1: MC, Leiden, 31 March 2004Updated documentation.V3.7.0: MC, Leiden, 23 March 2004Revised implementation of MDEGREE option. Nonlinear implementation:
straightforward, robust, but slower.V3.6.0: MC, Leiden, 19 March 2004Added MDEGREE option for multiplicative polynomials. Linear implementation:
fast, works well in most cases, but can fail in certain cases.V3.5.0: MC, Leiden, 11 December 2003Included /OVERSAMPLE option.V3.4.7: MC, Leiden, 8 December 2003First released version.V1.0.0: Leiden, 10 October 2001Created by Michele Cappellari.