def collapse_gaussfit(cube,axis=2):
    std_coll = cube.std(axis=axis)
    mean_std = median(std_coll.ravel())
    if axis > 0:
        cube = cube.swapaxes(0,axis)
    width_arr = zeros(cube.shape[1:])
    amp_arr = zeros(cube.shape[1:])
    chi2_arr = zeros(cube.shape[1:])
    offset_arr = zeros(cube.shape[1:])
    starttime = time.time()
    print(cube.shape)
    print("Fitting a total of %i spectra with peak signal above %f" % ((cube.max(axis=0) > mean_std).sum(),mean_std))
    for i in xrange(cube.shape[1]):
        t0 = time.time()
        nspec = (cube[:,i,:].max(axis=0) > mean_std).sum()
        print("Working on row %d with %d spectra to fit" % (i,nspec), end=' ')
        for j in xrange(cube.shape[2]):
            if cube[:,i,j].max() > mean_std:
                pars = return_param(cube[:,i,j])
                width_arr[i,j] = pars[1]
                chi2_arr[i,j] = sum(( gerr(cube[:,i,j])(pars) )**2) 
                offset_arr[i,j] = pars[0]
                amp_arr[i,j] = pars[2]
            else: 
                width_arr[i,j] = numpy.nan
                chi2_arr[i,j] = numpy.nan
                offset_arr[i,j] = numpy.nan
                amp_arr[i,j] = numpy.nan
        dt = time.time()-t0
        if nspec > 0:
            print("in %f seconds (average: %f)" % (dt,dt/float(nspec)))
    print("Total time %f seconds" % (time.time()-starttime))

    return width_arr,offset_arr,amp_arr,chi2_arr
Beispiel #2
0
    def n_lorentzian(pars=None,a=None,dx=None,width=None):
        """
        Returns a function that sums over N lorentzians, where N is the length of
        a,dx,sigma *OR* N = len(pars) / 3

        The background "height" is assumed to be zero (you must "baseline" your
        spectrum before fitting)

        pars  - a list with len(pars) = 3n, assuming a,dx,sigma repeated
        dx    - offset (velocity center) values
        width - line widths (Lorentzian FWHM)
        a     - amplitudes
        """
        if len(pars) % 3 == 0:
            a = [pars[ii] for ii in xrange(0,len(pars),3)]
            dx = [pars[ii] for ii in xrange(1,len(pars),3)]
            width = [pars[ii] for ii in xrange(2,len(pars),3)]
        elif not(len(dx) == len(width) == len(a)):
            raise ValueError("Wrong array lengths! dx: %i  width %i  a: %i" % (len(dx),len(width),len(a)))

        def L(x):
            v = numpy.zeros(len(x))
            for i in range(len(dx)):
                v += a[i] / (2*pi) * w / ((x-dx)**2 + (w/2.0)**2)
            return v
        return L
Beispiel #3
0
    def n_gaussian(self, pars=None,a=None,dx=None,sigma=None):
        """
        Returns a function that sums over N gaussians, where N is the length of
        a,dx,sigma *OR* N = len(pars) / 3

        The background "height" is assumed to be zero (you must "baseline" your
        spectrum before fitting)

        pars  - a list with len(pars) = 3n, assuming a,dx,sigma repeated
        dx    - offset (velocity center) values
        sigma - line widths
        a     - amplitudes
        """
        if len(pars) % 3 == 0:
            a = [pars[ii] for ii in xrange(0,len(pars),3)]
            dx = [pars[ii] for ii in xrange(1,len(pars),3)]
            sigma = [pars[ii] for ii in xrange(2,len(pars),3)]
        elif not(len(dx) == len(sigma) == len(a)):
            raise ValueError("Wrong array lengths! dx: %i  sigma: %i  a: %i" % (len(dx),len(sigma),len(a)))

        def g(x):
            v = numpy.zeros(len(x))
            for ii in range(len(pars)/3):
                v += a[ii] * numpy.exp( - ( x - dx[ii] )**2 / (2.0*sigma[ii]**2) )
            return v
        return g
Beispiel #4
0
    def n_gaussian(self, pars=None, a=None, dx=None, sigma=None):
        """
        Returns a function that sums over N gaussians, where N is the length of
        a,dx,sigma *OR* N = len(pars) / 3

        The background "height" is assumed to be zero (you must "baseline" your
        spectrum before fitting)

        pars  - a list with len(pars) = 3n, assuming a,dx,sigma repeated
        dx    - offset (velocity center) values
        sigma - line widths
        a     - amplitudes
        """
        if len(pars) % 3 == 0:
            a = [pars[ii] for ii in xrange(0, len(pars), 3)]
            dx = [pars[ii] for ii in xrange(1, len(pars), 3)]
            sigma = [pars[ii] for ii in xrange(2, len(pars), 3)]
        elif not (len(dx) == len(sigma) == len(a)):
            raise ValueError("Wrong array lengths! dx: %i  sigma: %i  a: %i" %
                             (len(dx), len(sigma), len(a)))

        def g(x):
            v = numpy.zeros(len(x))
            for ii in range(len(pars) / 3):
                v += a[ii] * numpy.exp(-(x - dx[ii])**2 / (2.0 * sigma[ii]**2))
            return v

        return g
Beispiel #5
0
def collapse_gaussfit(cube, axis=2):
    std_coll = cube.std(axis=axis)
    mean_std = median(std_coll.ravel())
    if axis > 0:
        cube = cube.swapaxes(0, axis)
    width_arr = zeros(cube.shape[1:])
    amp_arr = zeros(cube.shape[1:])
    chi2_arr = zeros(cube.shape[1:])
    offset_arr = zeros(cube.shape[1:])
    starttime = time.time()
    print cube.shape
    print "Fitting a total of %i spectra with peak signal above %f" % (
        (cube.max(axis=0) > mean_std).sum(), mean_std)
    for i in xrange(cube.shape[1]):
        t0 = time.time()
        nspec = (cube[:, i, :].max(axis=0) > mean_std).sum()
        print "Working on row %d with %d spectra to fit" % (i, nspec),
        for j in xrange(cube.shape[2]):
            if cube[:, i, j].max() > mean_std:
                pars = return_param(cube[:, i, j])
                width_arr[i, j] = pars[1]
                chi2_arr[i, j] = sum((gerr(cube[:, i, j])(pars))**2)
                offset_arr[i, j] = pars[0]
                amp_arr[i, j] = pars[2]
            else:
                width_arr[i, j] = numpy.nan
                chi2_arr[i, j] = numpy.nan
                offset_arr[i, j] = numpy.nan
                amp_arr[i, j] = numpy.nan
        dt = time.time() - t0
        if nspec > 0:
            print "in %f seconds (average: %f)" % (dt, dt / float(nspec))
    print "Total time %f seconds" % (time.time() - starttime)

    return width_arr, offset_arr, amp_arr, chi2_arr
Beispiel #6
0
    def n_lorentzian(pars=None, a=None, dx=None, width=None):
        """
        Returns a function that sums over N lorentzians, where N is the length of
        a,dx,sigma *OR* N = len(pars) / 3

        The background "height" is assumed to be zero (you must "baseline" your
        spectrum before fitting)

        pars  - a list with len(pars) = 3n, assuming a,dx,sigma repeated
        dx    - offset (velocity center) values
        width - line widths (Lorentzian FWHM)
        a     - amplitudes
        """
        if len(pars) % 3 == 0:
            a = [pars[ii] for ii in xrange(0, len(pars), 3)]
            dx = [pars[ii] for ii in xrange(1, len(pars), 3)]
            width = [pars[ii] for ii in xrange(2, len(pars), 3)]
        elif not (len(dx) == len(width) == len(a)):
            raise ValueError("Wrong array lengths! dx: %i  width %i  a: %i" %
                             (len(dx), len(width), len(a)))

        def L(x):
            v = numpy.zeros(len(x))
            for i in range(len(dx)):
                v += a[i] / (2 * pi) * w / ((x - dx)**2 + (w / 2.0)**2)
            return v

        return L
def poly_fitter(order=1):
    """
    Generator for polynomial fitter class
    """

    myclass =  model.SpectralModel(polymodel, order+1,
            parnames=['coeff%i' % ii for ii in xrange(order+1)], 
            parlimited=[(False,False) for ii in xrange(order+1)], 
            parlimits=[(0,0) for ii in xrange(order+1)], 
            shortvarnames=['C%i' % ii for ii in xrange(order+1)]
            )
    myclass.__name__ = "polymodel"
    
    return myclass
Beispiel #8
0
def poly_fitter(order=1):
    """
    Generator for polynomial fitter class
    """

    myclass = model.SpectralModel(
        polymodel,
        order + 1,
        parnames=['coeff%i' % ii for ii in xrange(order + 1)],
        parlimited=[(False, False) for ii in xrange(order + 1)],
        parlimits=[(0, 0) for ii in xrange(order + 1)],
        shortvarnames=['C%i' % ii for ii in xrange(order + 1)])
    myclass.__name__ = "polymodel"

    return myclass
def get_chunks(num_items, chunk):
    '''
    Parameters
    ----------
    num_items : int
        Number of total items.
    chunk : int
        Size of chunks

    Returns
    -------
    chunks : list of np.ndarray
        List of channels in chunks of the given size.
    '''
    items = np.arange(num_items)

    if num_items == chunk:
        return [items]

    chunks = \
        np.array_split(items,
                       [chunk * i for i in xrange(int(num_items / chunk))])
    if chunks[-1].size == 0:
        # Last one is empty
        chunks = chunks[:-1]
    if chunks[0].size == 0:
        # First one is empty
        chunks = chunks[1:]

    return chunks
Beispiel #10
0
    def tableprint(self, item_length=15, numbered=True):
        """
        Print data in table-friendly format

        Parameters
        ----------
        item_length : int
            Number of characters per item printed
        numbered : bool
            Are the parameters numbered?  In pyspeckit, they will always be,
            but this was included for compatibility with generic fitters
        """
        stripped_names = list(
            set([par.parname.strip("0123456789") for par in self]))

        nlines = len(self.n) / len(stripped_names)

        strformat = "%" + str(item_length) + "s"
        fltformat = "%" + str(item_length) + "g"

        print(" ".join([strformat % name for name in stripped_names]))
        if numbered:
            for ii in xrange(nlines):
                print(" ".join([
                    fltformat % (self[name + "%i" % ii].value)
                    for name in stripped_names
                ]))
        else:
            print(" ".join(
                [fltformat % (self[name].value) for name in stripped_names]))
def get_chunks(num_items, chunk):
    '''
    Parameters
    ----------
    num_items : int
        Number of total items.
    chunk : int
        Size of chunks

    Returns
    -------
    chunks : list of np.ndarray
        List of channels in chunks of the given size.
    '''
    items = np.arange(num_items)

    if num_items == chunk:
        return [items]

    chunks = \
        np.array_split(items,
                       [chunk * i for i in xrange(int(num_items / chunk))])
    if chunks[-1].size == 0:
        # Last one is empty
        chunks = chunks[:-1]
    if chunks[0].size == 0:
        # First one is empty
        chunks = chunks[1:]

    return chunks
Beispiel #12
0
    def tableprint(self, item_length=15, numbered=True):
        """
        Print data in table-friendly format

        Parameters
        ----------
        item_length : int
            Number of characters per item printed
        numbered : bool
            Are the parameters numbered?  In pyspeckit, they will always be,
            but this was included for compatibility with generic fitters
        """
        stripped_names = list(set([par.parname.strip("0123456789") for par in self]))

        nlines = len(self.n) / len(stripped_names)

        strformat = "%" + str(item_length) + "s"
        fltformat = "%" + str(item_length) + "g"

        print(" ".join([strformat % name for name in stripped_names]))
        if numbered:
            for ii in xrange(nlines):
                print(" ".join([fltformat % (self[name+"%i" % ii].value) for
                                name in stripped_names]))
        else:
            print(" ".join([fltformat % (self[name].value) for name in
                            stripped_names]))
Beispiel #13
0
def plane_smooth(cube,cubedim=0,parallel=True,numcores=None,**kwargs):
    """
    parallel-map the smooth function

    Parameters
    ----------
    parallel: bool
        defaults True.  Set to false if you want serial (for debug purposes?)
    numcores: int
        pass to parallel_map (None = use all available)
    """
    if not smoothOK:
        return

    if cubedim != 0:
        cube = cube.swapaxes(0,cubedim)

    cubelist = [cube[ii,:,:] for ii in xrange(cube.shape[0])]

    Psmooth = lambda C: smooth(C,**kwargs)

    if parallel:
        smoothcube = array(parallel_map(Psmooth,cubelist,numcores=numcores))
    else:
        smoothcube = array(map(Psmooth,cubelist))

    if cubedim != 0:
        smoothcube = smoothcube.swapaxes(0,cubedim)

    return smoothcube
