Ejemplo n.º 1
0
Archivo: data.py Proyecto: vlslv/pwkit
    def plot_lightcurve (self, ccd_id=None, bin_energies=False):
        # XXX CIAO COPY/PASTE DOES THIS EVEN WORK???
        import omega as om
        from ...bblocks import tt_bblock
        from ..ciao.data import tight_bounds

        if ccd_id is None:
            if len (self.gti) != 1:
                raise Exception ('must specify ccd_id')
            ccd_id = list(self.gti.keys())[0]

        kev = self.events['pi'] * 1e-3 # XXXXXXX
        vb = om.layout.VBox (2)

        if kev.size == 0:
            vb[0] = om.RectPlot()
            vb[1] = om.RectPlot()
            tmin = self.gti[ccd_id]['start_dmjd'].min()
            tmax = self.gti[ccd_id]['stop_dmjd'].max()
            if np.isnan(tmin):
                tmin, tmax = -1., 1.
            emin, emax = -1., 1.
            rmin, rmax = -1., 1.
        else:
            bbinfo = tt_bblock (
                self.gti[ccd_id]['start_dmjd'],
                self.gti[ccd_id]['stop_dmjd'],
                self.events['dmjd'].sort_values(),
                intersect_with_bins = True,
            )
            cps = bbinfo.rates / 86400

            tmin, tmax = tight_bounds (bbinfo.ledges[0], bbinfo.redges[-1])
            emin, emax = tight_bounds (kev.min (), kev.max ())
            rmin, rmax = tight_bounds (cps.min (), cps.max ())

            vb[0] = om.RectPlot ()
            csp = om.rect.ContinuousSteppedPainter (keyText='%d events' % (self.events.shape[0]))
            csp.setFloats (np.concatenate ((bbinfo.ledges, bbinfo.redges[-1:])),
                           np.concatenate ((cps, [0])))
            vb[0].add (csp)

            if bin_energies:
                vb[1] = self._plot_binned_event_energies(
                    bbinfo,
                    energy_scale = 1e-3,
                    dsn = 0
                )
            else:
                vb[1] = om.quickXY (self.events['dmjd'], kev, None, lines=0)

        vb[0].setBounds (tmin, tmax, rmin, rmax)
        vb[0].setYLabel ('Count rate (ct/s)')
        vb[0].bpainter.paintLabels = False
        self._plot_add_gtis (vb[0], ccd_id)

        vb[1].setBounds (tmin, tmax, emin, emax)
        vb[1].setLabels ('MJD - %d' % self.mjd0, 'Energy (keV)')
        self._plot_add_gtis (vb[1], ccd_id)
        return vb
Ejemplo n.º 2
0
def demo_divine_figure_2a():
    """If I type in the coefficients exactly as printed in the paper, the results
    at L = 7.2 disagree substantially with what's published in the paper. I've
    checked my code over and I think everything is working right and typed in
    correctly, so I suspect that there's a typo in the table of coefficients.
    If I change the a0 coefficient at L = 7.2 from 6.39 to 5.8, the plot in
    this figure looks much closer to the original. So that's what I've done.

    The position of the E > 21 MeV curve at L = 16 is also off compared to the
    figure in the paper. It is less obvious how to patch up that problem, and
    it feels less urgent, so I'm not trying to deal with that at the moment.

    """
    import omega as om

    L = np.array([
        1.09, 1.55, 1.75, 1.90, 2.00, 2.10, 2.40, 2.60, 2.80, 2.85, 3.20, 3.60,
        6.2, 7.2, 9.00, 11.0, 12.0, 14.0, 16.0
    ])

    moment = 4.255

    p = om.RectPlot()

    for E in [0.1, 3., 21]:
        # Note: ignoring augmented field strength at L > 20
        B = moment * L**-3
        J = inner_radbelt_e_omnidirectional_integ_flux(moment, L, B, E)[0]
        ok = np.isfinite(J)
        p.addXY(L[ok], J[ok], 'E = %.1f' % E)

    p.setLinLogAxes(False, True)
    p.setBounds(0, 16, 3e4, 3e9)
    p.setLabels('McIlwain L', 'Omnidirectional integral flux (cm^-2 s^-1)')
    return p
Ejemplo n.º 3
0
def main():
    import omega as om
    from pwkit.ndshow_gtk3 import cycle, view

    ###xg, yg, grid1 = calculate_dynat(n_pseudo_particles=2048, n_steps=30000)
    ###xg, yg, grid1 = calculate_fixed(n_pseudo_particles=16384, delta_t=0.00001)
    ###xg, yg, grid1 = calculate_debug(n_pseudo_particles=4096, n_steps=10000, delta_t=0.00001)
    ###_, _, grid2 = calculate(delta_t=0.00005)

    y_bins = 40
    y_edges = np.linspace(YMIN, YMAX, y_bins + 1)
    y_centers = 0.5 * (y_edges[1:] + y_edges[:-1])
    yg = y_centers.reshape((-1, 1))

    x_bins = 40
    x_edges = np.linspace(XMIN, XMAX, x_bins + 1)
    x_centers = 0.5 * (x_edges[1:] + x_edges[:-1])
    xg = x_centers.reshape((1, -1))

    rho = np.sqrt(np.log(xg / x0)**2 + np.log(yg / y0)**2) / u0
    exact = ((xg * y0 / (x0 * yg))**(1. / (2 * u0 * D0)) *
             k0(rho * np.sqrt(1 + D0**2 * u0**2) / (np.sqrt(2) * D0)) /
             (2 * np.pi * D0 * u0**2 * np.sqrt(xg * yg * x0 * y0)))

    ###grid1 *= np.percentile(exact, 95) / np.percentile(grid1, 95)

    ###cycle([exact[::-1], grid1[::-1]], yflip=True)

    view(exact[::-1], yflip=True)

    p = om.RectPlot()
    p.addXY(xg, exact[10], 'exact')
    ###p.addXY(xg, grid1[10], 'mine')
    p.show()
Ejemplo n.º 4
0
    def plot(self, ispw, amp=True):
        import omega as om

        p = om.RectPlot()

        for iant, ipol in sorted(six.iterkeys(self.antpols)):
            for this_ispw, isoln in self.antpols[iant, ipol]:
                if this_ispw != ispw:
                    continue

                f = self.flags[ipol, :, isoln]
                w = np.where(~f)[0]

                if amp:
                    v = np.abs(self.vals[ipol, :, isoln])
                else:
                    v = np.angle(self.vals[ipol, :, isoln], deg=True)

                for s in numutil.slice_around_gaps(w, 1):
                    wsub = w[s]

                    if wsub.size == 0:
                        continue  # Should never happen, but eh.

                    lines = (wsub.size > 1)
                    p.addXY(wsub, v[wsub], None, lines=lines, dsn=iant)

        return p
Ejemplo n.º 5
0
def summers05_figure_1():
    import omega as om

    alpha_star = 0.16
    x_m = 0.35
    delta_x = 0.15
    R = 8.5e-8
    Omega_e = 59941  # = 2 * np.pi * 9540
    max_wave_lat = 15 * np.pi / 180

    degrees = np.linspace(0.1, 89.9, 100)
    sinas = np.sin(degrees * np.pi / 180)

    vb = om.layout.VBox(3)
    vb[0] = paa = om.RectPlot()
    vb[1] = pap = om.RectPlot()
    vb[2] = ppp = om.RectPlot()

    for kev in 100, 300, 1000, 3000:
        E = kev / 511.  # normalized to mc^2 = 511 keV
        Daa, Dap, Dpp = compute_local(E,
                                      sinas,
                                      Omega_e,
                                      alpha_star,
                                      R,
                                      x_m,
                                      delta_x,
                                      max_wave_lat,
                                      'R',
                                      wave_filtering='f',
                                      p_scaled=True)
        paa.addXY(degrees, Daa, str(kev))
        pap.addXY(degrees, np.abs(Dap), str(kev))
        ppp.addXY(degrees, Dpp, str(kev))

    for p in paa, pap, ppp:
        p.setLinLogAxes(False, True)
        p.setBounds(0, 90, 1e-8, 0.1)
        p.setXLabel('Pitch angle (degrees)')

    paa.setYLabel('D_aa')
    pap.setYLabel('|D_ap|/p')
    ppp.setYLabel('D_pp/p^2')

    return vb
