Example #1
0
File: interp.py Project: nhmc/H2
def fit_spline(x, y, bins=4, estimator=np.median):
    """ Find a smooth function that approximates `x`, `y`.

    `bins` is the number of bins into which the sample is split. Returns
    a function f(x) that approximates y from min(x) to max(x).

    Notes
    -----
    The sample is split into bins number of sub-samples with evenly
    spaced x values. The median x and y value within each subsample is
    measured, and a cubic spline is drawn through these subsample
    median points.

    `x` must be sorted lowest -> highest, but need not be evenly spaced.
    """
    x,y = map(np.asarray, (x,y))
    good = ~np.isnan(x)
    good &= ~np.isnan(y)
    x = x[good]
    y = y[good]
    binedges = np.linspace(x.min(), x.max(), bins+1)
    medvals = []
    cbins = []
    for x0,x1 in zip(binedges[:-1], binedges[1:]):
        cond = between(x, x0, x1)
        if not cond.any():
            continue
        cbins.append(estimator(x[cond]))
        medvals.append(estimator(y[cond]))

    if len(cbins) < 3:
        raise RuntimeError('Too few bins')
    return AkimaSpline(cbins, medvals)
Example #2
0
def editRow(row):
    gotChoice = False
    while not gotChoice:
        utilities.clearScreen()
        #print(row); input(); quit()
        print('1) Solution Type: %s' % row[2][1][1])
        print('2) Distance:      %s' % row[0])
        interval = utilities.format_time_string(row[1])
        if interval[0] == 'interval':
            print('3) Time:          %s' % interval[1])
        else: pass   #-> there should be no error from this function
                     #   call - the time is guaranteed to be a float. 
        choice = input('Which line do you wish to edit ([r] to return)? ')
        if choice.lower() == 'r':
            gotChoice = True
        elif utilities.isInt(choice) and utilities.between(int(choice), 1, 3):
                gotChoice = True
        else: input('%s is not a valid choice: press [ENTER] to continue' % choice)

    if choice == 'r': return

    if choice == '3':
        row[1] = get_time()
        editRow(row)
    elif choice == '2':
        row[0] = get_distance()
        editRow(row)
    elif choice == '1':
        input('rutwro')
Example #3
0
def get_row():
    choice = input('Which leg? ')
    if choice == 'q': return(0)
    if len(choice) > 0 and utilities.isInt(choice):
            if utilities.between(int(choice), 1, len(result_set)): return(result_set[int(choice) - 1])
            else: input('%s is not a valid choice.  Press [Enter] to continue (or [q] to quit)' % choice)
    else: input('You must choose a leg between %d through %d.  Press [Enter] to continue (or [q] to quit)' % (1, len(result_set)))
Example #4
0
File: spec.py Project: nhmc/H2
def plotlines(z, ax, atmos=None, lines=None, labels=False, ls="dotted", color="k", trim=False, fontsize=10, **kwargs):
    """ Draw vertical dotted lines showing expected positions of
    absorption and emission lines, given a redshift.

    Parameters
    ----------
    atmos : list of float pairs, or True (None)
      Regions of atmospheric absorption to plot. If True, it uses an
      internal list of regions.
    lines : stuctured array, optional
      If given, it must be a record array with fields 'name' and 'wa'.

    Returns the mpl artists representing the lines.
    """
    if lines is None:
        lines = readtxt(DATAPATH + "linelists/galaxy_lines", names="wa,name,select")
    else:
        lines = np.rec.fromrecords([(l["name"], l["wa"]) for l in lines], names="name,wa")
    autoscale = ax.get_autoscale_on()
    if autoscale:
        ax.set_autoscale_on(False)
    artists = []
    w0, w1 = ax.get_xlim()
    wa = lines.wa * (z + 1)
    if trim:
        c0 = between(wa, w0, w1)
        wa = wa[c0]
        lines = lines[c0]
    artists.append(axvlines(wa, ax=ax, ls=ls, color=color, **kwargs))
    if labels:
        for i in range(3):
            for w, l in zip(wa[i::3], lines[i::3]):
                if not (w0 < w < w1) and trim:
                    continue
                # name = l.name + '%.2f' % l.wa
                name = l.name
                artists.append(
                    puttext(
                        w,
                        0.7 + i * 0.08,
                        name,
                        ax,
                        xcoord="data",
                        alpha=1,
                        fontsize=fontsize,
                        rotation=90,
                        ha="right",
                        color=color,
                    )
                )
    if atmos:
        if atmos == True:
            atmos = None
        artists.append(plotatmos(ax, atmos=atmos))
    if autoscale:
        ax.set_autoscale_on(True)

    return artists