Beispiel #14
0
def plane_smooth(cube, cubedim=0, parallel=True, numcores=None, **kwargs):
    """
    parallel-map the smooth function

    Parameters
    ----------
    parallel: bool
        defaults True.  Set to false if you want serial (for debug purposes?)
    numcores: int
        pass to parallel_map (None = use all available)
    """
    if not smoothOK:
        return

    if cubedim != 0:
        cube = cube.swapaxes(0, cubedim)

    cubelist = [cube[ii, :, :] for ii in xrange(cube.shape[0])]

    Psmooth = lambda C: smooth(C, **kwargs)

    if parallel:
        smoothcube = array(parallel_map(Psmooth, cubelist, numcores=numcores))
    else:
        smoothcube = array(map(Psmooth, cubelist))

    if cubedim != 0:
        smoothcube = smoothcube.swapaxes(0, cubedim)

    return smoothcube
Beispiel #15
0
 def clear(self, nbytes):
     """
     Write nbytes of zeros.
     """
     blank_data = b'\0' * self.block_size
     for i in xrange(0, nbytes, self.block_size):
         length = min(nbytes - i, self.block_size)
         self.write(blank_data[:length])
Beispiel #16
0
 def clear(self, nbytes):
     """
     Write nbytes of zeros.
     """
     blank_data = b'\0' * self.block_size
     for i in xrange(0, nbytes, self.block_size):
         length = min(nbytes - i, self.block_size)
         self.write(blank_data[:length])
Beispiel #17
0
 def _array_fromfile(fd, size):
     chunk_size = 1024 ** 3
     if size < chunk_size:
         return np.fromfile(fd, dtype=np.uint8, count=size)
     else:
         array = np.empty(size, dtype=np.uint8)
         for beg in xrange(0, size, chunk_size):
             end = min(size, beg + chunk_size)
             array[beg:end] = np.fromfile(fd, dtype=np.uint8, count=end - beg)
         return array
Beispiel #18
0
 def firstclick_guess(self):
     """
     Initialize self.guesses
     """
     self.Spectrum.plotter.axis.set_autoscale_on(False)
     if self.guesses is None:
         self.guesses = []
     elif len(self.guesses) > 0:
         for ii in xrange(len(self.guesses)):
             self.guesses.pop()
Beispiel #19
0
 def _array_fromfile(fd, size):
     chunk_size = 1024 ** 3
     if size < chunk_size:
         return np.fromfile(fd, dtype=np.uint8, count=size)
     else:
         array = np.empty(size, dtype=np.uint8)
         for beg in xrange(0, size, chunk_size):
             end = min(size, beg + chunk_size)
             array[beg:end] = np.fromfile(fd, dtype=np.uint8, count=end - beg)
         return array
Beispiel #20
0
    def compute_luminosity(self, pars):
        """
        Determine luminosity of line (need distance and flux units).
        """

        lum = 0
        niter = (len(pars) / 3)
        for i in xrange(int(niter)):
            lum += self.compute_flux(pars) * 4. * np.pi * self.d**2
        return lum
Beispiel #21
0
    def compute_luminosity(self, pars):
        """
        Determine luminosity of line (need distance and flux units).
        """

        lum = 0
        niter = (len(pars) / 3)
        for i in xrange(int(niter)):
            lum += self.compute_flux(pars) * 4. * np.pi * self.d**2
        return lum
Beispiel #22
0
 def firstclick_guess(self):
     """
     Initialize self.guesses
     """
     self.Spectrum.plotter.axis.set_autoscale_on(False)
     if self.guesses is None:
         self.guesses = []
     elif len(self.guesses) > 0:
         for ii in xrange(len(self.guesses)):
             self.guesses.pop()
Beispiel #23
0
    def compute_amplitude(self, pars):
        """
        Calculate amplitude of emission line.  Should be easy - add multiple components if they exist.
        Currently assumes multiple components have the same centroid.
        """

        amp = 0
        niter = (len(pars) / 3)
        for i in xrange(int(niter)):
            amp += pars[3 * i]
        return amp * self.fluxnorm
Beispiel #24
0
def formaldehyde_pyradex(xarr,
                         density=4,
                         column=13,
                         temperature=20,
                         xoff_v=0.0,
                         opr=1.0,
                         width=1.0,
                         tbackground=2.73,
                         grid_vwidth=1.0,
                         debug=False,
                         verbose=False,
                         **kwargs):
    """
    Use a grid of RADEX-computed models to make a model line spectrum

    The RADEX models have to be available somewhere.
    OR they can be passed as arrays.  If as arrays, the form should be:
    texgrid = ((minfreq1,maxfreq1,texgrid1),(minfreq2,maxfreq2,texgrid2))

    xarr must be a SpectroscopicAxis instance
    xoff_v, width are both in km/s

    grid_vwidth is the velocity assumed when computing the grid in km/s
    this is important because tau = modeltau / width (see, e.g.,
    Draine 2011 textbook pgs 219-230)
    """

    raise NotImplementedError("Not done yet.")
    import pyradex

    # Convert X-units to frequency in GHz
    xarr = xarr.as_unit('Hz', quiet=True)

    tb_nu_cumul = np.zeros(len(xarr))

    R = pyradex.Radex(
        molecule='oh2co-h2',
        column=column,
        temperature=temperature,
        density=10**density,
        tbackground=tbackground,
    )

    spec = np.sum(
        [(formaldehyde_vtau(xarr,
                            Tex=float(tex[ii]),
                            tau=float(tau[ii]),
                            xoff_v=xoff_v,
                            width=width,
                            **kwargs) * (xarr.as_unit('GHz') > minfreq[ii]) *
          (xarr.as_unit('GHz') < maxfreq[ii])) for ii in xrange(len(tex))],
        axis=0)

    return spec
Beispiel #25
0
 def read_blocks(self, size):
     """
     Read ``size`` bytes of data from the file, one block at a
     time.  The result is a generator where each value is a bytes
     object.
     """
     i = 0
     for i in xrange(0, size - self._blksize, self._blksize):
         yield self.read(self._blksize)
     if i < size:
         yield self.read(size - i)
Beispiel #26
0
    def compute_amplitude(self, pars):
        """
        Calculate amplitude of emission line.  Should be easy - add multiple components if they exist.
        Currently assumes multiple components have the same centroid.
        """

        amp = 0
        niter = (len(pars) / 3)
        for i in xrange(int(niter)):
            amp += pars[3 * i]
        return amp * self.fluxnorm
Beispiel #27
0
    def compute_flux(self, pars):
        """
        Calculate integrated flux of emission line.  Works for multi-component fits too.  Unnormalized.
        """

        flux = 0
        niter = (len(pars) / 3)
        assert niter == int(niter)
        for i in xrange(int(niter)):
            flux += np.sqrt(2. * np.pi) * pars[3 * i] * abs(pars[2 + 3 * i])

        return flux * self.fluxnorm
Beispiel #28
0
    def compute_flux(self, pars):
        """
        Calculate integrated flux of emission line.  Works for multi-component fits too.  Unnormalized.
        """

        flux = 0
        niter = (len(pars) / 3)
        assert niter == int(niter)
        for i in xrange(int(niter)):
            flux += np.sqrt(2. * np.pi) * pars[3 * i] * abs(pars[2 + 3 * i])

        return flux * self.fluxnorm
Beispiel #29
0
    def n_formaldehyde(self, pars=None, fittau=False, **kwargs):
        """
        Returns a function that sums over N ammonia line profiles, where N is the length of
        tkin,tex,Ntot,width,xoff_v,fortho *OR* N = len(pars) / 6

        The background "height" is assumed to be zero (you must "baseline" your
        spectrum before fitting)

        pars  - a list with len(pars) = 6n, assuming tkin,tex,Ntot,width,xoff_v,fortho repeated
        """
        if len(pars) % 6 == 0:
            tkin = [pars[ii] for ii in xrange(0,len(pars),6)]
            tex = [pars[ii] for ii in xrange(1,len(pars),6)]
            Ntot = [pars[ii] for ii in xrange(2,len(pars),6)]
            width = [pars[ii] for ii in xrange(3,len(pars),6)]
            xoff_v = [pars[ii] for ii in xrange(4,len(pars),6)]
            fortho = [pars[ii] for ii in xrange(5,len(pars),6)]
        elif not(len(tkin) == len(tex) == len(Ntot) == len(xoff_v) == len(width) == len(fortho)):
            raise ValueError("Wrong array lengths!")

        modelkwargs = kwargs.copy()
        def L(x):
            v = np.zeros(len(x))
            for i in range(len(tkin)):
                modelkwargs.update({'tkin':tkin[i], 'tex':tex[i],
                        'width':width[i], 'xoff_v':xoff_v[i],
                        'fortho':fortho[i]})
                if fittau:
                    modelkwargs.update({'tau11':Ntot[i]})
                else:
                    modelkwargs.update({'Ntot':Ntot[i]})
                v += self.ammonia(x,**modelkwargs)
            return v
        return L
Beispiel #30
0
def formaldehyde_mm_despotic(xarr,
                             temperature=25,
                             column=13,
                             density=4,
                             xoff_v=0.0,
                             width=1.0,
                             grid_vwidth=1.0,
                             h2co_303_202=None,
                             h2co_322_221=None,
                             h2co_321_220=None,
                             debug=False,
                             verbose=False,
                             **kwargs):
    """
    Fitter to p-H2CO using despotic grids.  Requires building grids and passing in 
    functions for interpolating the h2co transition optical depth and 
    excitation temperatures. 
    """

    Tex303_202, tau303_202 = h2co_303_202(logdensity=density,
                                          logcolumn=column,
                                          temperature=temperature,
                                          sigmav=width)

    Tex322_221, tau322_221 = h2co_322_221(logdensity=density,
                                          logcolumn=column,
                                          temperature=temperature,
                                          sigmav=width)

    Tex321_220, tau321_220 = h2co_321_220(logdensity=density,
                                          logcolumn=column,
                                          temperature=temperature,
                                          sigmav=width)

    tex = [Tex303_202, Tex322_221, Tex321_220]
    tau = [tau303_202, tau322_221, tau321_220]
    minfreq = [218.15, 218.40, 218.7]
    maxfreq = [218.25, 218.55, 218.8]
    spec = np.sum([(formaldehyde_mm_vtau(xarr,
                                         Tex=float(tex[ii]),
                                         tau=float(tau[ii]),
                                         xoff_v=xoff_v,
                                         width=width,
                                         **kwargs) *
                    (xarr.as_unit('GHz').value > minfreq[ii]) *
                    (xarr.as_unit('GHz').value < maxfreq[ii]))
                   for ii in xrange(len(tex))],
                  axis=0)
    return spec
Beispiel #31
0
    def update_information(self, **kwargs):
        self.information = [
            ("Baseline Range","(%g,%g)" % (self.baseline.xmin,self.baseline.xmax)),
            ("Baseline Order","%i" % (self.baseline.order)),
            ("Baseline Subtracted?","%s" % (self.baseline.subtracted)),
            ("Fitter Range","(%g,%g)" % (self.specfit.xmin,self.specfit.xmax)),
            ("Fitter Type","%s" % (self.specfit.fittype)),
            ]

        for ii in xrange(self.specfit.npeaks):
            guesses = tuple(self.specfit.guesses[ii:ii+3])
            if len(guesses) == 3:
                self.information += [("Fitter guesses%i:" % ii , "p: %g c: %g w: %g" % guesses) ]
            else:
                break

        self.show_labels(**kwargs)
Beispiel #32
0
def read_galex(fitsfilename, orderselection='obj'):
    """
    Read in a GALEX xg-gsp.fits file 
    Definition of the file is here: 
    `<http://www.galex.caltech.edu/DATA/gr1_docs/GR1_Column_descriptions_for_-xg-gsp.fits.htm>`_

    Parameters
    ----------
    fitsfilename: string 
        The file name (must be a valid FITS file)
    orderselection: {'obj','objs'}
        'obj' selects the NUV 1st and FUV 2nd orders
        'objs' selects the NUV 2nd and FUV 3rd orders
            (higher resolution, lower S/N)

    Example
    -------
    # from http://galex.stsci.edu/GR6/?page=downloadlist&tilenum=5697&type=coaddS
    $ wget http://galex.stsci.edu/data/GR6/pipe/01-vsn/05697-VAR_J000836p545700/g/01-main/0001-img/07-try/VAR_J000836p545700-xg-gsp.fits.gz
    $ gunzip VAR_J000836p545700-xg-gsp.fits.gz

    >>> spblock = read_galex('VAR_J000836p545700-xg-gsp.fits')
    >>> spavg = spblock.average() # average over all spectra of the source (naive)
    >>> spblock.plotter()
    >>> spavg.plotter()
    """
    from .. import classes

    ff = pyfits.open(fitsfilename)
    bintable = ff[1].data

    # wavelength in angstroms
    wavelength = bintable.zero + np.arange(len(bintable.disp)) * bintable.disp
    xaxis = units.SpectroscopicAxis(wavelength, units='angstroms')

    splist = [
        Spectrum(data=bintable[orderselection][:, ii],
                 error=bintable[orderselection + "err"][:, ii],
                 xarr=xaxis,
                 header=ff[1].header)
        for ii in xrange(bintable[orderselection].shape[1])
    ]

    galexblock = ObsBlock(splist)

    return galexblock