Ejemplo n.º 6
0
def make_qq_plot(kev, obs, mdl, unit, key_text):
    """Make a quantile-quantile plot comparing events and a model.

    *kev*
      A 1D, sorted array of event energy bins measured in keV.
    *obs*
      A 1D array giving the number or rate of events in each bin.
    *mdl*
      A 1D array giving the modeled number or rate of events in each bin.
    *unit*
      Text describing the unit in which *obs* and *mdl* are measured; will
      be shown on the plot axes.
    *key_text*
      Text describing the quantile-quantile comparison quantity; will be
      shown on the plot legend.
    Returns:
      An :class:`omega.RectPlot` instance.

    *TODO*: nothing about this is Sherpa-specific. Same goes for some of the
    plotting routines in :mod:`pkwit.environments.casa.data`; might be
    reasonable to add a submodule for generic X-ray-y plotting routines.

    """
    import omega as om

    kev = np.asarray(kev)
    obs = np.asarray(obs)
    mdl = np.asarray(mdl)

    c_obs = np.cumsum(obs)
    c_mdl = np.cumsum(mdl)
    mx = max(c_obs[-1], c_mdl[-1])

    p = om.RectPlot()
    p.addXY([0, mx], [0, mx], '1:1')
    p.addXY(c_mdl, c_obs, key_text)

    # HACK: this range of numbers is chosen to give reasonable sampling for my
    # sources, which are typically quite soft.
    locs = np.array([0, 0.05, 0.08, 0.11, 0.17, 0.3, 0.4, 0.7, 1
                     ]) * (kev.size - 2)
    c0 = mx * 1.05
    c1 = mx * 1.1

    for loc in locs:
        i0 = int(np.floor(loc))
        frac = loc - i0
        kevval = (1 - frac) * kev[i0] + frac * kev[i0 + 1]
        mdlval = (1 - frac) * c_mdl[i0] + frac * c_mdl[i0 + 1]
        obsval = (1 - frac) * c_obs[i0] + frac * c_obs[i0 + 1]
        p.addXY([mdlval, mdlval], [c0, c1], '%.2f keV' % kevval, dsn=2)
        p.addXY([c0, c1], [obsval, obsval], None, dsn=2)

    p.setLabels('Cumulative model ' + unit, 'Cumulative data ' + unit)
    p.defaultKeyOverlay.vAlign = 0.3
    return p
Ejemplo n.º 7
0
def phase_plot(df,
               period,
               yofs=200,
               phofs=0.,
               lines=False,
               errs=True,
               psf='default',
               byrot=True):
    if psf == 'default':
        psf = om.stamps.Circle
    elif psf is None:
        psf = lambda: None

    df['nrot'] = (df['mjd'] - df['mjd'].min()) / period
    df['ph'] = (df['nrot'] + phofs) % 1.

    nmax = int(np.floor(df['nrot'].max()))

    p = om.RectPlot()
    nplot = 0

    for i in range(nmax + 1):
        subset = (df['nrot'] >= i) & (df['nrot'] < i + 1)
        if not subset.any():
            continue

        x = df[subset]['ph']
        u = df[subset]['ure']

        if byrot:
            y = df[subset]['re'] + i * yofs
        else:
            y = df[subset]['re'] + nplot * yofs

        if errs:
            p.addXYErr(
                x,
                y,
                u,
                None,
                lines=lines,
                pointStamp=psf(),
            )
        else:
            p.addXY(
                x,
                y,
                None,
                lines=lines,
                pointStamp=psf(),
            )

        nplot += 1

    p.setBounds(-0.05, 1.05)
    return p
Ejemplo n.º 8
0
def make_multi_qq_plots(arrays, key_text):
    """Make a quantile-quantile plot comparing multiple sets of events and models.

    *arrays*
      X.
    *key_text*
      Text describing the quantile-quantile comparison quantity; will be
      shown on the plot legend.
    Returns:
      An :class:`omega.RectPlot` instance.

    *TODO*: nothing about this is Sherpa-specific. Same goes for some of the
    plotting routines in :mod:`pkwit.environments.casa.data`; might be
    reasonable to add a submodule for generic X-ray-y plotting routines.

    *TODO*: Some gross code duplication here.

    """
    import omega as om

    p = om.RectPlot()
    p.addXY([0, 1.], [0, 1.], '1:1')

    for index, array in enumerate(arrays):
        kev, obs, mdl = array
        c_obs = np.cumsum(obs)
        c_mdl = np.cumsum(mdl)

        mx = 0.5 * (c_obs[-1] + c_mdl[-1])
        c_obs /= mx
        c_mdl /= mx

        p.addXY(c_mdl, c_obs, '%s #%d' % (key_text, index))

    # HACK: this range of numbers is chosen to give reasonable sampling for my
    # sources, which are typically quite soft.
    #
    # Note: this reuses the variables from the last loop iteration.
    locs = np.array([0, 0.05, 0.08, 0.11, 0.17, 0.3, 0.4, 0.7, 1
                     ]) * (kev.size - 2)
    c0 = 1.05
    c1 = 1.1

    for loc in locs:
        i0 = int(np.floor(loc))
        frac = loc - i0
        kevval = (1 - frac) * kev[i0] + frac * kev[i0 + 1]
        mdlval = (1 - frac) * c_mdl[i0] + frac * c_mdl[i0 + 1]
        obsval = (1 - frac) * c_obs[i0] + frac * c_obs[i0 + 1]
        p.addXY([mdlval, mdlval], [c0, c1], '%.2f keV' % kevval, dsn=2)
        p.addXY([c0, c1], [obsval, obsval], None, dsn=2)

    p.setLabels('Cumulative rescaled model', 'Cumulative rescaled data')
    p.defaultKeyOverlay.vAlign = 0.3
    return p
Ejemplo n.º 9
0
def snip_plot(df,
              t0,
              period,
              yofs=200,
              lines=False,
              errs=True,
              psf='default',
              tcol='dmjd',
              widthfactor=0.5):
    if psf == 'default':
        psf = om.stamps.Circle
    elif psf is None:
        psf = lambda: None

    p = om.RectPlot()
    nplot = 0
    tmax = df[tcol].max()
    width = widthfactor * period
    tleft = t0 - 0.5 * width

    while tleft < tmax:
        subset = (df[tcol] >= tleft) & (df[tcol] < tleft + width)
        if not subset.any():
            tleft += width
            continue

        x = df[subset][tcol] - (tleft + 0.5 * width)
        y = df[subset]['re'] + nplot * yofs
        u = df[subset]['ure']

        if errs:
            p.addXYErr(
                x,
                y,
                u,
                None,
                lines=lines,
                pointStamp=psf(),
            )
        else:
            p.addXY(
                x,
                y,
                None,
                lines=lines,
                pointStamp=psf(),
            )

        nplot += 1
        tleft += width

    p.setBounds(-0.5 * width, 0.5 * width)
    return p