Example #5
0
File: fitcont.py Project: nhmc/H2
    def update(self):
        """ Calculates the new continuum, residuals and updates the plots.


        Updates the following attributes:

          self.markers
          self.continuum
        """
        wa,fl,er = (self.spec[key] for key in 'wa fl er'.split())
        co = np.empty(len(wa))
        co.fill(np.nan)
        for b0,b1 in zip(self.breaks[:-1], self.breaks[1:]):
            cpts = [(x,y) for x,y in self.contpoints if b0 <= x <= b1]
            if len(cpts) == 0:
                continue 
            spline = AkimaSpline(*zip(*cpts))
            i,j = wa.searchsorted([b0,b1])
            co[i:j] = spline(wa[i:j])
        
        resid = (fl - co) / er
        # histogram
        bins = np.arange(0, 5+0.1, 0.2)
        w0,w1 = self.fig.axes[1].get_xlim()
        x,_ = np.histogram(resid[between(wa, w0, w1)],
                           bins=bins)
        b = np.repeat(bins, 2)
        X = np.concatenate([[0], np.repeat(x,2), [0]])
        Xmax = X.max()    
        X = 0.05 * X / Xmax
        self.markers['hist_left'].set_data(X, b)

        self.markers['contpoints'].set_data(zip(*self.contpoints))
        nbin = self.nbin
        self.markers['cont'].set_data(wa[::nbin], co[::nbin])
        self.markers['resid'].set_data(wa[::nbin], resid[::nbin])
        if self.smoothby is not None:
            sfl = convolve_psf(fl, self.smoothby)
            self.art_fl.set_data(wa, sfl)
        else:
            self.art_fl.set_data(wa, fl)
        self.continuum = co
        saveobj('_knots.sav', self.contpoints, overwrite=True)
        self.fig.canvas.draw()
Example #6
0
File: absorb.py Project: nhmc/H2
def calc_iontau(wa, ion, zp1, logN, b, debug=False, ticks=False, maxdv=1000.,
                label_tau_threshold=0.01, vpad=500., verbose=True):
    """ Returns tau values at each wavelength for transitions in ion.

    Parameters
    ----------
    wa : array of floats
      wavelength array
    ion : atom.data entry
      ion entry from readatom output dictionary
    zp1 : float
      redshift + 1
    logN : float
      log10(column density in cm**-2)
    b : float
      b parameter (km/s).  Assumes thermal broadening.
    maxdv : float (default 1000)
      For performance reasons, only calculate the Voigt profile for a
      single line to +/- maxdv.  Increase this if you expect DLA-type
      extended wings. None for no maximum.
    vpad : float (default 500)
      Include transitions that are within vpad km/s of either edge of
      the wavelength array.

    Returns
    -------
    tau : array of floats
      Array of optical depth values.
    """
    z = zp1 - 1
    if debug:
        i = int(len(wa)/2)
        psize =  c_kms * (wa[i] - wa[i-1]) / wa[i]
        print 'approx pixel width %.1f km/s at %.1f Ang' % (psize, wa[i])

    #select only ions with redshifted central wavelengths inside wa,
    #+/- the padding velocity range vpad.
    obswavs = ion.wa * zp1
    wmin = wa[0] * (1 - vpad / c_kms)
    wmax = wa[-1] * (1 + vpad / c_kms)
    trans = ion[between(obswavs, wmin, wmax)]
    if debug:
        if len(trans) == 0:
            print 'No transitions found overlapping with wavelength array'

    tickmarks = []
    sumtau = np.zeros_like(wa)
    i0 = i1 = None 
    for i,(wav0,osc,gam) in enumerate(trans):
        refwav = wav0 * zp1
        dv = (wa - refwav) / refwav * c_kms
        if maxdv is not None:
            i0,i1 = dv.searchsorted([-maxdv, maxdv])
        tau = calctau(dv[i0:i1], wav0, osc, gam, logN, btemp=b,
                      debug=debug, verbose=verbose)
        if ticks and tau.max() > label_tau_threshold:
            tickmarks.append((refwav, z, wav0, i))
        sumtau[i0:i1] += tau

    if ticks:
        return sumtau, tickmarks
    else:
        return sumtau