Beispiel #33
0
    def _remove_cut_lines(self):
        """
        Removes any cutlines that may already have existed in the
        input polygons.  This is so any cutlines in the final result
        will be optimized to be as short as possible and won't
        intersect each other.

        This works by finding coincident edges that are reverse to
        each other, and then splicing around them.
        """
        # As this proceeds, edges are removed from the graph.  It
        # iterates over a static list of all edges that exist at the
        # start, so each time one is selected, we need to ensure it
        # still exists as part of the graph.

        # This transforms the following (where = is the cut line)
        #
        #     \                    /
        #  A' +                    + B'
        #     |                    |
        #  A  +====================+ B
        #
        #  D  +====================+ C
        #     |                    |
        #  D' +                    + C'
        #     /                    \
        #
        # to this:
        #
        #     \                    /
        #  A' +                    + B'
        #     |                    |
        #  A  +                    + C
        #     |                    |
        #  D' +                    + C'
        #     /                    \
        #

        edges = list(self._edges)
        for i in xrange(len(edges)):
            AB = edges[i]
            if AB not in self._edges:
                continue
            A, B = AB._nodes
            if len(A._edges) == 3 and len(B._edges) == 3:
                self._remove_edge(AB)
Beispiel #34
0
    def _remove_cut_lines(self):
        """
        Removes any cutlines that may already have existed in the
        input polygons.  This is so any cutlines in the final result
        will be optimized to be as short as possible and won't
        intersect each other.

        This works by finding coincident edges that are reverse to
        each other, and then splicing around them.
        """
        # As this proceeds, edges are removed from the graph.  It
        # iterates over a static list of all edges that exist at the
        # start, so each time one is selected, we need to ensure it
        # still exists as part of the graph.

        # This transforms the following (where = is the cut line)
        #
        #     \                    /
        #  A' +                    + B'
        #     |                    |
        #  A  +====================+ B
        #
        #  D  +====================+ C
        #     |                    |
        #  D' +                    + C'
        #     /                    \
        #
        # to this:
        #
        #     \                    /
        #  A' +                    + B'
        #     |                    |
        #  A  +                    + C
        #     |                    |
        #  D' +                    + C'
        #     /                    \
        #

        edges = list(self._edges)
        for i in xrange(len(edges)):
            AB = edges[i]
            if AB not in self._edges:
                continue
            A, B = AB._nodes
            if len(A._edges) == 3 and len(B._edges) == 3:
                self._remove_edge(AB)
Beispiel #35
0
def formaldehyde_mm_despotic(xarr,
                             temperature=25,
                             column=13,
                             density=4,
                             xoff_v=0.0,
                             width=1.0,
                             grid_vwidth=1.0,
                             h2co_303_202=None,
                             h2co_322_221=None,
                             h2co_321_220=None,
                             debug=False,
                             verbose=False,
                             **kwargs):
    """
    Fitter to p-H2CO using despotic grids.  Requires building grids and passing in
    functions for interpolating the h2co transition optical depth and
    excitation temperatures.
    """

    Tex303_202, tau303_202 = h2co_303_202(logdensity=density,
                                          logcolumn=column,
                                          temperature=temperature,
                                          sigmav=width)

    Tex322_221, tau322_221 = h2co_322_221(logdensity=density,
                                          logcolumn=column,
                                          temperature=temperature,
                                          sigmav=width)

    Tex321_220, tau321_220 = h2co_321_220(logdensity=density,
                                          logcolumn=column,
                                          temperature=temperature,
                                          sigmav=width)

    tex = [Tex303_202, Tex322_221, Tex321_220]
    tau = [tau303_202, tau322_221, tau321_220]
    minfreq = [218.15, 218.40, 218.7]
    maxfreq = [218.25, 218.55, 218.8]
    spec = np.sum([
        (formaldehyde_mm_vtau(xarr, Tex=float(tex[ii]), tau=float(tau[ii]),
                              xoff_v=xoff_v, width=width, **kwargs)
         * (xarr.as_unit('GHz').value>minfreq[ii]) *
         (xarr.as_unit('GHz').value<maxfreq[ii])) for ii in xrange(len(tex))],
                  axis=0)
    return spec
Beispiel #36
0
    def update_information(self, **kwargs):
        self.information = [
            ("Baseline Range",
             "(%g,%g)" % (self.baseline.xmin, self.baseline.xmax)),
            ("Baseline Order", "%i" % (self.baseline.order)),
            ("Baseline Subtracted?", "%s" % (self.baseline.subtracted)),
            ("Fitter Range",
             "(%g,%g)" % (self.specfit.xmin, self.specfit.xmax)),
            ("Fitter Type", "%s" % (self.specfit.fittype)),
        ]

        for ii in xrange(self.specfit.npeaks):
            guesses = tuple(self.specfit.guesses[ii:ii + 3])
            if len(guesses) == 3:
                self.information += [("Fitter guesses%i:" % ii,
                                      "p: %g c: %g w: %g" % guesses)]
            else:
                break

        self.show_labels(**kwargs)
Beispiel #37
0
def load_IRAF_multispec(fitsfilename):
    """
    Load an IRAF multispec file as a list of spectra
    (a list of spectra can be passed to `pyspeckit.ObsBlock` if they are all of
    the same wavelength regime, but different objects or different spectra of
    the same object.  They can be passed to `pyspeckit.Spectra` if, e.g., you
    have an Echelle spectrum 
    """

    fitsfile = pyfits.open(fitsfilename)

    data, err, xax, header = read_echelle(fitsfile[0])

    speclist = [Spectrum(data=data[ii,:], 
            error=err[ii,:],
            xarr=xax[ii,:], 
            header=header) 
        for ii in xrange(data.shape[0])]

    return speclist
Beispiel #38
0
def read_galex(fitsfilename, orderselection='obj'):
    """
    Read in a GALEX xg-gsp.fits file 
    Definition of the file is here: 
    `<http://www.galex.caltech.edu/DATA/gr1_docs/GR1_Column_descriptions_for_-xg-gsp.fits.htm>`_

    Parameters
    ----------
    fitsfilename: string 
        The file name (must be a valid FITS file)
    orderselection: {'obj','objs'}
        'obj' selects the NUV 1st and FUV 2nd orders
        'objs' selects the NUV 2nd and FUV 3rd orders
            (higher resolution, lower S/N)

    Example
    -------
    # from http://galex.stsci.edu/GR6/?page=downloadlist&tilenum=5697&type=coaddS
    $ wget http://galex.stsci.edu/data/GR6/pipe/01-vsn/05697-VAR_J000836p545700/g/01-main/0001-img/07-try/VAR_J000836p545700-xg-gsp.fits.gz
    $ gunzip VAR_J000836p545700-xg-gsp.fits.gz

    >>> spblock = read_galex('VAR_J000836p545700-xg-gsp.fits')
    >>> spavg = spblock.average() # average over all spectra of the source (naive)
    >>> spblock.plotter()
    >>> spavg.plotter()
    """
    from .. import classes

    ff = pyfits.open(fitsfilename)
    bintable = ff[1].data

    # wavelength in angstroms
    wavelength = bintable.zero + np.arange(len(bintable.disp)) * bintable.disp
    xaxis = units.SpectroscopicAxis(wavelength,units='angstroms')

    splist = [Spectrum(data=bintable[orderselection][:,ii], error=bintable[orderselection+"err"][:,ii], xarr=xaxis, header=ff[1].header)
            for ii in xrange(bintable[orderselection].shape[1])]

    galexblock = ObsBlock(splist)

    return galexblock
Beispiel #39
0
    def n_formaldehyde(self, pars=None, fittau=False, **kwargs):
        """
        Returns a function that sums over N ammonia line profiles, where N is the length of
        tkin,tex,Ntot,width,xoff_v,fortho *OR* N = len(pars) / 6

        The background "height" is assumed to be zero (you must "baseline" your
        spectrum before fitting)

        pars  - a list with len(pars) = 6n, assuming tkin,tex,Ntot,width,xoff_v,fortho repeated
        """
        if len(pars) % 6 == 0:
            tkin = [pars[ii] for ii in xrange(0, len(pars), 6)]
            tex = [pars[ii] for ii in xrange(1, len(pars), 6)]
            Ntot = [pars[ii] for ii in xrange(2, len(pars), 6)]
            width = [pars[ii] for ii in xrange(3, len(pars), 6)]
            xoff_v = [pars[ii] for ii in xrange(4, len(pars), 6)]
            fortho = [pars[ii] for ii in xrange(5, len(pars), 6)]
        elif not (len(tkin) == len(tex) == len(Ntot) == len(xoff_v) ==
                  len(width) == len(fortho)):
            raise ValueError("Wrong array lengths!")

        modelkwargs = kwargs.copy()

        def L(x):
            v = np.zeros(len(x))
            for i in range(len(tkin)):
                modelkwargs.update({
                    'tkin': tkin[i],
                    'tex': tex[i],
                    'width': width[i],
                    'xoff_v': xoff_v[i],
                    'fortho': fortho[i]
                })
                if fittau:
                    modelkwargs.update({'tau11': Ntot[i]})
                else:
                    modelkwargs.update({'Ntot': Ntot[i]})
                v += self.ammonia(x, **modelkwargs)
            return v

        return L
Beispiel #40
0
def fitnh3tkin(input_dict,
               dobaseline=True,
               baselinekwargs={},
               crop=False,
               guessline='twotwo',
               tex=15,
               tkin=20,
               column=15.0,
               fortho=0.66,
               tau=None,
               thin=False,
               quiet=False,
               doplot=True,
               fignum=1,
               guessfignum=2,
               smooth=False,
               scale_keyword=None,
               rebase=False,
               npeaks=1,
               guesses=None,
               **kwargs):
    """
    Given a dictionary of filenames and lines, fit them together
    e.g. {'oneone':'G000.000+00.000_nh3_11.fits'}
    """
    spdict = dict([(linename, Spectrum(value, scale_keyword=scale_keyword))
                   if type(value) is str else (linename, value)
                   for linename, value in iteritems(input_dict)])
    splist = spdict.values()

    for sp in splist:  # required for plotting, cropping
        sp.xarr.convert_to_unit('km/s')

    if crop and len(crop) == 2:
        for sp in splist:
            sp.crop(*crop)

    if dobaseline:
        for sp in splist:
            sp.baseline(**baselinekwargs)

    if smooth and type(smooth) is int:
        for sp in splist:
            sp.smooth(smooth)

    spdict[guessline].specfit(fittype='gaussian',
                              negamp=False,
                              vheight=False,
                              guesses='moments')
    ampguess, vguess, widthguess = spdict[guessline].specfit.modelpars
    if widthguess < 0:
        raise ValueError("Width guess was < 0.  This is impossible.")
    print("RMS guess (errspec): ", spdict[guessline].specfit.errspec.mean())
    print("RMS guess (residuals): ", spdict[guessline].specfit.residuals.std())
    errguess = spdict[guessline].specfit.residuals.std()

    if rebase:
        # redo baseline subtraction excluding the centroid +/- about 20 km/s
        vlow = spdict[guessline].specfit.modelpars[1] - (
            19.8 + spdict[guessline].specfit.modelpars[2] * 2.35)
        vhigh = spdict[guessline].specfit.modelpars[1] + (
            19.8 + spdict[guessline].specfit.modelpars[2] * 2.35)
        for sp in splist:
            sp.baseline(exclude=[vlow, vhigh], **baselinekwargs)

    for sp in splist:
        sp.error[:] = errguess

    if doplot:
        spdict[guessline].plotter(figure=guessfignum)
        spdict[guessline].specfit.plot_fit()

    spectra = Spectra(splist)
    spectra.specfit.npeaks = npeaks

    if tau is not None:
        if guesses is None:
            guesses = [
                a for i in xrange(npeaks)
                for a in (tkin + random.random() * i, tex,
                          tau + random.random() * i,
                          widthguess + random.random() * i,
                          vguess + random.random() * i, fortho)
            ]
        spectra.specfit(fittype='ammonia_tau',
                        quiet=quiet,
                        multifit=None,
                        guesses=guesses,
                        thin=thin,
                        **kwargs)
    else:
        if guesses is None:
            guesses = [
                a for i in xrange(npeaks)
                for a in (tkin + random.random() * i, tex,
                          column + random.random() * i,
                          widthguess + random.random() * i,
                          vguess + random.random() * i, fortho)
            ]
        spectra.specfit(fittype='ammonia',
                        quiet=quiet,
                        multifit=None,
                        guesses=guesses,
                        thin=thin,
                        **kwargs)

    if doplot:
        plot_nh3(spdict, spectra, fignum=fignum)

    return spdict, spectra