Ejemplo n.º 10
0
def plot_one(plotnum, data, prd):
    data['n'] = (data['mjd'] - 58404.598) / prd + 0.5
    data['ph'] = data['n'] % 1.
    nmax = int(np.ceil(data['n'].max()))

    p = om.RectPlot()

    for i in range(nmax):
        s = data[(data['n'] >= i) & (data['n'] < i + 1)]

        # All this junk to avoid connecting over bandpass cal visits
        t = np.asarray(s.mjd)
        w = np.where((t[1:] - t[:-1]) > dt_sep_cutoff)[0]
        if w.size == 0:
            segments = [s]
        else:
            assert w.size == 1
            tcut = s.mjd.iloc[w[0]]
            segments = [s[s.mjd <= tcut], s[s.mjd > tcut]]

        if colormap is None:
            for seg in segments:
                p.addDF(seg[['ph', cmpt, 'u'+cmpt]], None, dsn=i, lines=True,
                        pointStamp=stamp())
        else:
            colormap_value = i / (nmax - 1)
            color = tuple(colormap(colormap_value)) + (alpha_term,)

            for seg in segments:
                p.addDF(seg[['ph', cmpt, 'u'+cmpt]], None, dsn=None, lines=True,
                        pointStamp=stamp(),
                        lineStyle={'color': color},
                        stampStyle={'color': color})

    p.addKeyItem('%.3f hr' % (24 * prd))
    for ap in p.bpainter, p.tpainter:
        ap.everyNthMajor = 2
        ap.minorTicks = 2
        ap.majorTickScale = 1.7
    p.setXLabel('Phase')
    p.lpainter.majorTickScale = p.rpainter.majorTickScale = 1.7

    if plotnum == 0:
        p.setYLabel('Flux Density(μJy)')
    else:
        p.lpainter.paintLabels = False

    p.defaultKeyOverlay.hAlign = 0.89
    p.defaultKeyOverlay.vAlign = 0.04
    p.add(TextOverlay(0.05, 0.02, '<span size="xx-large" weight="700">(%s)</span>' % (chr(ord('A') + plotnum))))
    p.setBounds(xmin=-0.05, xmax=1.05, ymin=-70, ymax=800)
    return p
Ejemplo n.º 11
0
def make_specseq_plot(settings, ii):
    import omega as om

    p = om.RectPlot()
    p.setLinLogAxes(True, False)

    for icml, cml in enumerate(ii.cmls):
        spect = ii.spectrum(icml, settings.stokes)
        p.addXY(ii.freqs, spect, '%.0f' % cml)

    p.defaultKeyOverlay.hAlign = 0.95
    p.setLabels('Frequency (GHz)', 'Flux density (uJy)')

    return p
Ejemplo n.º 12
0
    def plot(self):
        import omega as om

        p = om.RectPlot()
        dt = (np.asarray(self.times) - self.times[0]) * 24.
        print 'Base time is', util.jdToFull(self.times[0])

        for pol, amps in self.amps.iteritems():
            us = self.ampus[pol]
            p.addXYErr(dt, amps, us, util.polarizationName(pol), lines=False)

        #p.setBounds (ymin=0)
        p.setLabels('Relative Time (hr)', 'Flux Density (Jy)')
        return p
Ejemplo n.º 13
0
    def plot(self,
             modelx,
             dlines=False,
             xmin=None,
             xmax=None,
             ymin=None,
             ymax=None,
             **kwargs):
        """Plot the data and model (requires `omega`).

        This assumes that `data` is 1D and that `mfunc` takes one argument
        that should be treated as the X variable.

        """
        import omega as om

        modelx = np.asarray(modelx)
        if modelx.shape != self.data.shape:
            raise ValueError('modelx and data arrays must have same shape')

        modely = self.mfunc(modelx)
        sigmas = self.invsigma**-1  # TODO: handle invsigma = 0

        vb = om.layout.VBox(2)
        vb.pData = om.quickXYErr(modelx,
                                 self.data,
                                 sigmas,
                                 'Data',
                                 lines=dlines,
                                 **kwargs)

        vb[0] = vb.pData
        vb[0].addXY(modelx, modely, 'Model')
        vb[0].setYLabel('Y')
        vb[0].rebound(False, True)
        vb[0].setBounds(xmin, xmax, ymin, ymax)

        vb[1] = vb.pResid = om.RectPlot()
        vb[1].defaultField.xaxis = vb[1].defaultField.xaxis
        vb[1].addXYErr(modelx, self.resids, sigmas, None, lines=False)
        vb[1].setLabels('X', 'Residuals')
        vb[1].rebound(False, True)
        # ignore Y values since residuals are on different scale:
        vb[1].setBounds(xmin, xmax)

        vb.setWeight(0, 3)
        return vb
Ejemplo n.º 14
0
def main():
    import time
    from pwkit.ndshow_gtk3 import view

    t0 = time.time()
    x_centers1, grid1 = calculate(delta_t=0.0002)
    #x_centers2, grid2 = calculate(delta_t=0.00005)
    elapsed = time.time() - t0
    print('Calculated grid(s) in %.1f seconds' % elapsed)

    xex = np.linspace(0, XMAX, 50)
    yex = (np.exp(Q) - np.exp(Q * xex)) / (np.exp(Q) - 1)

    p = om.RectPlot()
    p.addXY(xex, yex, 'exact')
    p.addXY(x_centers1, grid1, '0.0002')
    #p.addXY(x_centers2, grid2, '0.00005')
    p.defaultKeyOverlay.hAlign = 0.95
    p.show()
Ejemplo n.º 15
0
Archivo: data.py Proyecto: vlslv/pwkit
    def _plot_binned_event_energies(self,
                                    bbinfo,
                                    energy_scale=1.,
                                    time_key='dmjd',
                                    target_max_per_bin=100,
                                    **kwargs):
        import omega as om
        from scipy.stats.mstats_extras import mjci

        p = om.RectPlot()
        time = self.events[time_key]
        energy = self.events['energy'] * energy_scale

        for ledge, redge in zip(bbinfo.ledges, bbinfo.redges):
            subset = self.events[(time >= ledge) & (time < redge)]
            n = subset.shape[0]

            if n == 0:
                continue

            nbin = max(int(np.floor(n / target_max_per_bin)), 1)
            subbin_width = (redge - ledge) / nbin

            for i in range(nbin):
                t0 = ledge + i * subbin_width
                t1 = t0 + subbin_width
                tmid = 0.5 * (t0 + t1)
                matched = (time >= t0) & (time < t1)
                subsubset = self.events[matched]
                if subsubset.shape[0] == 0:
                    continue

                subsubenergy = energy[matched]
                med_energy = subsubenergy.median()
                u_med_energy = mjci(subsubenergy.data, prob=0.5).item()
                p.addXY([t0, t1], [med_energy, med_energy], None, **kwargs)
                p.addXY([tmid, tmid],
                        [med_energy - u_med_energy, med_energy + u_med_energy],
                        None, **kwargs)

        return p
Ejemplo n.º 16
0
def demo_divine_figure_2b():
    import omega as om

    E = np.logspace(np.log10(0.06), np.log10(35), 64)

    moment = 4.255
    alpha = 0.5 * np.pi

    p = om.RectPlot()

    for L in [2, 6.2, 10.5]:
        # Note: ignoring augmented field strength at L > 20
        B = moment * L**-3
        p.addXY(E, inner_radbelt_e_integ_intensity(moment, L, B, alpha, E),
                'L = %.1f' % L)

    p.setLinLogAxes(True, True)
    p.setBounds(0.03, 100., 4000., 3e8)
    p.defaultKeyOverlay.hAlign = 0.9
    p.setLabels('Energy (MeV)', 'Integ. Intensity (cm^-2 s^-1 sr^-1)')
    return p
Ejemplo n.º 17
0
Archivo: demo7.py Proyecto: pkgw/vernon
def main():
    import omega as om

    xex, yex = exact()
    #xbvp, ybvp = bvp()

    xb = np.linspace(0.05, 0.95, 8)
    yb = np.empty_like(xb)

    #for i in range(xb.size):
    #    yb[i] = backwards(xb[i])

    #xf, yf = forwards_scalar()
    xf, yf = forwards_vector_fixed_steps()

    p = om.RectPlot()
    p.addXY(xex, yex, 'exact')
    #p.addXY(xbvp, ybvp, 'BVP')
    #p.addXY(xb, yb, 'backwards', lines=False)
    p.addXY(xf, yf, 'forwards', lines=False)
    p.defaultKeyOverlay.hAlign = 0.95
    p.show()
Ejemplo n.º 18
0
def demo_divine_figure_2c():
    import omega as om

    E = 3.  # MeV
    moment = 4.255
    alpha = 0.5 * np.pi

    p = om.RectPlot()

    for L, lammax in [(2, 40.), (6.2, 65.), (10.5, 70.)]:
        mlat_deg = np.linspace(0., lammax, 64)
        mlat_rad = mlat_deg * astutil.D2R
        # Note: ignoring augmented field strength at L > 20
        r = L * np.cos(mlat_rad)**2
        B = moment * r**-3 * (1 + 3 * np.sin(mlat_rad)**2)**0.5
        p.addXY(mlat_deg,
                inner_radbelt_e_integ_intensity(moment, L, B, alpha, E),
                'L = %.1f' % L)

    p.setLinLogAxes(False, True)
    p.setBounds(0, 70, 3e3, 3e7)
    p.defaultKeyOverlay.hAlign = 0.9
    p.setLabels('Mag. Lat (deg)', 'Integ. Intensity (cm^-2 s^-1 sr^-1)')
    return p