Beispiel #41
0
def test_ordering():
    nrepeat = 10

    A = polygon.SphericalPolygon(
        [[3.532808036921135653e-01, 6.351523005458726834e-01, -6.868582305351954576e-01],
         [3.532781068942476010e-01, 6.351564219435104075e-01, -6.868558064493115456e-01],
         [3.529538811375814156e-01, 6.351027504797477352e-01, -6.870720880104047579e-01],
         [3.533428330964511477e-01, 6.345142927049303161e-01, -6.874157800432978416e-01],
         [3.533486351814376647e-01, 6.345151843837375516e-01, -6.874119745843003670e-01],
         [3.533513056857608414e-01, 6.345111416839894769e-01, -6.874143334620310686e-01],
         [3.536740696809928530e-01, 6.345607036635456666e-01, -6.872025653337667794e-01],
         [3.536713200704008631e-01, 6.345649108795897719e-01, -6.872000954889618818e-01],
         [3.536761865498951884e-01, 6.345656515431040701e-01, -6.871969069700470945e-01],
         [3.536788213460497765e-01, 6.345616140129455296e-01, -6.871992792142280759e-01],
         [3.540056257094351122e-01, 6.346113105009757449e-01, -6.869850810245486938e-01],
         [3.536200722272911379e-01, 6.352081961257413090e-01, -6.866319189293832448e-01],
         [3.536142814048366390e-01, 6.352072452054380314e-01, -6.866357809093986964e-01],
         [3.536116196666648781e-01, 6.352113634102898310e-01, -6.866333419163089813e-01],
         [3.532833767830895755e-01, 6.351574192193063517e-01, -6.868521736876195272e-01],
         [3.532861440234288386e-01, 6.351531838825796861e-01, -6.868546669018701367e-01],
         [3.532808036921135653e-01, 6.351523005458726834e-01, -6.868582305351954576e-01]],
        [3.536414047913637448e-01, 6.348851549491377755e-01, -6.869196436573932196e-01])

    B = polygon.SphericalPolygon(
        [[3.529249199274748783e-01, 6.356925960489819838e-01, -6.865412764158403958e-01],
         [3.533126219535084322e-01, 6.351003877952851040e-01, -6.868898664200949744e-01],
         [3.533173735956686712e-01, 6.351012981906917210e-01, -6.868865805589428053e-01],
         [3.529301898742857047e-01, 6.356935934402119237e-01, -6.865376437853726310e-01],
         [3.532584388080926563e-01, 6.357475490961038700e-01, -6.863188247667159070e-01],
         [3.536441982306618437e-01, 6.351510082118909661e-01, -6.866723948326530769e-01],
         [3.533173735956686712e-01, 6.351012981906917210e-01, -6.868865805589428053e-01],
         [3.533126219535084322e-01, 6.351003877952851040e-01, -6.868898664200949744e-01],
         [3.529898380712340189e-01, 6.350508125724935171e-01, -6.871016225198859351e-01],
         [3.526006883384300017e-01, 6.356389133339014341e-01, -6.867575456003104373e-01],
         [3.529249199274748783e-01, 6.356925960489819838e-01, -6.865412764158403958e-01]],
        [3.532883212044564125e-01, 6.354215160430938258e-01, -6.866053153377369433e-01])

    areas = []
    for i in xrange(nrepeat):
        C = A.intersection(B)
        areas.append(C.area())
    areas = np.array(areas)
    assert_array_almost_equal(areas[:-1], areas[1:])

    def roll_polygon(P, i):
        points = P.points
        points = np.roll(points[:-1], i, 0)
        points = np.append(points, [points[0]], 0)
        return polygon.SphericalPolygon(points, P.inside)

    Aareas = []
    Bareas = []
    Careas = []
    for i in xrange(nrepeat):
        AS = roll_polygon(A, i)
        BS = roll_polygon(B, i)

        C = AS.intersection(BS)

        Aareas.append(A.area())
        Bareas.append(B.area())
        Careas.append(C.area())

        for j in xrange(nrepeat):
            CS = roll_polygon(C, j)
            Careas.append(CS.area())

    Aareas = np.array(Aareas)
    Bareas = np.array(Bareas)
    Careas = np.array(Careas)
    assert_array_almost_equal(Aareas[:-1], Aareas[1:])
    assert_array_almost_equal(Bareas[:-1], Bareas[1:])
    assert_array_almost_equal(Careas[:-1], Careas[1:])
Beispiel #42
0
def formaldehyde_radex_orthopara_temp(xarr, density=4, column=13,
                                      orthopara=1.0, temperature=15.0,
                                      xoff_v=0.0, width=1.0,
                                      Tbackground1=2.73,
                                      Tbackground2=2.73,
                                      grid_vwidth=1.0,
                                      grid_vwidth_scale=False, texgrid=None,
                                      taugrid=None, hdr=None,
                                      path_to_texgrid='', path_to_taugrid='',
                                      debug=False, verbose=False,
                                      getpars=False, **kwargs):
    """
    Use a grid of RADEX-computed models to make a model line spectrum

    The RADEX models have to be available somewhere.
    OR they can be passed as arrays.  If as arrays, the form should be:
    texgrid = ((minfreq1,maxfreq1,texgrid1),(minfreq2,maxfreq2,texgrid2))

    xarr must be a SpectroscopicAxis instance
    xoff_v, width are both in km/s

    grid_vwidth is the velocity assumed when computing the grid in km/s
    this is important because tau = modeltau / width (see, e.g.,
    Draine 2011 textbook pgs 219-230)
    grid_vwidth_scale is True or False: False for LVG, True for Sphere
    """

    if texgrid is None and taugrid is None:
        if path_to_texgrid == '' or path_to_taugrid=='':
            raise IOError("Must specify model grids to use.")
        else:
            taugrid = [pyfits.getdata(path_to_taugrid)]
            texgrid = [pyfits.getdata(path_to_texgrid)]
            hdr = pyfits.getheader(path_to_taugrid)
            minfreq = (4.8,)
            maxfreq = (5.0,)
    elif len(taugrid)==len(texgrid) and hdr is not None:
        minfreq,maxfreq,texgrid = zip(*texgrid)
        minfreq,maxfreq,taugrid = zip(*taugrid)
    else:
        raise Exception

    densityarr = (np.arange(taugrid[0].shape[3])+hdr['CRPIX1']-1)*hdr['CD1_1']+hdr['CRVAL1'] # log density
    columnarr  = (np.arange(taugrid[0].shape[2])+hdr['CRPIX2']-1)*hdr['CD2_2']+hdr['CRVAL2'] # log column
    temparr    = (np.arange(taugrid[0].shape[1])+hdr['CRPIX3']-1)*hdr['CDELT3']+hdr['CRVAL3'] # temperature
    oprarr     = (np.arange(taugrid[0].shape[0])+hdr['CRPIX4']-1)*hdr['CDELT4']+hdr['CRVAL4'] # log ortho/para ratio

    gridval1 = np.interp(density,     densityarr,  np.arange(len(densityarr)))
    gridval2 = np.interp(column,      columnarr,   np.arange(len(columnarr)))
    gridval3 = np.interp(temperature, temparr,     np.arange(len(temparr)))
    gridval4 = np.interp(orthopara,   oprarr,      np.arange(len(oprarr)))
    if np.isnan(gridval1) or np.isnan(gridval2):
        raise ValueError("Invalid column/density")

    if scipyOK:
        slices = [slice(int(np.floor(gv)),int(np.floor(gv)+2))
                  for gv in (gridval4,gridval3,gridval2,gridval1)]
        tau = [scipy.ndimage.map_coordinates(tg[slices],
                                             np.array([[gridval4 % 1],
                                                       [gridval3 % 1],
                                                       [gridval2 % 1],
                                                       [gridval1 % 1]]),
                                             order=1, prefilter=False)
               for tg in taugrid]
        tex = [scipy.ndimage.map_coordinates(tg[slices],
                                             np.array([[gridval4 % 1],
                                                       [gridval3 % 1],
                                                       [gridval2 % 1],
                                                       [gridval1 % 1]]),
                                             order=1,prefilter=False)
               for tg in texgrid]
    else:
        raise ImportError("Couldn't import scipy, therefore cannot interpolate")
    #tau = modelgrid.line_params_2D(gridval1,gridval2,densityarr,columnarr,taugrid[temperature_gridnumber,:,:])
    #tex = modelgrid.line_params_2D(gridval1,gridval2,densityarr,columnarr,texgrid[temperature_gridnumber,:,:])

    # there can be different background temperatures at each frequency
    tbg = [Tbackground1,Tbackground2]

    if verbose:
        print("density %20.12g   column: %20.12g   temperature: %20.12g   opr: %20.12g   xoff_v: %20.12g   width: %20.12g" % (density, column, temperature, orthopara, xoff_v, width))
        print("tau: ",tau," tex: ",tex)
        print("minfreq: ",minfreq," maxfreq: ",maxfreq)
        print("tbg: ",tbg)

    if debug > 1:
        import pdb; pdb.set_trace()

    if getpars:
        return tau,tex

    spec = np.sum([(formaldehyde_vtau(xarr.as_unit('Hz', quiet=True),
                                      Tex=float(tex[ii]), tau=float(tau[ii]),
                                      Tbackground=tbg[ii], xoff_v=xoff_v,
                                      width=width, **kwargs)
                    * (xarr.as_unit('GHz')>minfreq[ii])
                    * (xarr.as_unit('GHz')<maxfreq[ii]))
                   for ii in xrange(len(tex))],
                  axis=0)

    return spec
Beispiel #43
0
def formaldehyde_pyradex(xarr, density=4, column=13, temperature=20,
                         xoff_v=0.0, opr=1.0, width=1.0, tbackground=2.73,
                         grid_vwidth=1.0, debug=False, verbose=False,
                         **kwargs):
    """
    Use a grid of RADEX-computed models to make a model line spectrum

    The RADEX models have to be available somewhere.
    OR they can be passed as arrays.  If as arrays, the form should be:
    texgrid = ((minfreq1,maxfreq1,texgrid1),(minfreq2,maxfreq2,texgrid2))

    xarr must be a SpectroscopicAxis instance
    xoff_v, width are both in km/s

    grid_vwidth is the velocity assumed when computing the grid in km/s
    this is important because tau = modeltau / width (see, e.g.,
    Draine 2011 textbook pgs 219-230)
    """

    raise NotImplementedError("Not done yet.")
    import pyradex

    # Convert X-units to frequency in GHz
    xarr = xarr.as_unit('Hz', quiet=True)

    tb_nu_cumul = np.zeros(len(xarr))

    R = pyradex.Radex(molecule='oh2co-h2', column=column,
                      temperature=temperature, density=10**density,
                      tbackground=tbackground,)

    spec = np.sum([(formaldehyde_vtau(xarr,Tex=float(tex[ii]),tau=float(tau[ii]),xoff_v=xoff_v,width=width, **kwargs)
                * (xarr.as_unit('GHz')>minfreq[ii]) * (xarr.as_unit('GHz')<maxfreq[ii])) for ii in xrange(len(tex))],
                axis=0)

    return spec
Beispiel #44
0
 def values(self):
     return [self._dict[self._dict_index[ii]] for ii in xrange(len(self))]
Beispiel #45
0
 def keys(self):
     return [self._dict_index[ii] for ii in xrange(len(self))]
        agpy.pymc_plotting.hist2d(spmchdf5b, 'TEMPERATURE0', 'COLUMN0', doerrellipse=False, clear=True, bins=50,fignum=5)
        pl.savefig("h2co_mm_tem_vs_col_tmb2.png")
        agpy.pymc_plotting.hist2d(spmchdf5b, 'DENSITY0', 'COLUMN0', doerrellipse=False, clear=True, bins=50,fignum=6)
        pl.savefig("h2co_mm_den_vs_col_tmb2.png")

        spmchdf5d.sample(1e5)
        spmchdf5d.db.close()
        agpy.pymc_plotting.hist2d(spmchdf5d, 'TEMPERATURE0', 'DENSITY0', doerrellipse=False, clear=True, bins=50, fignum=4)
        pl.savefig("h2co_mm_tem_vs_den_tmb_vel.png")
        agpy.pymc_plotting.hist2d(spmchdf5d, 'TEMPERATURE0', 'COLUMN0', doerrellipse=False, clear=True, bins=50,fignum=5)
        pl.savefig("h2co_mm_tem_vs_col_tmb_vel.png")
        agpy.pymc_plotting.hist2d(spmchdf5d, 'DENSITY0', 'COLUMN0', doerrellipse=False, clear=True, bins=50,fignum=6)
        pl.savefig("h2co_mm_den_vs_col_tmb_vel.png")

        pars = dict([(k,spmchdf5b.trace(k)[-50:]) for k in sp3.specfit.parinfo.keys()])
        for ii in xrange(0,50):
            sp3.specfit.plot_model( [pars[k][ii] for k in sp3.specfit.parinfo.keys()],
                    clear=False, 
                    composite_fit_color='r',
                    plotkwargs={'alpha':0.01})

        sp3.plotter.autorefresh=False
        pars = dict([(k,spmchdf5d.trace(k)[-1000:]) for k in sp3.specfit.parinfo.keys()])
        for ii in xrange(0,1000):
            sp3.specfit.plot_model( [pars[k][ii] for k in sp3.specfit.parinfo.keys()],
                    clear=False, 
                    composite_fit_color='r',
                    plotkwargs={'alpha':0.01}, composite_lw=2)
        sp3.plotter.refresh()

Beispiel #47
0
def formaldehyde_radex_tau(xarr,
                           density=4,
                           column=13,
                           xoff_v=0.0,
                           width=1.0,
                           grid_vwidth=1.0,
                           grid_vwidth_scale=False,
                           taugrid=None,
                           hdr=None,
                           path_to_taugrid='',
                           temperature_gridnumber=3,
                           debug=False,
                           verbose=False,
                           return_hyperfine_components=False,
                           **kwargs):
    """
    Use a grid of RADEX-computed models to make a model line spectrum

     * uses hyperfine components
     * assumes *tau* varies but *tex* does not!

    The RADEX models have to be available somewhere.
    OR they can be passed as arrays.  If as arrays, the form should be:
    texgrid = ((minfreq1,maxfreq1,texgrid1),(minfreq2,maxfreq2,texgrid2))

    xarr must be a SpectroscopicAxis instance
    xoff_v, width are both in km/s

    grid_vwidth is the velocity assumed when computing the grid in km/s
    this is important because tau = modeltau / width (see, e.g.,
    Draine 2011 textbook pgs 219-230)
    grid_vwidth_scale is True or False: False for LVG, True for Sphere
    """

    if verbose:
        print("Parameters: dens=%f, column=%f, xoff=%f, width=%f" %
              (density, column, xoff_v, width))

    if taugrid is None:
        if path_to_taugrid == '':
            raise IOError("Must specify model grids to use.")
        else:
            taugrid = [pyfits.getdata(path_to_taugrid)]
            hdr = pyfits.getheader(path_to_taugrid)
            yinds, xinds = np.indices(taugrid[0].shape[1:])
            densityarr = (xinds + hdr['CRPIX1'] -
                          1) * hdr['CD1_1'] + hdr['CRVAL1']  # log density
            columnarr = (yinds + hdr['CRPIX2'] -
                         1) * hdr['CD2_2'] + hdr['CRVAL2']  # log column
            minfreq = (4.8, )
            maxfreq = (5.0, )
    elif hdr is not None:
        minfreq, maxfreq, taugrid = zip(*taugrid)
        yinds, xinds = np.indices(taugrid[0].shape[1:])
        densityarr = (xinds + hdr['CRPIX1'] -
                      1) * hdr['CD1_1'] + hdr['CRVAL1']  # log density
        columnarr = (yinds + hdr['CRPIX2'] -
                     1) * hdr['CD2_2'] + hdr['CRVAL2']  # log column
    else:
        raise Exception

    # Convert X-units to frequency in GHz
    xarr = xarr.as_unit('Hz', quiet=True)

    gridval1 = np.interp(density, densityarr[0, :], xinds[0, :])
    gridval2 = np.interp(column, columnarr[:, 0], yinds[:, 0])
    if np.isnan(gridval1) or np.isnan(gridval2):
        raise ValueError("Invalid column/density")

    if scipyOK:
        slices = [temperature_gridnumber] + [
            slice(np.floor(gv),
                  np.floor(gv) + 2) for gv in (gridval2, gridval1)
        ]
        tau = [
            scipy.ndimage.map_coordinates(tg[slices],
                                          np.array([[gridval2 % 1],
                                                    [gridval1 % 1]]),
                                          order=1) for tg in taugrid
        ]
    else:
        raise ImportError(
            "Couldn't import scipy, therefore cannot interpolate")

    # let the hyperfine module determine the hyperfine components, and pass all of them here
    spec_components = [
        (formaldehyde_vtau(xarr.as_unit('Hz', quiet=True),
                           tau=float(tau[ii]),
                           xoff_v=xoff_v,
                           width=width,
                           return_tau=True,
                           return_hyperfine_components=True,
                           **kwargs) * (xarr.as_unit('GHz') > minfreq[ii]) *
         (xarr.as_unit('GHz') < maxfreq[ii])) for ii in xrange(len(tau))
    ]

    # get an array of [n_lines, n_hyperfine, len(xarr)]
    if return_hyperfine_components:
        return np.array(spec_components).sum(axis=0)
    else:
        return np.sum(spec_components, axis=0).sum(axis=0)
Beispiel #48
0
    def multinh3fit(self, xax, data, npeaks=1, err=None, params=[20,20,1e10,1.0,0.0,0.5],
            fixed=[False,False,False,False,False,False],
            limitedmin=[True,True,True,True,False,True],
            limitedmax=[False,False,False,False,False,True], minpars=[2.73,2.73,0,0,0,0],
            maxpars=[0,0,0,0,0,1], quiet=True, shh=True, veryverbose=False, **kwargs):
        """
        Fit multiple nh3 profiles

        Inputs:
           xax - x axis
           data - y axis
           npeaks - How many nh3 profiles to fit?  Default 1 (this could supersede onedgaussfit)
           err - error corresponding to data

         These parameters need to have length = 6*npeaks.  If npeaks > 1 and length = 6, they will
         be replicated npeaks times, otherwise they will be reset to defaults:
           params - Fit parameters: [amplitude, offset, Gfwhm, Lfwhm] * npeaks
                  If len(params) % 6 == 0, npeaks will be set to len(params) / 6
           fixed - Is parameter fixed?
           limitedmin/minpars - set lower limits on each parameter (default: width>0, Tex and Tkin > Tcmb)
           limitedmax/maxpars - set upper limits on each parameter

           quiet - should MPFIT output each iteration?
           shh - output final parameters?

        Returns:
           Fit parameters
           Model
           Fit errors
           chi2
        """

        self.npars = 6

        if len(params) != npeaks and (len(params) / self.npars) > npeaks:
            npeaks = len(params) / self.npars 
        self.npeaks = npeaks

        if isinstance(params,np.ndarray): params=params.tolist()

        # make sure all various things are the right length; if they're not, fix them using the defaults
        for parlist in (params,fixed,limitedmin,limitedmax,minpars,maxpars):
            if len(parlist) != self.npars*self.npeaks:
                # if you leave the defaults, or enter something that can be multiplied by 3 to get to the
                # right number of gaussians, it will just replicate
                if len(parlist) == self.npars: 
                    parlist *= npeaks 
                elif parlist==params:
                    parlist[:] = [20,20,1e10,1.0,0.0,0.5] * npeaks
                elif parlist==fixed:
                    parlist[:] = [False,False,False,False,False,False] * npeaks
                elif parlist==limitedmax:
                    parlist[:] = [False,False,False,False,False,True] * npeaks
                elif parlist==limitedmin:
                    parlist[:] = [True,True,True,True,False,True] * npeaks
                elif parlist==minpars:
                    parlist[:] = [2.73,0,0,0,0,0] * npeaks
                elif parlist==maxpars:
                    parlist[:] = [0,0,0,0,0,1] * npeaks

        def mpfitfun(x,y,err):
            if err is None:
                def f(p,fjac=None): return [0,(y-self.n_ammonia(pars=p, **kwargs)(x))]
            else:
                def f(p,fjac=None): return [0,(y-self.n_ammonia(pars=p, **kwargs)(x))/err]
            return f

        parnames = {0:"TKIN",1:"TEX",2:"NTOT",3:"WIDTH",4:"XOFF_V",5:"FORTHO"}

        parinfo = [ {'n':ii, 'value':params[ii],
            'limits':[minpars[ii],maxpars[ii]],
            'limited':[limitedmin[ii],limitedmax[ii]], 'fixed':fixed[ii],
            'parname':parnames[ii%self.npars]+str(ii/self.npars), 
            'mpmaxstep':0,'error':ii} 
            for ii in xrange(len(params)) ]
        parinfo[0]['mpmaxstep'] = 1.0
        parinfo[1]['mpmaxstep'] = 1.0

        if veryverbose:
            print "GUESSES: "
            print "\n".join(["%s: %s" % (p['parname'],p['value']) for p in parinfo])

        mp = mpfit(mpfitfun(xax,data,err),parinfo=parinfo,quiet=quiet)
        mpp = mp.params
        if mp.perror is not None: mpperr = mp.perror
        else: mpperr = mpp*0
        chi2 = mp.fnorm

        if mp.status == 0:
            raise Exception(mp.errmsg)

        if not shh:
            print "Fit message: ",mp.errmsg
            print "Final fit values: "
            for i,p in enumerate(mpp):
                parinfo[i]['value'] = p
                print parinfo[i]['parname'],p," +/- ",mpperr[i]
            print "Chi2: ",mp.fnorm," Reduced Chi2: ",mp.fnorm/len(data)," DOF:",len(data)-len(mpp)

        if mpp[1] > mpp[0]: mpp[1] = mpp[0]  # force Tex>Tkin to Tex=Tkin (already done in n_ammonia)
        self.mp = mp
        self.mpp = mpp
        self.mpperr = mpperr
        self.model = self.n_ammonia(pars=mpp,**kwargs)(xax)
        return mpp,self.n_ammonia(pars=mpp,**kwargs)(xax),mpperr,chi2
Beispiel #49
0
def formaldehyde_radex_orthopara_temp(xarr,
                                      density=4,
                                      column=13,
                                      orthopara=1.0,
                                      temperature=15.0,
                                      xoff_v=0.0,
                                      width=1.0,
                                      Tbackground1=2.73,
                                      Tbackground2=2.73,
                                      grid_vwidth=1.0,
                                      grid_vwidth_scale=False,
                                      texgrid=None,
                                      taugrid=None,
                                      hdr=None,
                                      path_to_texgrid='',
                                      path_to_taugrid='',
                                      debug=False,
                                      verbose=False,
                                      getpars=False,
                                      **kwargs):
    """
    Use a grid of RADEX-computed models to make a model line spectrum

    The RADEX models have to be available somewhere.
    OR they can be passed as arrays.  If as arrays, the form should be:
    texgrid = ((minfreq1,maxfreq1,texgrid1),(minfreq2,maxfreq2,texgrid2))

    xarr must be a SpectroscopicAxis instance
    xoff_v, width are both in km/s

    grid_vwidth is the velocity assumed when computing the grid in km/s
    this is important because tau = modeltau / width (see, e.g.,
    Draine 2011 textbook pgs 219-230)
    grid_vwidth_scale is True or False: False for LVG, True for Sphere
    """

    if texgrid is None and taugrid is None:
        if path_to_texgrid == '' or path_to_taugrid == '':
            raise IOError("Must specify model grids to use.")
        else:
            taugrid = [pyfits.getdata(path_to_taugrid)]
            texgrid = [pyfits.getdata(path_to_texgrid)]
            hdr = pyfits.getheader(path_to_taugrid)
            minfreq = (4.8, )
            maxfreq = (5.0, )
    elif len(taugrid) == len(texgrid) and hdr is not None:
        minfreq, maxfreq, texgrid = zip(*texgrid)
        minfreq, maxfreq, taugrid = zip(*taugrid)
    else:
        raise Exception

    densityarr = (np.arange(taugrid[0].shape[3]) + hdr['CRPIX1'] -
                  1) * hdr['CD1_1'] + hdr['CRVAL1']  # log density
    columnarr = (np.arange(taugrid[0].shape[2]) + hdr['CRPIX2'] -
                 1) * hdr['CD2_2'] + hdr['CRVAL2']  # log column
    temparr = (np.arange(taugrid[0].shape[1]) + hdr['CRPIX3'] -
               1) * hdr['CDELT3'] + hdr['CRVAL3']  # temperature
    oprarr = (np.arange(taugrid[0].shape[0]) + hdr['CRPIX4'] -
              1) * hdr['CDELT4'] + hdr['CRVAL4']  # log ortho/para ratio

    gridval1 = np.interp(density, densityarr, np.arange(len(densityarr)))
    gridval2 = np.interp(column, columnarr, np.arange(len(columnarr)))
    gridval3 = np.interp(temperature, temparr, np.arange(len(temparr)))
    gridval4 = np.interp(orthopara, oprarr, np.arange(len(oprarr)))
    if np.isnan(gridval1) or np.isnan(gridval2):
        raise ValueError("Invalid column/density")

    if scipyOK:
        slices = [
            slice(int(np.floor(gv)), int(np.floor(gv) + 2))
            for gv in (gridval4, gridval3, gridval2, gridval1)
        ]
        tau = [
            scipy.ndimage.map_coordinates(tg[slices],
                                          np.array([[gridval4 % 1],
                                                    [gridval3 % 1],
                                                    [gridval2 % 1],
                                                    [gridval1 % 1]]),
                                          order=1,
                                          prefilter=False) for tg in taugrid
        ]
        tex = [
            scipy.ndimage.map_coordinates(tg[slices],
                                          np.array([[gridval4 % 1],
                                                    [gridval3 % 1],
                                                    [gridval2 % 1],
                                                    [gridval1 % 1]]),
                                          order=1,
                                          prefilter=False) for tg in texgrid
        ]
    else:
        raise ImportError(
            "Couldn't import scipy, therefore cannot interpolate")
    #tau = modelgrid.line_params_2D(gridval1,gridval2,densityarr,columnarr,taugrid[temperature_gridnumber,:,:])
    #tex = modelgrid.line_params_2D(gridval1,gridval2,densityarr,columnarr,texgrid[temperature_gridnumber,:,:])

    # there can be different background temperatures at each frequency
    tbg = [Tbackground1, Tbackground2]

    if verbose:
        print(
            "density %20.12g   column: %20.12g   temperature: %20.12g   opr: %20.12g   xoff_v: %20.12g   width: %20.12g"
            % (density, column, temperature, orthopara, xoff_v, width))
        print("tau: ", tau, " tex: ", tex)
        print("minfreq: ", minfreq, " maxfreq: ", maxfreq)
        print("tbg: ", tbg)

    if debug > 1:
        import pdb
        pdb.set_trace()

    if getpars:
        return tau, tex

    spec = np.sum(
        [(formaldehyde_vtau(xarr.as_unit('Hz', quiet=True),
                            Tex=float(tex[ii]),
                            tau=float(tau[ii]),
                            Tbackground=tbg[ii],
                            xoff_v=xoff_v,
                            width=width,
                            **kwargs) * (xarr.as_unit('GHz') > minfreq[ii]) *
          (xarr.as_unit('GHz') < maxfreq[ii])) for ii in xrange(len(tex))],
        axis=0)

    return spec