Ejemplo n.º 19
0
def summarize():
    import omega as om

    alpha_star = 0.16
    x_m = 0.35
    delta_x = 0.20
    R = 8.5e-8
    Omega_e = 59941  # = 2 * np.pi * 9540
    max_wave_lat = 30 * np.pi / 180

    degrees = np.linspace(0.1, 89.9, 100)
    sinas = np.sin(degrees * np.pi / 180)

    hb = om.layout.HBox(3)
    hb[0] = paa = om.RectPlot()
    hb[1] = pap = om.RectPlot()
    hb[2] = ppp = om.RectPlot()

    dmin = dmax = None

    for kev in 100, 1000, 10000:
        E = kev / 511.  # normalized to mc^2 = 511 keV
        Daa, Dap, Dpp = compute(E,
                                sinas,
                                Omega_e,
                                alpha_star,
                                R,
                                x_m,
                                delta_x,
                                max_wave_lat,
                                'R',
                                wave_filtering='f',
                                p_scaled=True,
                                parallel=False)
        Dap = np.abs(Dap)

        cmin = min(Daa.min(), Dap.min(), Dpp.min())
        cmax = max(Daa.max(), Dap.max(), Dpp.max())

        if dmin is None:
            dmin, dmax = cmin, cmax
        else:
            dmin = min(dmin, cmin)
            dmax = max(dmax, cmax)

        paa.addXY(degrees, Daa, str(kev))
        pap.addXY(degrees, Dap, str(kev))
        ppp.addXY(degrees, Dpp, str(kev))

    if dmin == 0:
        dmin = 1e-12

    for p in paa, pap, ppp:
        p.setLinLogAxes(False, True)
        p.setBounds(0, 90, dmin * 0.8, dmax / 0.8)
        p.setXLabel('Pitch angle (degrees)')

    paa.setYLabel('D_aa')
    pap.setYLabel('|D_ap|/p')
    ppp.setYLabel('D_pp/p^2')

    return hb
Ejemplo n.º 20
0
def plot():
    df = photom.load_and_reduce('../target.phot.ll.txt')
    df['dhr'] = df['dmjd'] * 24
    soln = photom.BEST_SOLN

    toa_nrot, toas = photom.best_toas(df)
    toa_info = dict(zip(toa_nrot, toas - photom.MJD0))

    vb = om.layout.VBox(3)

    for dday in (0, 1, 2):
        subset = (df['dmjd'] >= dday) & (df['dmjd'] < (dday + 1))

        p = om.RectPlot()

        # Zero reference line
        p.addXY(
            [24 * (DMJD_XMIN + dday), 24 * (DMJD_XMAX + dday)], [0, 0],
            None,
            lineStyle = {'dashing': [3, 3], 'color': 'muted'},
            dsn = 0
        )

        # Actual data
        t = Time(np.median(df[subset]['dmjd']) + photom.MJD0, format='mjd', scale='utc')
        utdate = t.utc.strftime('%Y %b %d')
        p.addDF(df[subset][['dhr', 're', 'ure']], f'Day {dday+1} ({utdate} UT)')

        # Markers for the best-fit pulse ephemeris
        dmjdmin = DMJD_XMIN + dday
        nmin = (dmjdmin - soln.t0) / soln.period
        nmin = int(np.ceil(nmin))
        n = nmin

        while True:
            dmjd = soln.n_to_mjd(n) - photom.MJD0
            if dmjd > DMJD_XMAX + dday:
                break

            if n == nmin or n == nmin + PULSES_IN_DAY[dday] - 1:
                t = f'<span size="larger" weight="700">{n+1}</span>'
                p.add(XYText(24 * dmjd, 380, t))

            toa = toa_info.get(n)
            if toa is not None:
                p.addXY(
                    [24 * toa, 24 * toa], [150, 450],
                    None,
                    lineStyle = {'linewidth': 0.5, 'color': (0, 0, 0), 'dashing': [2, 2]},
                    dsn = 0
                )

            p.addXY(
                [24 * dmjd, 24 * dmjd], [250, 350],
                None,
                lineStyle = {'linewidth': 3, 'color': (0, 0, 0)},
                dsn = 0
            )
            n += 1

        # Labeling etc
        p.setBounds(24 * (DMJD_XMIN + dday), 24 * (DMJD_XMAX + dday), YMIN, YMAX)
        p.defaultKeyOverlay.hAlign = 0.97
        p.defaultKeyOverlay.vAlign = 0.07
        p.bpainter.numFormat = dhr_to_ut
        p.bpainter.minorTicks = 4

        p.add(TextOverlay(0.02, 0.04, '<span size="xx-large" weight="700">(%s)</span>' % (chr(ord('A') + dday))),
              rebound=False)

        vb[dday] = p

    vb[1].setYLabel('Flux density (μJy)')
    vb[2].setXLabel('Universal Time (UT)')

    return vb
Ejemplo n.º 21
0
def snip_page(df,
              t0,
              period,
              lines=False,
              errs=True,
              psf='default',
              tcol='dmjd',
              widthfactor=0.5):
    if psf == 'default':
        psf = om.stamps.Circle
    elif psf is None:
        psf = lambda: None

    pg = om.makeDisplayPager()
    tmax = df[tcol].max()
    width = widthfactor * period

    def gen_data():
        tleft = t0 - 0.5 * width

        while tleft < tmax:
            subset = (df[tcol] >= tleft) & (df[tcol] < tleft + width)
            if not subset.any():
                tleft += width
                continue

            x = df[subset][tcol] - (tleft + 0.5 * width)
            y = df[subset]['re']
            u = df[subset]['ure']
            yield x, y, u
            tleft += width

    ymin = ymax = None

    for x, y, u in gen_data():
        if ymin is None:
            ymin = (y - u).min()
            ymax = (y + u).max()
        else:
            ymin = min(ymin, (y - u).min())
            ymax = max(ymax, (y + u).max())

    height = ymax - ymin
    if height == 0:
        height = 0.5 * ymax
    if height == 0:
        height = 1
    ymax = ymax + 0.05 * height
    ymin = ymin - 0.05 * height

    for x, y, u in gen_data():
        p = om.RectPlot()

        if errs:
            p.addXYErr(
                x,
                y,
                u,
                None,
                lines=lines,
                pointStamp=psf(),
            )
        else:
            p.addXY(
                x,
                y,
                None,
                lines=lines,
                pointStamp=psf(),
            )

        p.setBounds(-0.5 * width, 0.5 * width, ymin, ymax)
        pg.send(p)

    pg.done()