Beispiel #50
0
def formaldehyde_radex(xarr,
                       density=4,
                       column=13,
                       xoff_v=0.0,
                       width=1.0,
                       grid_vwidth=1.0,
                       grid_vwidth_scale=False,
                       texgrid=None,
                       taugrid=None,
                       hdr=None,
                       path_to_texgrid='',
                       path_to_taugrid='',
                       temperature_gridnumber=3,
                       debug=False,
                       verbose=False,
                       **kwargs):
    """
    Use a grid of RADEX-computed models to make a model line spectrum

    The RADEX models have to be available somewhere.
    OR they can be passed as arrays.  If as arrays, the form should be:
    texgrid = ((minfreq1,maxfreq1,texgrid1),(minfreq2,maxfreq2,texgrid2))

    xarr must be a SpectroscopicAxis instance
    xoff_v, width are both in km/s

    grid_vwidth is the velocity assumed when computing the grid in km/s
    this is important because tau = modeltau / width (see, e.g.,
    Draine 2011 textbook pgs 219-230)
    grid_vwidth_scale is True or False: False for LVG, True for Sphere
    """

    if texgrid is None and taugrid is None:
        if path_to_texgrid == '' or path_to_taugrid == '':
            raise IOError("Must specify model grids to use.")
        else:
            taugrid = [pyfits.getdata(path_to_taugrid)]
            texgrid = [pyfits.getdata(path_to_texgrid)]
            hdr = pyfits.getheader(path_to_taugrid)
            yinds, xinds = np.indices(taugrid[0].shape[1:])
            densityarr = (xinds + hdr['CRPIX1'] -
                          1) * hdr['CD1_1'] + hdr['CRVAL1']  # log density
            columnarr = (yinds + hdr['CRPIX2'] -
                         1) * hdr['CD2_2'] + hdr['CRVAL2']  # log column
            minfreq = (4.8, )
            maxfreq = (5.0, )
    elif len(taugrid) == len(texgrid) and hdr is not None:
        minfreq, maxfreq, texgrid = zip(*texgrid)
        minfreq, maxfreq, taugrid = zip(*taugrid)
        yinds, xinds = np.indices(taugrid[0].shape[1:])
        densityarr = (xinds + hdr['CRPIX1'] -
                      1) * hdr['CD1_1'] + hdr['CRVAL1']  # log density
        columnarr = (yinds + hdr['CRPIX2'] -
                     1) * hdr['CD2_2'] + hdr['CRVAL2']  # log column
    else:
        raise Exception

    # Convert X-units to frequency in GHz
    xarr = xarr.as_unit('Hz', quiet=True)

    tau_nu_cumul = np.zeros(len(xarr))

    gridval1 = np.interp(density, densityarr[0, :], xinds[0, :])
    gridval2 = np.interp(column, columnarr[:, 0], yinds[:, 0])
    if np.isnan(gridval1) or np.isnan(gridval2):
        raise ValueError("Invalid column/density")

    if scipyOK:
        slices = [temperature_gridnumber] + [
            slice(np.floor(gv),
                  np.floor(gv) + 2) for gv in (gridval2, gridval1)
        ]
        tau = [
            scipy.ndimage.map_coordinates(tg[slices],
                                          np.array([[gridval2 % 1],
                                                    [gridval1 % 1]]),
                                          order=1) for tg in taugrid
        ]
        tex = [
            scipy.ndimage.map_coordinates(tg[slices],
                                          np.array([[gridval2 % 1],
                                                    [gridval1 % 1]]),
                                          order=1) for tg in texgrid
        ]
    else:
        raise ImportError(
            "Couldn't import scipy, therefore cannot interpolate")
    #tau = modelgrid.line_params_2D(gridval1,gridval2,densityarr,columnarr,taugrid[temperature_gridnumber,:,:])
    #tex = modelgrid.line_params_2D(gridval1,gridval2,densityarr,columnarr,texgrid[temperature_gridnumber,:,:])

    if verbose:
        print("density %20.12g column %20.12g: tau %20.12g tex %20.12g" %
              (density, column, tau, tex))

    if debug:
        import pdb
        pdb.set_trace()

    spec = np.sum(
        [(formaldehyde_vtau(xarr,
                            Tex=float(tex[ii]),
                            tau=float(tau[ii]),
                            xoff_v=xoff_v,
                            width=width,
                            **kwargs) * (xarr.as_unit('GHz') > minfreq[ii]) *
          (xarr.as_unit('GHz') < maxfreq[ii])) for ii in xrange(len(tex))],
        axis=0)

    return spec
Beispiel #51
0
def formaldehyde_mm_radex(xarr, 
        temperature=25,
        column=13,
        density=4,
        xoff_v=0.0,
        width=1.0, 
        grid_vwidth=1.0,
        texgrid=None,
        taugrid=None,
        hdr=None,
        path_to_texgrid='',
        path_to_taugrid='',
        debug=False,
        verbose=False,
        **kwargs):
    """
    Use a grid of RADEX-computed models to make a model line spectrum

    The RADEX models have to be available somewhere.
    OR they can be passed as arrays.  If as arrays, the form should be:
    texgrid = ((minfreq1,maxfreq1,texgrid1),(minfreq2,maxfreq2,texgrid2))

    xarr must be a SpectroscopicAxis instance
    xoff_v, width are both in km/s


    Parameters
    ----------
    grid_vwidth : float
        the velocity assumed when computing the grid in km/s
        this is important because tau = modeltau / width (see, e.g., 
        Draine 2011 textbook pgs 219-230)
    density : float
        Density!
    """

    if texgrid is None and taugrid is None:
        if path_to_texgrid == '' or path_to_taugrid=='':
            raise IOError("Must specify model grids to use.")
        else:
            taugrid = [pyfits.getdata(path_to_taugrid)]
            texgrid = [pyfits.getdata(path_to_texgrid)]
            hdr = pyfits.getheader(path_to_taugrid)
            zinds,yinds,xinds = np.indices(taugrid[0].shape)
            if 'CD1_1' in hdr:
                cd11 = 'CD1_1'
                cd22 = 'CD2_2'
            else:
                cd11 = 'CDELT1'
                cd22 = 'CDELT2'
            densityarr = (xinds+hdr['CRPIX1']-1)*hdr[cd11]+hdr['CRVAL1'] # log density
            columnarr  = (yinds+hdr['CRPIX2']-1)*hdr[cd22]+hdr['CRVAL2'] # log column
            temparr    = (zinds+hdr['CRPIX3']-1)*hdr['CDELT3']+hdr['CRVAL3'] # lin temperature
            minfreq = (218.,)
            maxfreq = (219.,)
    elif len(taugrid)==len(texgrid) and hdr is not None:
        minfreq,maxfreq,texgrid = zip(*texgrid)
        minfreq,maxfreq,taugrid = zip(*taugrid)
        zinds,yinds,xinds = np.indices(taugrid[0].shape)
        if 'CD1_1' in hdr:
            cd11 = 'CD1_1'
            cd22 = 'CD2_2'
        else:
            cd11 = 'CDELT1'
            cd22 = 'CDELT2'
        densityarr = (xinds+hdr['CRPIX1']-1)*hdr[cd11]+hdr['CRVAL1'] # log density
        columnarr  = (yinds+hdr['CRPIX2']-1)*hdr[cd22]+hdr['CRVAL2'] # log column
        temparr    = (zinds+hdr['CRPIX3']-1)*hdr['CDELT3']+hdr['CRVAL3'] # lin temperature
    else:
        raise Exception
    
    # Convert X-units to frequency in GHz
    xarr = xarr.as_unit('Hz', quiet=True)

    #tau_nu_cumul = np.zeros(len(xarr))

    gridval1 = np.interp(density, densityarr[0,0,:], xinds[0,0,:])
    gridval2 = np.interp(column, columnarr[0,:,0], yinds[0,:,0])
    gridval3 = np.interp(temperature, temparr[:,0,0], zinds[:,0,0])
    if np.isnan(gridval1) or np.isnan(gridval2) or np.isnan(gridval3):
        raise ValueError("Invalid column/density")

    if scipyOK:
        # this is mostly a trick for speed: slice so you only have two thin layers to interpolate
        # between
        #slices = [density_gridnumber] + [slice(np.floor(gv),np.floor(gv)+2) for gv in (gridval2,gridval1)]
        slices = [slice(np.floor(gridval3),np.floor(gridval3)+2),
                  slice(np.floor(gridval2),np.floor(gridval2)+2),
                  slice(np.floor(gridval1),np.floor(gridval1)+2)
                  ]
        tau = [scipy.ndimage.map_coordinates(tg[slices],
            np.array([[gridval3%1],[gridval2%1],[gridval1%1]]),order=1) for tg in taugrid]
        tex = [scipy.ndimage.map_coordinates(tg[slices],
            np.array([[gridval3%1],[gridval2%1],[gridval1%1]]),order=1) for tg in texgrid]
    else:
        raise ImportError("Couldn't import scipy, therefore cannot interpolate")
    #tau = modelgrid.line_params_2D(gridval1,gridval2,densityarr,columnarr,taugrid[temperature_gridnumber,:,:])
    #tex = modelgrid.line_params_2D(gridval1,gridval2,densityarr,columnarr,texgrid[temperature_gridnumber,:,:])

    if verbose:
        for ta,tk in zip(tau,tex):
            print("density %20.12g temperature %20.12g column %20.12g: tau %20.12g tex %20.12g" % (density, temperature, column, ta, tk))

    if debug:
        import pdb; pdb.set_trace()

    spec = np.sum([
        (formaldehyde_mm_vtau(xarr, Tex=float(tex[ii]), tau=float(tau[ii]),
            xoff_v=xoff_v, width=width, **kwargs)
        * (xarr.as_unit('GHz').value>minfreq[ii]) * 
         (xarr.as_unit('GHz').value<maxfreq[ii])) for ii in xrange(len(tex))],
                axis=0)
  
    return spec