Ejemplo n.º 22
0
def plot_flare_zoom(dphot, plotinfo):
    from . import data

    dur = plotinfo.dmjd1 - plotinfo.dmjd0
    w = ((dphot.dmjd > plotinfo.dmjd0 - 0.1 * dur) &
         (dphot.dmjd < plotinfo.dmjd1 + 0.1 * dur))
    subset = dphot[w]

    p = om.RectPlot()
    med_uncerts = []
    max_val = None
    max_loc = None

    for icmp, cinfo in enumerate(plotinfo.components):
        kt1 = cinfo.key if plotinfo.showkey else None

        med_uncerts.append(subset['u' + cinfo.name].median())

        ml = subset[cinfo.name].argmax()
        if max_val is None or subset[cinfo.name][ml] > max_val:
            max_val = subset[cinfo.name][ml]
            max_loc = ml

        for mask in data.photom_generate_indices(subset):
            visit = subset.take(mask)
            venv = om.rect.VEnvelope(kt1)
            yhi = np.asarray(visit[cinfo.name])
            ylo = 0 * yhi
            w = np.where(ylo > yhi)
            tmp = ylo[w]
            ylo[w] = yhi[w]
            yhi[w] = tmp
            venv.setFloats(np.asarray(visit.dmjd), ylo, yhi)
            venv.style = {'color': cinfo.color}
            p.add(venv)
            kt1 = None

    if plotinfo.showkey:
        p.defaultKeyOverlay.hAlign = 0.05
        p.defaultKeyOverlay.vAlign = 0.06

    med_uncert = np.median(med_uncerts)
    p.addXYErr([plotinfo.uncert_loc[0]], [plotinfo.uncert_loc[1]],
               [med_uncert],
               None,
               lineStyle={'color': (0, 0, 0)},
               stampStyle={'color': (0, 0, 0)})
    p.addHLine(0, None, zheight=-5, lineStyle=plotinfo.refline_style)
    p.setBounds(plotinfo.dmjd0, plotinfo.dmjd1, *plotinfo.ybounds)

    tp = om.TextPainter('<big><b>%s</b></big>' % plotinfo.desc)
    co = p.add(om.rect.AbsoluteFieldOverlay(tp), rebound=False)
    co.hAlign = 0.95
    co.vAlign = 0.05

    if plotinfo.paintleft:
        p.lpainter.everyNthMajor = 3
    else:
        p.lpainter.paintLabels = False

    for ap in p.bpainter, p.tpainter:
        ap.autoBumpThreshold = 0
        ap.minorTicks = 10
    p.bpainter.labelMinorTicks = True
    p.bpainter.everyNthMinor = 5

    for ap in p.lpainter, p.rpainter:
        ap.minorTicks = 2

    if plotinfo.labelleft:
        p.setYLabel('Flux density(μJy)')

    if plotinfo.labelbot:
        mjd0 = np.floor(dphot.mjd.min())
        p.setXLabel('MJD - %.0f(day)' % mjd0)

    # time away from peak top-axis label
    dmjdpeak = subset.dmjd[max_loc]
    ds0 = 86400 * (plotinfo.dmjd0 - dmjdpeak)
    ds1 = 86400 * (plotinfo.dmjd1 - dmjdpeak)
    p.tpainter.axis = om.rect.LinearAxis(ds0, ds1)
    p.tpainter.paintLabels = True
    p.tpainter.autoBumpThreshold = 10.
    p.tpainter.minorTicks = 4
    p.tpainter.everyNthMajor = 2
    p.setSideLabel(p.SIDE_TOP, pangosub('t – t{peak}(sec)'))

    return p
Ejemplo n.º 23
0
    def report(self, cfg):
        import omega as om
        import omega.gtk3
        from pwkit import ndshow_gtk3

        self.all_aps = np.sort(list(self.all_aps))
        self.all_bps = sorted(self.all_bps)
        self.all_times = np.sort(list(self.all_times))

        # Antpols by DDID, time:
        data = []
        descs = []

        for ddid, stats in self.ap_time_stats_by_ddid.items():
            mean, scat = postproc(stats.finish(self.all_times, self.all_aps))
            data.append(mean / scat)
            descs.append('DDID %d' % ddid)

        print(
            'Viewing X axis: antpol; Y axis: time; iteration: DDID (~= spwid) ...'
        )
        ndshow_gtk3.cycle(data, descs, run_main=True)

        # Antpols by DDID, freq:
        data = []
        descs = []

        for ddid, stats in self.ap_spec_stats_by_ddid.items():
            mean, scat = postproc(stats.finish(self.all_aps))
            data.append(mean / scat)
            descs.append('DDID %d' % ddid)

        print('Viewing X axis: frequency; Y axis: antpol; iteration: DDID ...')
        ndshow_gtk3.cycle(data, descs, run_main=True)

        # Antpols by DDID
        p = om.RectPlot()

        for ddid, stats in self.ap_stats_by_ddid.items():
            ok, mean, scat = postproc_mask(stats.finish(self.all_aps))
            p.addXYErr(
                np.arange(len(self.all_aps))[ok], mean, scat, 'DDID %d' % ddid)

        p.setBounds(-0.5, len(self.all_aps) - 0.5)
        p.setLabels('Antpol number', 'Mean closure phase (rad)')
        p.addHLine(0, keyText=None, zheight=-1)
        print('Viewing everything grouped by antpol ...')
        p.show()

        # Basepols by DDID
        data = []
        descs = []
        tostatuses = []

        def bpgrid_status(pol1, pol2, ants, yx):
            i, j = [int(_) for _ in np.floor(yx + 0.5)]
            if i < 0 or j < 0 or i >= ants.size or j >= ants.size:
                return ''

            ni = self._getname(ants[i])
            nj = self._getname(ants[j])

            if i <= j:
                return '%s-%s %s' % (ni, nj, util.pol_names[pol1])
            return '%s-%s %s' % (nj, ni, util.pol_names[pol2])

        for ddid, stats in self.bp_stats_by_ddid.items():
            mean, scat = postproc(stats.finish(self.all_bps))
            nmean = mean / scat
            pol1, pol2, ants, grid = grid_bp_data(self.all_bps,
                                                  zip(self.all_bps, nmean))
            data.append(grid)
            descs.append('DDID %d' % ddid)
            tostatuses.append(lambda yx: bpgrid_status(pol1, pol2, ants, yx))

        print('Viewing X axis: antpol1; Y axis: antpol2; iteration: DDID ...')
        ndshow_gtk3.cycle(data, descs, tostatuses=tostatuses, run_main=True)

        # Everything by time
        ok, mean, scat = postproc_mask(
            self.global_stats_by_time.finish(self.all_times))
        stimes = self.all_times[ok] / 86400
        st0 = int(np.floor(stimes.min()))
        stimes -= st0
        p = om.quickXYErr(stimes, mean, scat)
        p.addHLine(0, keyText=None, zheight=-1)
        p.setLabels('MJD - %d' % st0, 'Mean closure phase (rad)')
        print('Viewing everything grouped by time ...')
        p.show()
Ejemplo n.º 24
0
def debug_toa_analysis(
    soln,
    df,
    toas,
    weights,
    nrots=NROT_ALL,
    widthfactor=0.7,
    sort='seq',
    yrange=None,
):
    # Solve for the period so that we can figure out how to convert the
    # weights into uncertainties.

    from pwkit.lsqmdl import PolynomialModel
    invsigma = weights**0.5
    mtoa = toas.mean()
    ephem = PolynomialModel(1, nrots, toas - mtoa, invsigma).solve()
    ephem.print_soln()
    print('T0:', ephem.params[0] + mtoa - MJD0)
    print('RMS residual:', (ephem.resids**2).mean()**0.5)
    wtscale = np.sqrt(ephem.rchisq)

    uncerts = wtscale * weights**-0.5

    pg = om.makeDisplayPager()
    half_inner_width = 0.25 * soln.period * widthfactor

    if sort == 'seq':
        sort_idx = np.arange(nrots.size)
    elif sort == 'resid':
        sort_idx = np.argsort(ephem.resids)
    else:
        raise ValueError(f'unhandled sort {sort!r}')

    for i in sort_idx:
        n = nrots[i]
        sl = soln.slice(df, n, widthfactor=widthfactor)
        sl['invsigma'] = 1. / sl['ure']
        toa = toas[i]
        mjd = soln.n_to_mjd(n)

        # Repeat the solution of the baseline flux used to determine
        # the excess.

        is_inner = np.abs(sl['dmjd']) < half_inner_width
        outer = sl[~is_inner]
        baseline = PolynomialModel(
            BASELINE_MODEL_POLYNOMIAL_ORDER,
            outer['dmjd'].values,
            outer['re'].values,
            outer['invsigma'].values,
        ).solve()

        p = om.RectPlot()

        # The TOA for this slice with its uncertainty, as determined from its
        # weight and the RMS of the residuals to the period fit.
        p.add(om.rect.XBand(toa - uncerts[i], toa + uncerts[i], keyText=None),
              dsn=0)
        p.addVLine(toa, keyText='n=%d Centroid TOA' % n, dsn=0)

        # The actual data.
        p.addDF(sl[['mjd', 're', 'ure']], dsn=1)

        # The definitions of the inner/outer windows used for the baseline fit and
        # excess flux computation.
        p.addVLine(mjd - half_inner_width,
                   dsn=2,
                   lineStyle={'dashing': [3, 3]},
                   keyText=None)
        p.addVLine(mjd + half_inner_width,
                   dsn=2,
                   lineStyle={'dashing': [3, 3]},
                   keyText=None)

        # The baseline flux fit
        bl_dmjd = np.linspace(-2 * half_inner_width, 2 * half_inner_width, 3)
        p.addXY(bl_dmjd + mjd, baseline.mfunc(bl_dmjd), None, dsn=2)

        # The new ephemeris fit
        label = 'New ephem (resid = %.5f = %.1fσ)' % (
            ephem.resids[i], ephem.resids[i] / uncerts[i])
        mjd_ephem = ephem.mfunc(n) + mtoa
        p.addVLine(mjd_ephem, dsn=3, keyText=label)

        if yrange is not None:
            p.setBounds(ymin=yrange[0], ymax=yrange[1])

        p.bpainter.numFormat = '%.8g'

        pg.send(p)

    pg.done()
    return ephem
Ejemplo n.º 25
0
    def plot (self):
        if isinstance (self.cfg.out, omega.render.Pager):
            # This is for non-CLI invocation.
            pager = self.cfg.out
        elif self.cfg.out is None:
            from omega import gtk3
            pager = om.makeDisplayPager ()
        else:
            pager = om.makePager (self.cfg.out,
                                  dims=self.cfg.dims,
                                  margins=self.cfg.margins,
                                  style=om.styles.ColorOnWhiteVector ())

        # Collect the data as loaded

        skeys = sorted (six.viewkeys (self.results))
        normalized = {}
        spws = set ()
        polns = set ()

        for antnum, antname in enumerate (self.antnames):
            for key in skeys:
                spw, poln, time = key
                gc = self.results[key]
                idx = gc.ant_to_antidx.get (antnum)
                if idx is None:
                    continue

                samps, otherant = gc.get_normalized (idx)
                bysp = normalized.setdefault (antname, {})
                bytime = bysp.setdefault ((spw, poln), {})
                bytime[time] = (samps, otherant)
                polns.add (poln)
                spws.add (spw)

        spws = sorted (spws)
        polns = sorted (polns)
        spwseq = dict ((s, i) for (i, s) in enumerate (spws))
        polnseq = dict ((p, i) for (i, p) in enumerate (polns))

        # Group by time and get dims

        rmin = rmax = imin = imax = amin = amax = None

        for antname, bysp in six.viewitems (normalized):
            for spwpol in list (six.viewkeys (bysp)):
                bytime = bysp[spwpol]
                times = sorted (six.viewkeys (bytime))
                samps = np.concatenate (tuple (bytime[t][0] for t in times))
                otherants = np.concatenate (tuple (bytime[t][1] for t in times))
                logamps = np.log10 (np.abs (samps))
                bysp[spwpol] = samps, otherants, logamps

                if rmin is None:
                    rmin = samps.real.min ()
                    rmax = samps.real.max ()
                    imin = samps.imag.min ()
                    imax = samps.imag.max ()
                    amin = logamps.min ()
                    amax = logamps.max ()
                else:
                    rmin = min (rmin, samps.real.min ())
                    rmax = max (rmax, samps.real.max ())
                    imin = min (imin, samps.imag.min ())
                    imax = max (imax, samps.imag.max ())
                    amin = min (amin, logamps.min ())
                    amax = max (amax, logamps.max ())

        # Square things up in the real/imag plot and add little margins

        rrange = rmax - rmin
        irange = imax - imin
        arange = amax - amin

        if rrange < irange:
            delta = 0.5 * (irange - rrange)
            rmax += delta
            rmin -= delta
            rrange = irange
        else:
            delta = 0.5 * (rrange - irange)
            imax += delta
            imin -= delta
            irange = rrange

        rmax += 0.05 * rrange
        rmin -= 0.05 * rrange
        imax += 0.05 * irange
        imin -= 0.05 * irange
        amax += 0.05 * arange
        amin -= 0.05 * arange

        # Info for overplotted cumulative histogram of log-ampls

        def getlogamps ():
            for bysp in six.viewvalues (normalized):
                for samps, otherant, logamp in six.viewvalues (bysp):
                    yield logamp

        all_log_amps = np.concatenate (tuple (getlogamps ()))
        all_log_amps.sort ()
        all_log_amps_x = np.linspace (0., len (self.antnames), all_log_amps.size)
        all_log_amps_bounds = scoreatpercentile (all_log_amps, [2.5, 97.5])

        # Actually plot

        for antname in self.antnames:
            bysp = normalized.get (antname)
            if bysp is None:
                continue # no data

            reim = om.RectPlot ()
            reim.addKeyItem (antname)
            reim.addHLine (0, keyText=None, zheight=-2, dsn=0, lineStyle={'color': (0,0,0), 'dashing': (2, 2)})
            reim.addVLine (1, keyText=None, zheight=-2, dsn=0, lineStyle={'color': (0,0,0), 'dashing': (2, 2)})

            loga = om.RectPlot ()
            loga.addHLine (0, keyText=None, zheight=-2, dsn=0, lineStyle={'color': (0,0,0), 'dashing': (2, 2)})
            loga.addXY (all_log_amps_x, all_log_amps, None, lineStyle={'color': (0,0,0)})
            for a in all_log_amps_bounds:
                loga.addHLine (a, keyText=None, zheight=-2, dsn=0, lineStyle={'color': (0,0,0), 'dashing': (1, 3)})

            for (spw, poln), (samps, otherant, logamp) in six.viewitems (bysp):
                # Real/imag plot
                ms = om.stamps.MultiStamp ('cnum', 'shape', 'tlines')
                ms.fixedsize = 4
                ms.fixedlinestyle = {'color': 'muted'}

                cnum = np.zeros (samps.size, dtype=np.int)
                cnum.fill (spwseq[spw])

                shape = np.zeros_like (cnum)
                shape.fill (polnseq[poln])

                dp = om.rect.XYDataPainter (lines=False, pointStamp=ms, keyText=None)
                dp.setInts (cnum, shape, otherant + 1)
                dp.setFloats (samps.real, samps.imag)
                reim.add (dp)

                # Log-amplitudes plot
                ms = om.stamps.MultiStamp ('cnum', 'shape', 'tlines')
                ms.fixedsize = 4
                ms.fixedlinestyle = {'color': 'muted'}

                cnum = np.zeros (samps.size, dtype=np.int)
                cnum.fill (spwseq[spw])

                shape = np.zeros_like (cnum)
                shape.fill (polnseq[poln])

                dp = om.rect.XYDataPainter (lines=False, pointStamp=ms, keyText=None)
                dp.setInts (cnum, shape, otherant + 1)
                dp.setFloats (otherant, np.log10 (np.abs (samps)))
                loga.add (dp)

            for spw in spws:
                for poln in polns:
                    s = EmulatedMultiStamp (polnseq[poln], spwseq[spw], 4)
                    reim.addKeyItem (ManualStampKeyPainter ('spw#%d %s' % (spw, poln), s))

            reim.setLabels ('Normalized real part', 'Normalized imaginary part')
            reim.setBounds (rmin, rmax, imin, imax)
            # Unfortunately this is not compatible with VBox layout right now.
            #reim.fieldAspect = 1.

            loga.setLabels ('Paired antenna number', 'Log10 amplitude ratio')
            loga.setBounds (-0.5, len (self.antnames) + 0.5, amin, amax)

            vb = om.layout.VBox (2)
            vb[0] = reim
            vb[1] = loga
            vb.setWeight (0, 3)
            pager.send (vb)

        pager.done ()