Beispiel #52
0
    def __init__(self, specfit, targetfig, toolfig=None, nsubplots=12):
        """
        *targetfig*
            The figure instance to adjust

        *toolfig*
            The figure instance to embed the subplot tool into. If
            None, a default figure will be created. If you are using
            this from the GUI
        """

        self.targetfig = targetfig
        self.specfit = specfit
        self.baseline = specfit.Spectrum.baseline
        self.plotter = specfit.Spectrum.plotter

        from matplotlib import pyplot

        if toolfig is None:
            tbar = matplotlib.rcParams['toolbar'] # turn off the navigation toolbar for the toolfig
            matplotlib.rcParams['toolbar'] = 'None'
            self.toolfig = pyplot.figure(figsize=(6,3))
            self.toolfig.canvas.set_window_title("Fit Tools for "+targetfig.canvas.manager.window.title())
            self.toolfig.subplots_adjust(top=0.9,left=0.05,right=0.95)
            matplotlib.rcParams['toolbar'] = tbar
        else:
            self.toolfig = toolfig
            self.toolfig.subplots_adjust(left=0.0, right=1.0)


        #bax = self.toolfig.add_axes([0.6, 0.05, 0.15, 0.075])
        #self.buttonrefresh = Button(bax, 'Refresh')

        # buttons ruin everything.
        # fax = self.toolfig.add_axes([0.1, 0.05, 0.15, 0.075])
        # self.buttonfit = Button(fax, 'Fit')
        # 
        # resetax = self.toolfig.add_axes([0.7, 0.05, 0.15, 0.075])
        # self.buttonreset = Button(resetax, 'Reset')

        # resetblax = self.toolfig.add_axes([0.3, 0.05, 0.15, 0.075])
        # self.buttonresetbl = Button(resetblax, 'Reset BL')

        # resetfitax = self.toolfig.add_axes([0.5, 0.05, 0.15, 0.075])
        # self.buttonresetfit = Button(resetfitax, 'Reset fit')

        def refresh(event):
            thisdrawon = self.drawon

            self.drawon = False

            self.update_information()

            # draw the canvas
            self.drawon = thisdrawon
            if self.drawon:
                self.toolfig.canvas.draw()
                self.targetfig.canvas.draw()

        def fit(event):
            self.specfit.button3action(event)

        def reset_fit(event):
            self.specfit.guesses = []
            self.specfit.npeaks = 0
            self.specfit.includemask[:] = True
            self.refresh(event)

        def reset_baseline(event):
            self.baseline.unsubtract()
            self.refresh(event)

        def reset(event):
            reset_baseline(event)
            reset_fit(event)
            self.plotter()
            self.refresh(event)

        # during refresh there can be a temporary invalid state
        # depending on the order of the refresh so we turn off
        # validation for the refreshting
        #validate = self.toolfig.subplotpars.validate
        #self.toolfig.subplotpars.validate = False
        #self.buttonrefresh.on_clicked(refresh)
        #self.toolfig.subplotpars.validate = validate

        # these break everything.
        # self.buttonfit.on_clicked(fit)
        # self.buttonresetfit.on_clicked(reset_fit)
        # self.buttonresetbl.on_clicked(reset_baseline)
        # self.buttonreset.on_clicked(reset)


        #menuitems = []
        #for label in ('polynomial','blackbody','log-poly'):
        #    def on_select(item):
        #        print 'you selected', item.labelstr
        #    item = MenuItem(fig, label, props=props, hoverprops=hoverprops,
        #                    on_select=on_select)
        #    menuitems.append(item)

        #menu = Menu(fig, menuitems)


        self.axes = [self.toolfig.add_subplot(nsubplots,1,spnum, frame_on=False, navigate=False, xticks=[], yticks=[]) 
                for spnum in xrange(1,nsubplots+1)]
        #self.axes = self.toolfig.add_axes([0,0,1,1])

        self.use_axes = [0,1,2,4,5,6,7,8,9,10,11]
        self.labels = dict([(axnum,None) for axnum in self.use_axes])
        self.update_information()

        self.targetfig.canvas.mpl_connect('button_press_event',self.refresh)
        self.targetfig.canvas.mpl_connect('key_press_event',self.refresh)
        self.targetfig.canvas.mpl_connect('draw_event',self.refresh)
Beispiel #53
0
def h2co_mm_radex(xarr,
        Temperature=25,
        logColumn=13,
        logDensity=4,
        xoff_v=0.0,
        width=1.0,
        grid_vwidth=1.0,
        gridbundle = None,
        debug=False,
        verbose=False,
        **kwargs):

    """
    Use a grid of RADEX-computed models to make a model line spectrum

    The RADEX models have to be available somewhere.
    OR they can be passed as arrays.  If as arrays, the form should be:
    texgrid = ((minfreq1,maxfreq1,texgrid1),(minfreq2,maxfreq2,texgrid2))

    xarr must be a SpectroscopicAxis instance
    xoff_v, width are both in km/s


    Parameters
    ----------
    grid_vwidth : float
        the velocity assumed when computing the grid in km/s
        this is important because tau = modeltau / width (see, e.g.,
        Draine 2011 textbook pgs 219-230)
    density : float
        Density!
    """

    # Convert X-units to frequency in GHz
    xarr = xarr.as_unit('Hz', quiet=True)
    Tex303,Tex322,Tex321,tau303,tau322,tau321 = gridbundle


    # if this gets too far different from 1, we are gonna have a Bad Time.
    scalefac = grid_vwidth/width

    tex = (Tex303(logColumn,logDensity,Temperature),
           Tex322(logColumn,logDensity,Temperature),
           Tex321(logColumn,logDensity,Temperature))
    tau =  (tau303(logColumn,logDensity,Temperature)*scalefac,
            tau322(logColumn,logDensity,Temperature)*scalefac,
            tau321(logColumn,logDensity,Temperature)*scalefac)
    if np.any(np.isnan(tex)) or np.any(np.isnan(tau)):
        raise ValueError("Invalid column/density")

    if verbose:
        for ta,tk in zip(tau,tex):
            print("density %20.12g temperature %20.12g column %20.12g: tau %20.12g tex %20.12g" % (logDensity, Temperature, logColumn, ta, tk))

    if debug:
        import pdb; pdb.set_trace()

# here there be physics
    ckms = 2.99792458e5
    freq_dict = {
        '303': 218.222192e9,
        '322': 218.475632e9,
        '321': 218.760066e9,
        }
    Tbg = 2.73 #because it totally is


    nu0 = np.array([ 218.222192e9, 218.475632e9,218.760066e9])
    nuwidth = [width/ckms*nu for nu in nu0]
    nuoff = [xoff_v/ckms*nu for nu in nu0]
    minfreq = nu0/1e9 - 0.25
    maxfreq = nu0/1e9 + 0.25
#    spec2 = np.zeros(len(xarr))
#    for ii in range(len(nu0)):
#        taunu = tau[ii]*np.exp(-(xarr+nuoff[ii]-nu0[ii])**2/(2.0*nuwidth[ii]**2))
#        spec2 = spec2 + (1-np.exp(-taunu))*tex[ii] + Tbg*(np.exp(-taunu)-1)  #second term assumes an ON-OFF

    spec = np.sum([
            (formaldehyde_mm_vtau(xarr, Tex=float(tex[ii]), tau=float(tau[ii]),
                                  xoff_v=xoff_v, width=width, **kwargs)
             * (xarr.as_unit('GHz')>minfreq[ii]) * (xarr.as_unit('GHz')<maxfreq[ii])) for ii in xrange(len(tex))],
                  axis=0)
#    import pdb
#    pdb.set_trace()


    return spec
Beispiel #54
0
def formaldehyde_mm_radex(xarr, 
        temperature=25,
        column=13,
        density=4,
        xoff_v=0.0,
        width=1.0, 
        grid_vwidth=1.0,
        texgrid=None,
        taugrid=None,
        hdr=None,
        path_to_texgrid='',
        path_to_taugrid='',
        debug=False,
        verbose=False,
        **kwargs):
    """
    Use a grid of RADEX-computed models to make a model line spectrum

    The RADEX models have to be available somewhere.
    OR they can be passed as arrays.  If as arrays, the form should be:
    texgrid = ((minfreq1,maxfreq1,texgrid1),(minfreq2,maxfreq2,texgrid2))

    xarr must be a SpectroscopicAxis instance
    xoff_v, width are both in km/s


    Parameters
    ----------
    grid_vwidth : float
        the velocity assumed when computing the grid in km/s
        this is important because tau = modeltau / width (see, e.g., 
        Draine 2011 textbook pgs 219-230)
    density : float
        Density!
    """

    if texgrid is None and taugrid is None:
        if path_to_texgrid == '' or path_to_taugrid=='':
            raise IOError("Must specify model grids to use.")
        else:
            taugrid = [pyfits.getdata(path_to_taugrid)]
            texgrid = [pyfits.getdata(path_to_texgrid)]
            hdr = pyfits.getheader(path_to_taugrid)
            zinds,yinds,xinds = np.indices(taugrid[0].shape)
            if 'CD1_1' in hdr:
                cd11 = 'CD1_1'
                cd22 = 'CD2_2'
            else:
                cd11 = 'CDELT1'
                cd22 = 'CDELT2'
            densityarr = (xinds+hdr['CRPIX1']-1)*hdr[cd11]+hdr['CRVAL1'] # log density
            columnarr  = (yinds+hdr['CRPIX2']-1)*hdr[cd22]+hdr['CRVAL2'] # log column
            temparr    = (zinds+hdr['CRPIX3']-1)*hdr['CDELT3']+hdr['CRVAL3'] # lin temperature
            minfreq = (218.,)
            maxfreq = (219.,)
    elif len(taugrid)==len(texgrid) and hdr is not None:
        minfreq,maxfreq,texgrid = zip(*texgrid)
        minfreq,maxfreq,taugrid = zip(*taugrid)
        zinds,yinds,xinds = np.indices(taugrid[0].shape)
        if 'CD1_1' in hdr:
            cd11 = 'CD1_1'
            cd22 = 'CD2_2'
        else:
            cd11 = 'CDELT1'
            cd22 = 'CDELT2'
        densityarr = (xinds+hdr['CRPIX1']-1)*hdr[cd11]+hdr['CRVAL1'] # log density
        columnarr  = (yinds+hdr['CRPIX2']-1)*hdr[cd22]+hdr['CRVAL2'] # log column
        temparr    = (zinds+hdr['CRPIX3']-1)*hdr['CDELT3']+hdr['CRVAL3'] # lin temperature
    else:
        raise Exception
    
    # Convert X-units to frequency in GHz
    xarr = xarr.as_unit('Hz', quiet=True)

    #tau_nu_cumul = np.zeros(len(xarr))

    gridval1 = np.interp(density, densityarr[0,0,:], xinds[0,0,:])
    gridval2 = np.interp(column, columnarr[0,:,0], yinds[0,:,0])
    gridval3 = np.interp(temperature, temparr[:,0,0], zinds[:,0,0])
    if np.isnan(gridval1) or np.isnan(gridval2) or np.isnan(gridval3):
        raise ValueError("Invalid column/density")

    if scipyOK:
        # this is mostly a trick for speed: slice so you only have two thin layers to interpolate
        # between
        #slices = [density_gridnumber] + [slice(np.floor(gv),np.floor(gv)+2) for gv in (gridval2,gridval1)]
        slices = [slice(np.floor(gridval3),np.floor(gridval3)+2),
                  slice(np.floor(gridval2),np.floor(gridval2)+2),
                  slice(np.floor(gridval1),np.floor(gridval1)+2)
                  ]
        tau = [scipy.ndimage.map_coordinates(tg[slices],
            np.array([[gridval3%1],[gridval2%1],[gridval1%1]]),order=1) for tg in taugrid]
        tex = [scipy.ndimage.map_coordinates(tg[slices],
            np.array([[gridval3%1],[gridval2%1],[gridval1%1]]),order=1) for tg in texgrid]
    else:
        raise ImportError("Couldn't import scipy, therefore cannot interpolate")
    #tau = modelgrid.line_params_2D(gridval1,gridval2,densityarr,columnarr,taugrid[temperature_gridnumber,:,:])
    #tex = modelgrid.line_params_2D(gridval1,gridval2,densityarr,columnarr,texgrid[temperature_gridnumber,:,:])

    if verbose:
        for ta,tk in zip(tau,tex):
            print("density %20.12g temperature %20.12g column %20.12g: tau %20.12g tex %20.12g" % (density, temperature, column, ta, tk))

    if debug:
        import pdb; pdb.set_trace()

    spec = np.sum([
        (formaldehyde_mm_vtau(xarr, Tex=float(tex[ii]), tau=float(tau[ii]),
            xoff_v=xoff_v, width=width, **kwargs)
        * (xarr.as_unit('GHz').value>minfreq[ii]) * 
         (xarr.as_unit('GHz').value<maxfreq[ii])) for ii in xrange(len(tex))],
                axis=0)
  
    return spec