Ejemplo n.º 26
0
def make_spectrum_plot(model_plot,
                       data_plot,
                       desc,
                       xmin_clamp=0.01,
                       min_valid_x=None,
                       max_valid_x=None):
    """Make a plot of a spectral model and data.

    *model_plot*
      A model plot object returned by Sherpa from a call like `ui.get_model_plot()`
      or `ui.get_bkg_model_plot()`.
    *data_plot*
      A data plot object returned by Sherpa from a call like `ui.get_source_plot()`
      or `ui.get_bkg_plot()`.
    *desc*
      Text describing the origin of the data; will be shown in the plot legend
      (with "Model" and "Data" appended).
    *xmin_clamp*
      The smallest "x" (energy axis) value that will be plotted; default is 0.01.
      This is needed to allow the plot to be shown on a logarithmic scale if
      the energy axes of the model go all the way to 0.
    *min_valid_x*
      Either None, or the smallest "x" (energy axis) value in which the model and
      data are valid; this could correspond to a range specified in the "notice"
      command during analysis. If specified, a gray band will be added to the plot
      showing the invalidated regions.
    *max_valid_x*
      Like *min_valid_x* but for the largest "x" (energy axis) value in which the
      model and data are valid.
    Returns:
      A tuple ``(plot, xlow, xhigh)``, where *plot* an OmegaPlot RectPlot
      instance, *xlow* is the left edge of the plot bounds, and *xhigh* is the
      right edge of the plot bounds.

    """
    import omega as om

    model_x = np.concatenate((model_plot.xlo, [model_plot.xhi[-1]]))
    model_x[0] = max(model_x[0], xmin_clamp)
    model_y = np.concatenate((model_plot.y, [0.]))

    # Sigh, sometimes Sherpa gives us bad values.
    is_bad = ~np.isfinite(model_y)
    if is_bad.sum():
        from .cli import warn
        warn('bad Sherpa model Y value(s) at: %r', np.where(is_bad)[0])
        model_y[is_bad] = 0

    data_left_edges = data_plot.x - 0.5 * data_plot.xerr
    data_left_edges[0] = max(data_left_edges[0], xmin_clamp)
    data_hist_x = np.concatenate(
        (data_left_edges, [data_plot.x[-1] + 0.5 * data_plot.xerr[-1]]))
    data_hist_y = np.concatenate((data_plot.y, [0.]))

    log_bounds_pad_factor = 0.9
    xlow = model_x[0] * log_bounds_pad_factor
    xhigh = model_x[-1] / log_bounds_pad_factor

    p = om.RectPlot()

    if min_valid_x is not None:
        p.add(om.rect.XBand(1e-3 * xlow, min_valid_x, keyText=None),
              zheight=-1,
              dsn=1)
    if max_valid_x is not None:
        p.add(om.rect.XBand(max_valid_x, xhigh * 1e3, keyText=None),
              zheight=-1,
              dsn=1)

    csp = om.rect.ContinuousSteppedPainter(keyText=desc + ' Model')
    csp.setFloats(model_x, model_y)
    p.add(csp)

    csp = om.rect.ContinuousSteppedPainter(keyText=None)
    csp.setFloats(data_hist_x, data_hist_y)
    p.add(csp)
    p.addXYErr(data_plot.x,
               data_plot.y,
               data_plot.yerr,
               desc + ' Data',
               lines=0,
               dsn=1)

    p.setLabels(data_plot.xlabel, data_plot.ylabel)
    p.setLinLogAxes(True, False)
    p.setBounds(xlow, xhigh)
    return p, xlow, xhigh
Ejemplo n.º 27
0
def make_multi_spectrum_plots(model_plot,
                              plotids,
                              data_getter,
                              desc,
                              xmin_clamp=0.01,
                              min_valid_x=None,
                              max_valid_x=None):
    """Make a plot of multiple spectral models and data.

    *model_plot*
      A model plot object returned by Sherpa from a call like
      ``ui.get_model_plot()`` or ``ui.get_bkg_model_plot()``.
    *data_plots*
      An iterable of data plot objects returned by Sherpa from calls like
      ``ui.get_source_plot(id)`` or ``ui.get_bkg_plot(id)``.
    *desc*
      Text describing the origin of the data; will be shown in the plot legend
      (with "Model" and "Data #<number>" appended).
    *xmin_clamp*
      The smallest "x" (energy axis) value that will be plotted; default is 0.01.
      This is needed to allow the plot to be shown on a logarithmic scale if
      the energy axes of the model go all the way to 0.
    *min_valid_x*
      Either None, or the smallest "x" (energy axis) value in which the model and
      data are valid; this could correspond to a range specified in the "notice"
      command during analysis. If specified, a gray band will be added to the plot
      showing the invalidated regions.
    *max_valid_x*
      Like *min_valid_x* but for the largest "x" (energy axis) value in which the
      model and data are valid.
    Returns:
      A tuple ``(plot, xlow, xhigh)``, where *plot* an OmegaPlot RectPlot
      instance, *xlow* is the left edge of the plot bounds, and *xhigh* is the
      right edge of the plot bounds.

    TODO: not happy about the code duplication with :func:`make_spectrum_plot`
    but here we are.

    """
    import omega as om
    from omega.stamps import DataThemedStamp, WithYErrorBars

    model_x = np.concatenate((model_plot.xlo, [model_plot.xhi[-1]]))
    model_x[0] = max(model_x[0], xmin_clamp)
    model_y = np.concatenate((model_plot.y, [0.]))

    # Sigh, sometimes Sherpa gives us bad values.
    is_bad = ~np.isfinite(model_y)
    if is_bad.sum():
        from .cli import warn
        warn('bad Sherpa model Y value(s) at: %r', np.where(is_bad)[0])
        model_y[is_bad] = 0

    p = om.RectPlot()
    data_csps = []
    data_lines = []
    xlow = xhigh = None

    for index, plotid in enumerate(plotids):
        data_plot = data_getter(plotid)
        data_left_edges = data_plot.x - 0.5 * data_plot.xerr
        data_left_edges[0] = max(data_left_edges[0], xmin_clamp)
        data_hist_x = np.concatenate(
            (data_left_edges, [data_plot.x[-1] + 0.5 * data_plot.xerr[-1]]))
        data_hist_y = np.concatenate((data_plot.y, [0.]))

        if xlow is None:
            xlow = model_x[0]
            xhigh = model_x[-1]
        else:
            xlow = min(xlow, model_x[0])
            xhigh = max(xhigh, model_x[-1])

        csp = om.rect.ContinuousSteppedPainter(keyText=None)
        csp.setFloats(data_hist_x, data_hist_y)
        data_csps.append(csp)

        inner_stamp = DataThemedStamp(None)
        stamp = WithYErrorBars(inner_stamp)

        lines = om.rect.XYDataPainter(lines=False,
                                      pointStamp=stamp,
                                      keyText='%s Data #%d' % (desc, index))
        lines.setFloats(data_plot.x, data_plot.y, data_plot.y + data_plot.yerr,
                        data_plot.y - data_plot.yerr)
        inner_stamp.setHolder(lines)
        data_lines.append(lines)

    log_bounds_pad_factor = 0.9
    xlow *= log_bounds_pad_factor
    xhigh /= log_bounds_pad_factor

    if min_valid_x is not None:
        p.add(om.rect.XBand(1e-3 * xlow, min_valid_x, keyText=None),
              zheight=-1,
              dsn=1)
    if max_valid_x is not None:
        p.add(om.rect.XBand(max_valid_x, xhigh * 1e3, keyText=None),
              zheight=-1,
              dsn=1)

    model_csp = om.rect.ContinuousSteppedPainter(keyText=desc + ' Model')
    model_csp.setFloats(model_x, model_y)
    p.add(model_csp)

    for index, (data_csp, lines) in enumerate(zip(data_csps, data_lines)):
        p.add(data_csp, dsn=index + 1)
        p.add(lines, dsn=index + 1)

    p.setLabels(data_plot.xlabel,
                data_plot.ylabel)  # data_plot = last one from the for loop
    p.setLinLogAxes(True, False)
    p.setBounds(xlow, xhigh)
    return p, xlow, xhigh