Beispiel #55
0
def fitnh3tkin(input_dict, dobaseline=True, baselinekwargs={}, crop=False,
               cropunit=None, guessline='twotwo', tex=15, trot=20, column=15.0,
               fortho=0.66, tau=None, thin=False, quiet=False, doplot=True,
               fignum=1, guessfignum=2, smooth=False, scale_keyword=None,
               rebase=False, tkin=None, npeaks=1, guesses=None,
               guess_error=True, **kwargs):
    """
    Given a dictionary of filenames and lines, fit them together
    e.g. {'oneone':'G000.000+00.000_nh3_11.fits'}

    Parameters
    ----------
    input_dict : dict
        A dictionary in which the keys are the ammonia line names (e.g.,
        'oneone', 'twotwo', etc) and the values are either Spectrum objects
        or filenames of spectra
    dobaseline : bool
        Fit and subtract a baseline prior to fitting the model?
        Keyword arguments to `pyspeckit.spectrum.Spectrum.baseline` are
        specified in ``baselinekwargs``.
    baselinekwargs : dict
        The keyword arguments for the baseline
    crop : bool or tuple
        A range of values to crop the spectrum to.  The units are specified by
        ``cropunit``; the default ``None`` will use pixels.  If False, no
        cropping will be performed.
    cropunit : None or astropy unit
        The unit for the crop parameter
    guess_error : bool
        Use the guess line to estimate the error in all spectra?
    """
    if tkin is not None:
        if trot == 20 or trot is None:
            trot = tkin
        else:
            raise ValueError("Please specify trot, not tkin")
        warnings.warn("Keyword 'tkin' is deprecated; use trot instead", DeprecationWarning)

    spdict = dict([(linename, Spectrum(value, scale_keyword=scale_keyword))
                   if type(value) is str else (linename, value)
                   for linename, value in iteritems(input_dict)
                  ])
    splist = spdict.values()

    for transition, sp in spdict.items(): # required for plotting, cropping
        sp.xarr.convert_to_unit('km/s', velocity_convention='radio',
                                refX=pyspeckit.spectrum.models.ammonia.freq_dict[transition]*u.Hz,
                                quiet=True)

    if crop and len(crop) == 2:
        for sp in splist:
            sp.crop(*crop, unit=cropunit)

    if dobaseline:
        for sp in splist:
            sp.baseline(**baselinekwargs)

    if smooth and type(smooth) is int:
        for sp in splist:
            sp.smooth(smooth)

    spdict[guessline].specfit(fittype='gaussian', negamp=False, vheight=False,
                              guesses='moments')
    ampguess, vguess, widthguess = spdict[guessline].specfit.modelpars
    if widthguess < 0:
        raise ValueError("Width guess was < 0.  This is impossible.")
    print("RMS guess (errspec): ", spdict[guessline].specfit.errspec.mean())
    print("RMS guess (residuals): ", spdict[guessline].specfit.residuals.std())
    errguess = spdict[guessline].specfit.residuals.std()

    if rebase:
        # redo baseline subtraction excluding the centroid +/- about 20 km/s
        vlow = spdict[guessline].specfit.modelpars[1]-(19.8+spdict[guessline].specfit.modelpars[2]*2.35)
        vhigh = spdict[guessline].specfit.modelpars[1]+(19.8+spdict[guessline].specfit.modelpars[2]*2.35)
        for sp in splist:
            sp.baseline(exclude=[vlow, vhigh], **baselinekwargs)

    for sp in splist:
        if guess_error:
            sp.error[:] = errguess
        sp.xarr.convert_to_unit(u.GHz)

    if doplot:
        spdict[guessline].plotter(figure=guessfignum)
        spdict[guessline].specfit.plot_fit()

    spectra = Spectra(splist)
    spectra.specfit.npeaks = npeaks

    if tau is not None:
        if guesses is None:
            guesses = [a for i in xrange(npeaks) for a in
                       (trot+random.random()*i, tex, tau+random.random()*i,
                        widthguess+random.random()*i, vguess+random.random()*i,
                        fortho)]
        fittype = 'ammonia_tau_thin' if thin else 'ammonia_tau'
        spectra.specfit(fittype=fittype, quiet=quiet, guesses=guesses,
                        **kwargs)
    else:
        if guesses is None:
            guesses = [a for i in xrange(npeaks) for a in
                       (trot+random.random()*i, tex, column+random.random()*i,
                        widthguess+random.random()*i, vguess+random.random()*i,
                        fortho)]
        if thin:
            raise ValueError("'thin' keyword not supported for the generic ammonia model")
        spectra.specfit(fittype='ammonia', quiet=quiet, guesses=guesses,
                        **kwargs)

    if doplot:
        plot_nh3(spdict, spectra, fignum=fignum)

    return spdict, spectra
Beispiel #56
0
 def values(self):
     return [self._dict[self._dict_index[ii]] for ii in xrange(len(self))]
Beispiel #57
0
def formaldehyde_radex_tau(xarr, density=4, column=13, xoff_v=0.0, width=1.0,
                           grid_vwidth=1.0, grid_vwidth_scale=False,
                           taugrid=None, hdr=None, path_to_taugrid='',
                           temperature_gridnumber=3, debug=False,
                           verbose=False, return_hyperfine_components=False,
                           **kwargs):
    """
    Use a grid of RADEX-computed models to make a model line spectrum

     * uses hyperfine components
     * assumes *tau* varies but *tex* does not!

    The RADEX models have to be available somewhere.
    OR they can be passed as arrays.  If as arrays, the form should be:
    texgrid = ((minfreq1,maxfreq1,texgrid1),(minfreq2,maxfreq2,texgrid2))

    xarr must be a SpectroscopicAxis instance
    xoff_v, width are both in km/s

    grid_vwidth is the velocity assumed when computing the grid in km/s
    this is important because tau = modeltau / width (see, e.g.,
    Draine 2011 textbook pgs 219-230)
    grid_vwidth_scale is True or False: False for LVG, True for Sphere
    """

    if verbose:
        print("Parameters: dens=%f, column=%f, xoff=%f, width=%f" % (density, column, xoff_v, width))

    if taugrid is None:
        if path_to_taugrid=='':
            raise IOError("Must specify model grids to use.")
        else:
            taugrid = [pyfits.getdata(path_to_taugrid)]
            hdr = pyfits.getheader(path_to_taugrid)
            yinds,xinds = np.indices(taugrid[0].shape[1:])
            densityarr = (xinds+hdr['CRPIX1']-1)*hdr['CD1_1']+hdr['CRVAL1'] # log density
            columnarr  = (yinds+hdr['CRPIX2']-1)*hdr['CD2_2']+hdr['CRVAL2'] # log column
            minfreq = (4.8,)
            maxfreq = (5.0,)
    elif hdr is not None:
        minfreq,maxfreq,taugrid = zip(*taugrid)
        yinds,xinds = np.indices(taugrid[0].shape[1:])
        densityarr = (xinds+hdr['CRPIX1']-1)*hdr['CD1_1']+hdr['CRVAL1'] # log density
        columnarr  = (yinds+hdr['CRPIX2']-1)*hdr['CD2_2']+hdr['CRVAL2'] # log column
    else:
        raise Exception

    # Convert X-units to frequency in GHz
    xarr = xarr.as_unit('Hz', quiet=True)

    gridval1 = np.interp(density, densityarr[0,:], xinds[0,:])
    gridval2 = np.interp(column, columnarr[:,0], yinds[:,0])
    if np.isnan(gridval1) or np.isnan(gridval2):
        raise ValueError("Invalid column/density")

    if scipyOK:
        slices = [temperature_gridnumber] + [slice(np.floor(gv),np.floor(gv)+2) for gv in (gridval2,gridval1)]
        tau = [scipy.ndimage.map_coordinates(tg[slices],np.array([[gridval2%1],[gridval1%1]]),order=1) for tg in taugrid]
    else:
        raise ImportError("Couldn't import scipy, therefore cannot interpolate")

    # let the hyperfine module determine the hyperfine components, and pass all of them here
    spec_components = [(formaldehyde_vtau(xarr.as_unit('Hz', quiet=True),
        tau=float(tau[ii]), xoff_v=xoff_v, width=width,
        return_tau=True, return_hyperfine_components=True, **kwargs) *
            (xarr.as_unit('GHz')>minfreq[ii]) *
            (xarr.as_unit('GHz')<maxfreq[ii]))
                for ii in  xrange(len(tau))]

    # get an array of [n_lines, n_hyperfine, len(xarr)]
    if return_hyperfine_components:
        return np.array(spec_components).sum(axis=0)
    else:
        return np.sum(spec_components, axis=0).sum(axis=0)
Beispiel #58
0
    def multigaussfit(self,
                      xax,
                      data,
                      npeaks=1,
                      err=None,
                      params=[1, 0, 1],
                      fixed=[False, False, False],
                      limitedmin=[False, False, True],
                      limitedmax=[False, False, False],
                      minpars=[0, 0, 0],
                      maxpars=[0, 0, 0],
                      quiet=True,
                      shh=True,
                      veryverbose=False,
                      negamp=None,
                      tied=['', '', ''],
                      parinfo=None,
                      debug=False,
                      **kwargs):
        """
        An improvement on onepeakgaussfit.  Lets you fit multiple gaussians.

        Inputs:
           xax - x axis
           data - y axis
           npeaks - How many gaussians to fit?  Default 1 (this could supersede onepeakgaussfit)
           err - error corresponding to data

         These parameters need to have length = 3*npeaks.  If npeaks > 1 and length = 3, they will
         be replicated npeaks times, otherwise they will be reset to defaults:
           params - Fit parameters: [amplitude, offset, width] * npeaks
                  If len(params) % 3 == 0, npeaks will be set to len(params) / 3
           fixed - Is parameter fixed?
           limitedmin/minpars - set lower limits on each parameter (default: width>0)
           limitedmax/maxpars - set upper limits on each parameter
           tied - link parameters together

           quiet - should MPFIT output each iteration?
           shh - output final parameters?

           kwargs are passed to mpfit

        Returns:
           Fit parameters
           Model
           Fit errors
           chi2
        """

        if len(params) != npeaks and (len(params) / 3) > npeaks:
            self.npeaks = len(params) / 3
        else:
            self.npeaks = npeaks

        if isinstance(params, numpy.ndarray): params = params.tolist()

        # make sure all various things are the right length; if they're not, fix them using the defaults
        # multiformaldehydefit should process negamp directly if kwargs.has_key('negamp') is False: kwargs['negamp'] = None
        pardict = {
            "params": params,
            "fixed": fixed,
            "limitedmin": limitedmin,
            "limitedmax": limitedmax,
            "minpars": minpars,
            "maxpars": maxpars,
            "tied": tied
        }
        for parlistname in pardict:
            parlist = pardict[parlistname]
            if len(parlist) != 3 * self.npeaks:
                # if you leave the defaults, or enter something that can be multiplied by 3 to get to the
                # right number of formaldehydeians, it will just replicate
                if veryverbose:
                    print("Correcting length of parameter %s" % parlistname)
                if len(parlist) == 3:
                    parlist *= self.npeaks
                elif parlistname == "params":
                    parlist[:] = [1, 0, 1] * self.npeaks
                elif parlistname == "fixed":
                    parlist[:] = [False, False, False] * self.npeaks
                elif parlistname == "limitedmax":
                    if negamp is None:
                        parlist[:] = [False, False, False] * self.npeaks
                    elif negamp is False:
                        parlist[:] = [False, False, False] * self.npeaks
                    else:
                        parlist[:] = [True, False, False] * self.npeaks
                elif parlistname == "limitedmin":
                    if negamp is None:
                        parlist[:] = [
                            False, False, True
                        ] * self.npeaks  # Lines can't have negative width!
                    elif negamp is False:
                        parlist[:] = [True, False, True] * self.npeaks
                    else:
                        parlist[:] = [False, False, True] * self.npeaks
                elif parlistname == "minpars" or parlistname == "maxpars":
                    parlist[:] = [0, 0, 0] * self.npeaks
                elif parlistname == "tied":
                    parlist[:] = ['', '', ''] * self.npeaks

        # mpfit doesn't recognize negamp, so get rid of it now that we're done setting limitedmin/max and min/maxpars
        #if kwargs.has_key('negamp'): kwargs.pop('negamp')

        def mpfitfun(x, y, err):
            if err is None:

                def f(p, fjac=None):
                    return [0, (y - self.n_gaussian(pars=p)(x))]
            else:

                def f(p, fjac=None):
                    return [0, (y - self.n_gaussian(pars=p)(x)) / err]

            return f

        if xax is None:
            xax = numpy.arange(len(data))

        parnames = {0: "AMPLITUDE", 1: "SHIFT", 2: "WIDTH"}

        if parinfo is None:
            parinfo = [{
                'n': ii,
                'value': params[ii],
                'limits': [minpars[ii], maxpars[ii]],
                'limited': [limitedmin[ii], limitedmax[ii]],
                'fixed': fixed[ii],
                'parname': parnames[ii % 3] + str(ii / 3),
                'error': ii,
                'tied': tied[ii]
            } for ii in xrange(len(params))]

        if veryverbose:
            print("GUESSES: ")
            print("\n".join(
                ["%s: %s" % (p['parname'], p['value']) for p in parinfo]))

        if debug:
            for p in parinfo:
                print(p)

        mp = mpfit(mpfitfun(xax, data, err),
                   parinfo=parinfo,
                   quiet=quiet,
                   **kwargs)
        mpp = mp.params
        if mp.perror is not None: mpperr = mp.perror
        else: mpperr = mpp * 0
        chi2 = mp.fnorm

        if mp.status == 0:
            raise Exception(mp.errmsg)

        if not shh:
            print("Fit status: ", mp.status)
            print("Fit error message: ", mp.errmsg)
            print("Fit message: ", mpfit_messages[mp.status])
            print("Final fit values: ")
            for i, p in enumerate(mpp):
                parinfo[i]['value'] = p
                print(parinfo[i]['parname'], p, " +/- ", mpperr[i])
            print("Chi2: ", mp.fnorm, " Reduced Chi2: ", mp.fnorm / len(data),
                  " DOF:",
                  len(data) - len(mpp))

        self.mp = mp
        self.mpp = mpp
        self.mpperr = mpperr
        self.model = self.n_gaussian(pars=mpp)(xax)
        return mpp, self.n_gaussian(pars=mpp)(xax), mpperr, chi2
Beispiel #59
0
 def keys(self):
     return [self._dict_index[ii] for ii in xrange(len(self))]