Ejemplo n.º 28
0
def plot_long_term_photom(dsrc, dref, dpdm, plotinfo):
    add_unbinned = plotinfo.get('add_unbinned', True)
    add_refsrc = plotinfo.get('add_refsrc', True)

    from . import data
    ssrc = data.photom_bin_by_visits(dsrc, half_scans=True)
    if add_refsrc:
        sref = data.photom_bin_by_visits(dref, half_scans=True)

    print('# typical integration time:', np.median(ssrc.inttime))
    mjd0 = dsrc.mjd.min() - dsrc.dmjd.min()
    prd = dpdm.both_prd / 24.

    c0 = plotinfo.comp0
    c1 = plotinfo.comp1
    dsn0 = plotinfo.dsn_base

    if not plotinfo.has('group_sep1'):
        groups = [slice(None)]
    else:
        groups = [(ssrc.dmjd < plotinfo.group_sep1),
                  (ssrc.dmjd > plotinfo.group_sep1) &
                  (ssrc.dmjd < plotinfo.group_sep2),
                  (ssrc.dmjd > plotinfo.group_sep2)]

    p = om.RectPlot()

    # Un-binned source data

    if add_unbinned:
        p.addXY(dsrc.dmjd,
                dsrc[c0],
                None,
                lines=0,
                pointStamp=om.stamps.Circle(fill=1, size=2),
                stampStyle={
                    'color': (1, plotinfo.unavg_intens, plotinfo.unavg_intens)
                })

        p.addXY(dsrc.dmjd,
                dsrc[c1],
                None,
                lines=0,
                pointStamp=om.stamps.Circle(fill=1, size=2),
                stampStyle={
                    'color': (plotinfo.unavg_intens, plotinfo.unavg_intens, 1)
                })

    # Horizontal zero lines(source and reference)

    p.addHLine(0, keyText=None, lineStyle={'color': (0, 0, 0), 'linewidth': 3})
    if add_refsrc:
        p.addHLine(plotinfo.ref_offset,
                   keyText=None,
                   lineStyle=plotinfo.ref_style)

    # Binned source and reference data

    kt1 = plotinfo.src_kt0
    kt2 = plotinfo.src_kt1

    if add_refsrc:
        kt3 = plotinfo.ref_kt0
        kt4 = plotinfo.ref_kt1
        sref['plot_' + c0] = sref[c0] + plotinfo.ref_offset
        sref['plot_' + c1] = sref[c1] + plotinfo.ref_offset

    for g in groups:
        p.addDF(ssrc[g][['dmjd', c0, 'u' + c0]],
                kt1,
                lines=1,
                pointStamp=om.stamps.Circle(fill=1, size=3),
                lineStyle={'linewidth': 2},
                dsn=dsn0 + 0,
                zheight=5)

        p.addDF(ssrc[g][['dmjd', c1, 'u' + c1]],
                kt2,
                lines=1,
                pointStamp=om.stamps.Circle(fill=1, size=3),
                lineStyle={'linewidth': 2},
                dsn=dsn0 + 1,
                zheight=5)

        if add_refsrc:
            p.addDF(sref[g][['dmjd', 'plot_' + c0, 'u' + c0]],
                    kt3,
                    lines=1,
                    pointStamp=om.stamps.Circle(fill=1, size=3),
                    lineStyle={'linewidth': 2},
                    dsn=2)

            p.addDF(sref[g][['dmjd', 'plot_' + c1, 'u' + c1]],
                    kt4,
                    lines=1,
                    pointStamp=om.stamps.Circle(fill=1, size=3),
                    lineStyle={'linewidth': 2},
                    dsn=3)

        kt1 = kt2 = kt3 = kt4 = None

    # Single-period PDM phasing, potentially with boxes identifying flare
    # zoom-ins.

    if plotinfo.has('zoom_ybounds'):
        for i in xrange(plotinfo.zoom_n_lines):
            t = (plotinfo.zoom_mjd0 - mjd0) + i * prd

            p.add(Rectangle(t - 0.5 * plotinfo.zoom_window_dur,
                            t + 0.5 * plotinfo.zoom_window_dur,
                            *plotinfo.zoom_ybounds,
                            style={
                                'color': 'muted',
                                'dashing': [7, 3]
                            }),
                  zheight=-5,
                  rebound=False)

            if plotinfo.zoom_desc is not None:
                p.add(XYText(t,
                             plotinfo.zoom_ybounds[1],
                             '<big><b>%s%d</b></big>' %
                             (plotinfo.zoom_desc, i + 1),
                             vAnchor=-0.03),
                      rebound=False)

    p.defaultKeyOverlay.hAlign = plotinfo.key_halign
    p.defaultKeyOverlay.vAlign = plotinfo.key_valign
    p.setBounds(*plotinfo.bounds)
    p.setYLabel('Flux density(μJy)')

    if plotinfo.label_bot:
        p.setXLabel('MJD - %.0f(day)' % mjd0)
    else:
        p.bpainter.paintLabels = False

    if plotinfo.add_dhr_top_axis:
        add_dhr_top_axis(p, dsrc)

    p.lpainter.everyNthMajor = 2
    return p
Ejemplo n.º 29
0
def demo_divine_figure_7l():
    """Lower panel of figure 7.

    """
    import omega as om

    d4 = JupiterD4Field()
    KM_IFY = 1e30  # cm^-6 => km^-6
    EV_IFY = 1e6  # MeV => eV

    blat = 0.
    blon = -110 * astutil.D2R  # sign?
    br = 6.  # R_J
    mlat, mlon, L = d4(blat, blon, br)
    B = d4.bmag(blat, blon, br)

    p = om.RectPlot()
    p.setLinLogAxes(True, True)

    # Energetic electron distribution

    E = np.array([0.07, 0.2, 0.5, 1.1, 3])  # MeV
    E_cgs = E * cgs.ergperev * 1e6
    j_energetic = radbelt_e_omnidirectional_diff_flux(
        blat,
        blon,
        br,
        E,
        d4,
    )
    j_energetic *= 1e-6 * cgs.evpererg  # per MeV to per erg
    f_energetic = cgs.me**2 * j_energetic / (8 * np.pi * E_cgs) * KM_IFY
    p.addXY(E * EV_IFY, f_energetic, 'Energetic')

    # Warm Maxwellian

    E = np.logspace(1., 4.15, 40)  # eV
    N_ew = warm_e_reference_density(blat, blon, br)
    print('DG83 warm density: 7.81; mine: %.2f' % N_ew)
    kT_cgs = 1e3 * cgs.ergperev
    prefactor = (cgs.me / (2 * np.pi * kT_cgs))**1.5
    f_ew_m = N_ew * prefactor * np.exp(-(E * cgs.ergperev) / kT_cgs) * KM_IFY
    p.addXY(E, f_ew_m, 'Warm Maxwellian')

    # Fitted Warm kappa distribution

    kappa_model = warm_e_psd_model(blat, blon, br, d4)
    print('DG83 warm N_0: 8.5 cm^-3; mine: %.2f' % kappa_model.params[0])
    print('DG83 warm E0: 933 eV; mine: %.0f' % (kappa_model.params[1] * 1e6))
    print('DG83 warm kappa: 2.32; mine: %.2f' % kappa_model.params[2])
    E = np.logspace(1., 6.5, 60)  # eV
    f_ew_k = kappa_model.mfunc(E * 1e-6) * KM_IFY
    p.addXY(E, f_ew_k, 'Warm kappa')

    # Cold electrons. The "2070 cm^-3" reported here seems to be the value for
    # the interpolated "N" from Table 7, not the N_k value corrected for the
    # fact that we're slightly off the disk. The figure caption seems pretty
    # clear about which location we're looking at, i.e. it seems unlikely that
    # the equations are supposed to be evaluated at the disk equator rather
    # than the rotational equator. So I think the discrepancy is just an
    # oversight / inclarity.

    N, kT_mev = cold_e_maxwellian_parameters(blat, blon, br)
    print('DG83 cold N_0: 2070 cm^-3; mine: %.0f' % N)
    print('DG83 cold kT: 36.1 eV; mine: %.1f' % (kT_mev * 1e6))
    E = np.logspace(1., 3., 30)  # eV
    f_ec_k = cold_e_psd(blat, blon, br, E * 1e-6) * KM_IFY
    p.addXY(E, f_ec_k, 'Cold')

    p.setBounds(1e1, 8e6, 1.2e-8, 9e6)
    p.defaultKeyOverlay.hAlign = 0.9
    p.setLabels('Energy (eV)', 'Elec distrib func (s^3/km^6)')
    return p