Exemplo n.º 1
0
def plot_id_focalplane(figsize=(30, 30)):
    '''
    plot all the different identity names of each pixel in the focal plane

    FPidentity is a recarray of shape 34*34
    '''
    global FPidentity
    if FPidentity is None: FPidentity = make_id_focalplane()

    scale_factor = figsize[0]
    title_fontsize = 0.67 * scale_factor
    label_fontsize = 0.2 * scale_factor

    fig = plt.figure(figsize=figsize)
    figure_window_title(fig, 'QUBIC Focal Plane ID Matrix')
    ax = fig.add_axes([0, 0, 1, 1])
    ax.text(0.5,
            0.96,
            'QUBIC Focal Plane ID Matrix',
            ha='center',
            va='bottom',
            transform=ax.transAxes,
            fontsize=title_fontsize)
    ax.set_xlim(-1, 35)
    ax.set_ylim(-1, 35)
    ax.set_aspect('equal')

    for fp_idx in range(len(FPidentity)):
        txt = 'Q%i' % (FPidentity[fp_idx].quadrant)
        quadrant = FPidentity[fp_idx].quadrant
        asic = FPidentity[fp_idx].ASIC
        colour = asic_colour[asic - 1]
        row = FPidentity[fp_idx].row
        col = FPidentity[fp_idx].col
        if FPidentity[fp_idx].TES == 0:
            colour = 'black'
            txt += '\nFP%4i' % FPidentity[fp_idx].index
        else:
            txt += ' %s\nFP%4i\nPIX%03i\nASIC%i\nTES%03i'\
                % (FPidentity[fp_idx].matrix.decode('UTF-8'),
                   FPidentity[fp_idx].index,
                   FPidentity[fp_idx].PIX,
                   FPidentity[fp_idx].ASIC,
                   FPidentity[fp_idx].TES)
        plot_square(col,
                    row,
                    colour=colour,
                    labelcolour='white',
                    label=txt,
                    fontsize=label_fontsize)
    return
Exemplo n.º 2
0
def plot_instrument_layout(q):
    '''
    plot the layout of the focal plane according to the qubicsoft simulation software
    q is a QubicInstrument object 
    '''
    basename = os.path.basename(q.calibration.detarray)
    config = q.config
    ttl = 'Layout for %s Instrument' % config

    fig = plt.figure(figsize=(20, 20))
    figure_window_title(fig, ttl)
    ax = fig.add_axes([0, 0, 1, 1])
    ax.set_aspect('equal')
    q.plot()
    for idx, pos in enumerate(q.detector.center[:, 0:2]):
        quadrant_idx = q.detector.quadrant[idx]
        quadrant = quadrant_idx + 1
        fpindex = q.detector.index[idx]
        lbl = 'Q%i\n%i' % (quadrant, fpindex)
        plt.text(pos[0],
                 pos[1],
                 lbl,
                 va='center',
                 ha='center',
                 fontsize=12,
                 color=quadrant_colour[quadrant_idx])

    ax.text(0.5,
            0.99,
            ttl,
            va='top',
            ha='center',
            fontsize=20,
            transform=ax.transAxes)

    return
Exemplo n.º 3
0
def demodulate(self,
               asic=None,
               TES=None,
               offset=None,
               interval=None,
               calsource=True,
               period=None,
               align_clocks=False,
               timeaxistype='pps',
               doplot=True,
               xwin=True):
    '''
    Interpolating source data to the timestamps of the data

    asic: the asic number (1 to 16)

    TES: the TES number (1 to 128)
         keyword 'all' means average all TES
         an array of size 128 of bool with the TES to average together

    offset: the constant offset between calsource timestamps and data timestamps
    this is of the order of 0.1sec
    
    interval is the time interval in which to calculate the demodulation

    calsource: you can force to not use the calsource

    period: fold at the given period.  Default is to get it from the calsource information

    align_clocks:  you can force the timestamps of the calsource and the data to start at the same time

    doplot: make plots

    xwin:  if making a plot, do not plot to screen if xwin==False
    '''
    if asic is None:
        print("\nPlease give an asic number\n")
        return None
    if TES is None:
        print(
            "\nPlease give a TES number or an array of TES to average together, or 'all'\n"
        )
        return None
    if interval is None:  # set interval to have no effect
        t0_interval = 0
        tend_interval = float(
            (dt.datetime.utcnow() + dt.timedelta(days=7)).strftime('%s'))
        interval = (t0_interval, tend_interval)
    interval = np.array(interval, dtype=np.float)

    given_period = period

    errlist = []
    retval = {}
    retval['asic'] = asic
    retval['TES'] = TES
    retval['dataset'] = self.dataset_name
    retval['calsource info'] = self.calsource_info()

    if isinstance(
            TES, np.ndarray) and TES.shape == (128, ) and TES.dtype == np.bool:
        self.printmsg('taking average of %i TES from ASIC %i' %
                      (TES.sum(), asic))
        TESstr = 'average of %i selected TES' % TES.sum()
        adu = self.timeline_array(asic=asic)
        data = adu[TES].mean(axis=0)
    elif TES == 'all':
        self.printmsg('taking average of all TES from ASIC %i' % asic)
        TESstr = 'all TES'
        adu = self.timeline_array(asic=asic)
        data = adu.mean(axis=0)
    else:
        try:
            data = self.timeline(asic=asic, TES=TES)
            if data is None: return retval
            TESstr = 'TES%03i' % TES
        except:
            self.printmsg('ERROR! Inappropriate argument for TES.')
            return retval

    t_data_orig = self.timeaxis(datatype='sci',
                                asic=asic,
                                axistype=timeaxistype)
    t_data = t_data_orig.copy()
    t0_data = t_data[0]
    if t0_data > 1494453600:  # if the timeaxis is made from the sampling time and starts at zero
        do_tzone_correction = True
    else:
        do_tzone_correction = False

    t_src_orig, v_src = self.calsource()
    if v_src is None or not calsource:
        use_calsource = False
        msg = 'No calsource.'
        self.printmsg(msg, verbosity=3)
        errlist.append(msg)
        t_src = t_data
        data_src = data
    else:
        # shift source to oscillate around zero
        use_calsource = True
        t_src = t_src_orig.copy()
        data_src = -v_src + v_src.mean(
        )  # source sampling inverted compared to data

    t0_src = t_src[
        0]  # this will be modified after the offset is calculated below
    retval['t0 source'] = t0_src

    # for some data, the source is in UT while the detector data is in localtime
    tz_offset = 0.0
    tz_count = 0
    if do_tzone_correction:
        delta_tz = np.abs(t0_data - t0_src)
        while delta_tz > 3599:
            tz_offset += 3600
            delta_tz -= 3600
            tz_count += 1
        if (t0_data - t0_src) < 0:
            tz_offset = -tz_offset
    retval['time zone offset'] = tz_offset
    retval['time zone offset hours'] = tz_count
    self.printmsg('time zone offset %f' % tz_offset, verbosity=3)

    # put data in UT (assume calsource was in UT)
    t_data -= tz_offset
    t0_data = t_data[0]
    interval -= tz_offset

    # if forcing the alignment of the clocks, make t_src start at the same time as t_data
    if align_clocks:
        self.printmsg('forcing alignment of the clocks', verbosity=3)
        align_offset = t_src[0] - t_data[0]
        t_src -= align_offset
        t0_src = t_src[0]
        self.printmsg('t0_src=%f' % t0_src, verbosity=3)
    else:
        align_offset = 0
    retval['clock forced realignment offset'] = align_offset

    # truncate the data timeline to overlapping time or to the given interval
    t0_list = [t0_data, t0_src, interval[0]]
    self.printmsg('t0_list = %s' % t0_list, verbosity=3)
    tend_list = [t_data[-1], t_src[-1], interval[1]]
    self.printmsg('tend_list = %s' % tend_list, verbosity=3)
    tstart = max(t0_list)
    tend = min(tend_list)
    self.printmsg('tstart,tend = %.6f, %.6f' % (tstart, tend), verbosity=3)
    if tend < tstart:
        self.printmsg(
            'Error!  The given interval does not have overlapping times with calsource and data.'
        )
        self.printmsg('        Maybe try with option:  align_clocks=True')
        return retval
    idx_start, idx_end = get_index_interval(t_data, (tstart, tend))
    retval['data time start index'] = idx_start
    retval['data time end index'] = idx_end
    self.printmsg('data: idx_start, idx_end = %i, %i' % (idx_start, idx_end),
                  verbosity=3)
    t_data = t_data[idx_start:idx_end]
    data = data[idx_start:idx_end]
    t0_data = t_data[0]
    retval['t0 data'] = t0_data
    t0_str = dt.datetime.utcfromtimestamp(t0_data).strftime(
        '%Y-%m-%d %H:%M:%S.%f')
    t0_filenamestr = dt.datetime.utcfromtimestamp(t0_data).strftime(
        '%Y%m%d-%H%M%S')

    # truncate the source timeline to overlapping time or to the given interval
    idxsrc_start, idxsrc_end = get_index_interval(t_src, (tstart, tend))
    self.printmsg('src: idx_start, idx_end = %i, %i' %
                  (idxsrc_start, idxsrc_end),
                  verbosity=3)
    t_src = t_src[idxsrc_start:idxsrc_end]
    data_src = data_src[idxsrc_start:idxsrc_end]

    # fit data to sine curve
    amplitude = 0.5 * (data.max() - data.min())
    calinfo = self.calsource_info()
    if given_period is None:
        if calinfo is not None and 'frequency' in calinfo['modulator'].keys():
            period = self.calsource_info()['modulator']['frequency']
        else:
            period = 1.0

    timeshift = 0.0
    amplitude_offset = data.mean()
    first_guess = (amplitude, period, timeshift, amplitude_offset)
    data_fit = fit_sine_curve(t_data - t0_data, data, first_guess=first_guess)
    retval['data fit'] = data_fit
    model_data = sine_curve_model(t_data - t0_data, data_fit['amplitude'],
                                  data_fit['period'], data_fit['timeshift'],
                                  data_fit['offset'])
    # find the first time of max (when sin(2pi((x+timeshift)/period) = 1)
    t_data_max = data_fit['period'] / 4 - data_fit['timeshift']
    # sometimes, curve_fit returns a negative amplitude, which is equivalent to a half-period phase shift
    if data_fit['amplitude'] < 0:
        t_data_max += 0.5 * data_fit['period']
    retval['t_data max'] = t_data_max

    # fit source to sine curve
    if use_calsource:
        amplitude = 0.5 * (data_src.max() - data_src.min())
        if self.calsource_info() is not None:
            period = self.calsource_info()['modulator']['frequency']
        elif given_period is None:
            period = 1.0
        else:
            period = given_period
        timeshift = 0.0
        amplitude_offset = 0.0
        first_guess = (amplitude, period, timeshift, amplitude_offset)
        source_fit = fit_sine_curve(t_src - t0_data,
                                    data_src,
                                    first_guess=first_guess)
        # find the first time of max (when sin(2pi((x+timeshift)/period) = 1)
        t_src_max = source_fit['period'] / 4 - source_fit['timeshift']
        # sometimes, curve_fit returns a negative amplitude, which is equivalent to a half-period phase shift
        if source_fit['amplitude'] < 0:
            t_src_max += 0.5 * source_fit['period']
    else:
        source_fit = data_fit
        t_src_max = t_data_max
        data_src = data
        t_src = t_data

    retval['source fit'] = source_fit
    retval['t_src max'] = t_src_max
    if given_period is None:
        period = source_fit['period']
    else:
        period = given_period
    retval['period'] = period  # this is the period we use for demodulation

    # find the constant timestamp offset between source and data
    # for more info: http://qubic.in2p3.fr/wiki/pmwiki.php/TD/Demodulation
    if offset is None:
        offset = t_data_max - t_src_max
    retval['source-data time offset'] = offset
    self.printmsg('source-data time offset %f' % offset, verbosity=3)

    # adjust the source timeline by the constant offset
    # go back to the original source data before applying the offset
    # and then find the appropriate interval
    if use_calsource:
        t_src_orig, v_src = self.calsource()
        t_src = t_src_orig.copy()
        data_src = -v_src + v_src.mean()

        t_src += (offset - align_offset)

        t0_src = t_src[0]
        # truncate the source timeline to overlapping time or to the given interval
        idxsrc_start, idxsrc_end = get_index_interval(t_src, (tstart, tend))
        retval['source time start index'] = idxsrc_start
        retval['source time end index'] = idxsrc_end
        self.printmsg('src: idx_start, idx_end = %i, %i' %
                      (idxsrc_start, idxsrc_end),
                      verbosity=3)
        t_src = t_src[idxsrc_start:idxsrc_end]
        data_src = data_src[idxsrc_start:idxsrc_end]
        model_src = sine_curve_model(t_src - t0_data, source_fit['amplitude'],
                                     source_fit['period'],
                                     source_fit['timeshift'] - offset,
                                     source_fit['offset'])

    # some values to return
    npts = len(data)
    retval['t_data'] = t_data
    retval['data'] = data
    retval['n data points'] = npts
    retval['interval'] = (t_data[0], t_data[-1])

    ### Interpolating source data to the timestamps of the data
    ### and making the product of the detector and the source
    ### the source is renormalized, but the data is only shifted to oscillate around 0
    if use_calsource:
        self.printmsg(
            'demodulate: number of points for t_data, t_src, data_src: %i, %i, %i'
            % (len(t_data), len(t_src), len(data_src)),
            verbosity=3)
        data_src_interp = np.interp(t_data - t0_data, t_src - t0_data,
                                    data_src)
    else:
        data_src_interp = data
    product = renorm(data_src_interp) * (data - data.mean())
    retval['calsource interpolated to data time axis'] = data_src_interp

    # demodulate, smoothed over a period
    freq_sampling = 1. / ((t_data[-1] - t_data[0]) / npts)
    size_period = int(freq_sampling * period) + 1
    filter_period = np.ones(size_period) / size_period
    try:
        demodulated = fftconvolve(product, filter_period, mode='same')
    except:
        msg = 'ERROR calculating demodulation'
        errlist.append(msg)
        self.printmsg(msg, verbosity=3)
        demodulated = np.zeros(size_period)

    retval['freq_sampling'] = freq_sampling
    retval['size_period'] = size_period
    retval['filter_period'] = filter_period
    retval['demodulated'] = demodulated
    retval['n demodulated points'] = len(demodulated)

    # rebin the result by period bins
    period_index = ((t_data - t_data[0]) / period).astype(int)
    allperiods = np.unique(period_index)
    binned_t = np.zeros(len(allperiods))
    binned_demodulated = np.zeros((len(allperiods)))
    binned_stdev = np.zeros((len(allperiods)))
    binned_npts = np.zeros((len(allperiods)))
    for idx, p_index in enumerate(allperiods):
        idxrange = period_index == p_index
        binned_t[idx] = np.mean(t_data[idxrange] - t_data[0])
        binned_demodulated[idx] = np.mean(demodulated[idxrange])
        binned_stdev[idx] = np.std(
            demodulated[idxrange])  # / np.sqrt(idxrange.sum()) really?
        binned_npts[idx] = idxrange.sum()
    retval['binned t'] = binned_t
    retval['binned demodulated'] = binned_demodulated
    retval['binned stdev'] = binned_stdev
    retval['demodulated signal'] = binned_demodulated[1:-1].mean()
    retval['demodulated signal error'] = binned_stdev[1:-1].mean()
    retval['npts per bin'] = binned_npts

    # fold the data and the calsource
    folded_t_data, folded_data, folded_dataerr = fold_data(
        t_data - t0_data, data, period)
    retval['folded t_data'] = folded_t_data
    retval['folded data'] = folded_data
    retval['folded data error'] = folded_dataerr
    if use_calsource:
        folded_t_src, folded_src, folded_srcerr = fold_data(
            t_src - t0_data, data_src, period)
        retval['folded t_src'] = folded_t_src
        retval['folded src'] = folded_src
        retval['folded src error'] = folded_srcerr

    # if not plotting, exit now
    if not doplot:
        retval['axes'] = None
        retval['fig'] = None
        return retval

    if xwin: plt.ion()
    else: plt.ioff()
    fig = plt.figure()
    retval['fig'] = fig
    figure_window_title(fig, 'data/calsource interpolation')
    axes = []

    # first column of plots
    data_label = 'ASIC %i, %s' % (asic, TESstr)
    axes.append(fig.add_axes((0.03, 0.68, 0.62, 0.3)))
    axes[-1].plot((t_data - t0_data),
                  renorm(data),
                  label=data_label,
                  ls='none',
                  marker='x')
    axes[-1].plot((t_data - t0_data),
                  renorm(model_data),
                  label='data sine model',
                  color='orange')
    axes[-1].plot([t_data_max, t_data_max], [-2, 2],
                  color='orange',
                  linewidth=3,
                  label='first data peak')
    if use_calsource:
        axes[-1].plot((t_src - t0_data),
                      renorm(data_src),
                      label='source',
                      ls='none',
                      marker='+')
        axes[-1].plot((t_src - t0_data),
                      renorm(model_src),
                      label='source sine model',
                      color='red')
        axes[-1].plot([t_src_max, t_src_max], [-2, 2],
                      color='red',
                      linewidth=3,
                      label='first source peak')
    axes[-1].legend()
    axes[-1].text(0.5,
                  1.01,
                  self.infotext(),
                  ha='center',
                  va='bottom',
                  transform=axes[-1].transAxes)
    axes[-1].set_xlim(0, t_data[-1] - t0_data)
    axes[-1].tick_params(labelbottom=False)

    axes.append(fig.add_axes((0.03, 0.35, 0.62, 0.3)))
    axes[-1].plot((t_data - t0_data),
                  renorm(data),
                  label=data_label,
                  marker='v',
                  ls='none')
    if use_calsource:
        axes[-1].plot((t_data - t0_data),
                      renorm(data_src_interp),
                      label='SRC (interp on data)',
                      marker='^',
                      ls='none')
    axes[-1].set_xlim(0, t_data[-1] - t0_data)
    axes[-1].legend()
    axes[-1].tick_params(labelbottom=False)

    axes.append(fig.add_axes((0.03, 0.03, 0.62, 0.3)))
    axes[-1].plot((t_data - t0_data),
                  product,
                  label='data $\\times$ source',
                  marker='o',
                  markersize=1,
                  ls='none')
    axes[-1].legend()
    axes[-1].set_xlabel('date / seconds since %s' % t0_str)
    axes[-1].set_xlim(0, t_data[-1] - t0_data)

    # second column of plots

    # folded
    axes.append(fig.add_axes((0.70, 0.68, 0.28, 0.3)))
    axes[-1].plot((t_data - t0_data) % period,
                  data,
                  label='folded %s' % data_label,
                  ls='none',
                  marker='x')
    axes[-1].plot(folded_t_data,
                  folded_data,
                  label='folded and averaged %s' % data_label,
                  ls='solid',
                  linewidth=3,
                  color='yellow')
    axes[-1].errorbar(folded_t_data,
                      folded_data,
                      yerr=folded_dataerr,
                      ls='none',
                      color='yellow',
                      capthick=2,
                      capsize=2)
    if use_calsource:
        axcal = axes[-1].twinx()
        axcal.plot((t_src - t0_data) % period,
                   data_src,
                   label='folded source',
                   ls='none',
                   marker='+')
        axcal.plot(folded_t_src,
                   folded_src,
                   label='folded and averaged source',
                   ls='solid',
                   linewidth=3,
                   color='red')
    axes[-1].text(0.5,
                  1.0,
                  'folding period = %.6f seconds' % period,
                  ha='center',
                  va='bottom',
                  transform=axes[-1].transAxes)
    axes[-1].legend()

    # demodulated
    axes.append(fig.add_axes((0.70, 0.35, 0.28, 0.3)))
    axes[-1].plot((t_data - t0_data),
                  demodulated,
                  label='demodulated',
                  ls='solid')
    axes[-1].errorbar(binned_t,
                      binned_demodulated,
                      yerr=binned_stdev,
                      label='binned',
                      marker='x',
                      markersize=3,
                      ls='none',
                      color='red',
                      capsize=3,
                      capthick=3)
    axes[-1].legend(loc='lower left')
    axes[-1].tick_params(labelbottom=False)
    # try:
    #     expo = int(np.log10(retval['demodulated signal']))
    #     val = retval['demodulated signal']/10**expo
    #     sig_str = '$%.6f\\times10^{%i}$' % (val,expo)
    #     expo = int(np.log10(retval['demodulated signal error']))
    #     val = retval['demodulated signal error']/10**expo
    #     err_str = '$%.2f\\times10^{%i}$' % (val,expo)
    # except:
    sig_str = '%.6f' % retval['demodulated signal']
    err_str = '%.2f' % retval['demodulated signal error']
    txt = 'demodulated signal = %s $\\pm$ %s' % (sig_str, err_str)
    if len(errlist) > 0:
        txt = '\n'.join([txt] + errlist)
    boxprops = dict(boxstyle='round', facecolor='wheat', alpha=0.5)
    axes[-1].text(0.5,
                  0.05,
                  txt,
                  ha='center',
                  va='bottom',
                  transform=axes[-1].transAxes,
                  bbox=boxprops)
    xlim = axes[-1].axis()[:2]

    # number of points per bin
    axes.append(fig.add_axes((0.70, 0.03, 0.28, 0.3)))
    axes[-1].bar(binned_t, binned_npts, align='center')
    axes[-1].set_xlim(xlim)
    axes[-1].set_xlabel('period / seconds')
    axes[-1].set_ylabel('number of points per bin')

    pngname = 'demodulation_diagnostic_ASIC%i_%s_%s.png' % (
        asic, TESstr.replace(' ', ''), t0_filenamestr)
    fig.savefig(pngname, format='png', dpi=100, bbox_inches='tight')
    retval['pngname'] = pngname

    retval['axes'] = axes
    if not xwin:
        retval['fig'] = None
        retval['axes'] = None
        plt.close(fig)
    return retval
Exemplo n.º 4
0
def plot_timestamp_diagnostic_fig2(self,
                                   analysis=None,
                                   hk=None,
                                   zoomx=None,
                                   zoomy=None,
                                   asic=None,
                                   ax=None,
                                   fontsize=12):
    '''
    make a plot of the timestamp diagnostic with the slope removed
    '''

    if analysis is None:
        analysis = self.timestamp_diagnostic(hk=hk, asic=asic)
    if analysis is None: return

    ttl = '%s horizontal' % analysis['tstamps_title']
    png_rootname = '%s_%s' % (ttl.lower().replace(
        ' ', '_'), self.obsdate.strftime('%Y%m%d-%H%M%S'))

    newplot = False
    if ax is None:
        fig = plt.figure(figsize=(16, 8))
        figure_window_title(fig, ttl)
        fig.suptitle(ttl, fontsize=fontsize)
        ax = fig.add_axes((0.05, 0.08, 0.9, 0.8))

    ax.text(0.50,
            1.00,
            ttl,
            ha='center',
            va='bottom',
            fontsize=fontsize,
            transform=ax.transAxes)
    ax.text(0.99,
            1.01,
            analysis['sample_period_txt'],
            ha='right',
            va='bottom',
            fontsize=fontsize,
            transform=ax.transAxes)
    ax.text(0.01,
            1.05,
            'avg number of samples between events: %.2f' %
            analysis['samples_per_pps'].mean(),
            fontsize=fontsize,
            transform=ax.transAxes)
    if analysis['lost_txt'] is not None:
        ax.text(0.99,
                1.1,
                analysis['lost_txt'],
                ha='right',
                va='bottom',
                fontsize=fontsize,
                transform=ax.transAxes)

    tstamps_horiz = analysis['tstamps'] - analysis['indextime']
    compstamps_horiz = analysis['compstamps'] - analysis['indextime']
    gps_horiz = analysis['gps'] - analysis['indextime']
    pps_indexes = analysis['pps_indexes']
    yminmax = (tstamps_horiz.min(), tstamps_horiz.max())
    # measure the peak to peak between the first and last PPS
    tstamps_horiz_between_pps = tstamps_horiz[pps_indexes[0]:pps_indexes[-1]]
    peak2peak = tstamps_horiz_between_pps.max(
    ) - tstamps_horiz_between_pps.min()
    peak2peak_txt = 'peak to peak variation: %.2f msec' % (1000 * peak2peak)
    self.printmsg(peak2peak_txt, verbosity=2)
    ax.text(0.01,
            1.0,
            peak2peak_txt,
            ha='left',
            va='bottom',
            fontsize=fontsize,
            transform=ax.transAxes)

    ax.plot([0, len(analysis['indextime'])], [0, 0], label='index time')
    ax.plot(tstamps_horiz, ls='none', marker='o', label='derived timestamps')
    ax.plot(compstamps_horiz, ls='none', marker='*', label='computer time')
    ax.plot(gps_horiz, ls='none', marker='x', label='GPS date')

    ax.set_ylabel('seconds', fontsize=fontsize)
    ax.set_xlabel('sample number', fontsize=fontsize)
    ax.set_ylim(yminmax)
    for idx in analysis['weird_idx']:
        ax.plot((idx, idx), yminmax, color='red', ls='dashed')
    ax.legend(fontsize=fontsize, loc='upper right')

    if newplot:
        pngname = '%s_full.png' % png_rootname
        fig.savefig(pngname, format='png', dpi=100, bbox_inches='tight')

    if zoomx is not None:
        ax.set_xlim(zoomx)

    if zoomy is not None:
        ax.set_ylim(zoomy)

    if zoomx is not None or zoomy is not None:
        if newplot:
            pngname = '%s_zoom.png' % png_rootname
            fig.savefig(pngname, format='png', dpi=100, bbox_inches='tight')

    return
Exemplo n.º 5
0
def plot_timestamp_diagnostic_fig1(self,
                                   analysis=None,
                                   hk=None,
                                   zoomx=None,
                                   zoomy=None,
                                   asic=None,
                                   ax=None,
                                   fontsize=12):
    '''
    make a plot of the timestamp diagnostic
    '''

    if analysis is None:
        analysis = self.timestamp_diagnostic(hk=hk, asic=asic)
    if analysis is None: return

    ttl = analysis['tstamps_title']
    png_rootname = '%s_%s' % (ttl.lower().replace(
        ' ', '_'), self.obsdate.strftime('%Y%m%d-%H%M%S'))

    newplot = False
    if ax is None:
        newplot = True
        fig = plt.figure(figsize=(16, 8))
        figure_window_title(fig, ttl)
        fig.suptitle(self.infotext(), fontsize=fontsize)
        ax = fig.add_axes((0.05, 0.08, 0.9, 0.8))

    ax.text(0.50,
            1.00,
            ttl,
            ha='center',
            va='bottom',
            fontsize=fontsize,
            transform=ax.transAxes)
    ax.text(0.99,
            1.01,
            analysis['sample_period_txt'],
            ha='right',
            va='bottom',
            fontsize=fontsize,
            transform=ax.transAxes)
    ax.text(0.01,
            1.05,
            'avg number of samples between events: %.2f' %
            analysis['samples_per_pps'].mean(),
            fontsize=fontsize,
            transform=ax.transAxes)
    if analysis['lost_txt'] is not None:
        ax.text(0.99,
                1.1,
                analysis['lost_txt'],
                ha='right',
                va='bottom',
                fontsize=fontsize,
                transform=ax.transAxes)

    # mark problems with a vertical line
    yminmax = (analysis['compstamps'].min(), analysis['compstamps'].max())
    pps_high = analysis['pps_high']
    pps_indexes = analysis['pps_indexes']
    ax.plot(analysis['indextime'], ls='none', marker='d', label='index time')
    ax.plot(analysis['tstamps'],
            ls='none',
            marker='o',
            label='derived timestamps')
    ax.plot(analysis['compstamps'],
            ls='none',
            marker='*',
            label='computer time')
    ax.plot(analysis['gps'], ls='none', marker='x', label='GPS date')
    ax.plot(pps_high,
            analysis['tstamps'][pps_high],
            ls='none',
            marker='^',
            label='pps high')
    ax.plot(pps_indexes,
            analysis['tstamps'][pps_indexes],
            ls='none',
            marker='o',
            label='pps indexes',
            markerfacecolor='none',
            markersize=16,
            color='black')
    for idx in analysis['weird_idx']:
        ax.plot((idx, idx), yminmax, color='red', ls='dashed')

    ax.set_ylabel('seconds', fontsize=fontsize)
    ax.set_ylim(yminmax)
    ax.set_xlabel('sample number', fontsize=fontsize)
    ax.tick_params(axis='both', labelsize=fontsize)
    ax.legend(fontsize=fontsize, loc='upper left')
    if newplot:
        pngname = '%s_full.png' % png_rootname
        fig.savefig(pngname, format='png', dpi=100, bbox_inches='tight')

    if zoomx is not None:
        ax.set_xlim(zoomx)
        ax.set_ylim(tstamps[zoomx[0]], tstamps[zoomx[1]])
        if newplot:
            pngname = '%s_zoom.png' % png_rootname
            ax.savefig(pngname, format='png', dpi=100, bbox_inches='tight')
    return
Exemplo n.º 6
0
def plot_pps_nsamples(self,
                      analysis=None,
                      hk=None,
                      zoomx=None,
                      zoomy=None,
                      asic=None,
                      ax=None,
                      fontsize=12):
    '''
    make a plot of the number of samples per PPS 
    '''

    if analysis is None:
        analysis = self.timestamp_diagnostic(hk=hk, asic=asic)
    if analysis is None:
        if ax is None:
            return
        ax.text(0.5,
                0.5,
                'Insufficient PPS Data',
                va='center',
                ha='center',
                fontsize=2 * fontsize,
                transform=ax.transAxes)
        ax.get_yaxis().set_visible(False)
        ax.get_xaxis().set_visible(False)
        return ax

    ttl = analysis['nsamples_title']
    png_rootname = '%s_%s' % (ttl.lower().replace(
        ' ', '_'), self.obsdate.strftime('%Y%m%d-%H%M%S'))

    newplot = False
    if ax is None:
        newplot = True
        fig = plt.figure(figsize=(16, 8))
        figure_window_title(fig, ttl)
        fig.suptitle(self.infotext(), fontsize=fontsize)
        ax = fig.add_axes((0.05, 0.08, 0.9, 0.8))

    ax.text(0.01,
            1.00,
            ttl,
            ha='left',
            va='bottom',
            fontsize=fontsize,
            transform=ax.transAxes)
    ax.text(0.99,
            1.01,
            analysis['sample_period_txt'],
            ha='right',
            va='bottom',
            fontsize=fontsize,
            transform=ax.transAxes)
    ax.text(0.01,
            1.05,
            analysis['avg samples_per_pps txt'],
            fontsize=fontsize,
            transform=ax.transAxes)
    if analysis['lost_txt'] is not None:
        ax.text(0.99,
                1.1,
                analysis['lost_txt'],
                ha='right',
                va='bottom',
                fontsize=fontsize,
                transform=ax.transAxes)

    if analysis['samples_per_pps'] is not None:
        ax.plot(analysis['samples_per_pps'])
    else:
        ax.text(0.5,
                0.5,
                'Insufficient PPS data',
                va='center',
                ha='center',
                fontsize=2 * fontsize,
                transform=ax.transAxes)
    ax.set_ylabel('Number of samples per PPS event', fontsize=fontsize)
    ax.set_xlabel('PPS event number', fontsize=fontsize)
    ax.tick_params(axis='both', labelsize=fontsize)
    for idx in analysis['weird_event']:
        ax.plot((idx, idx), (analysis['samples_per_pps'].min(),
                             analysis['samples_per_pps'].max()),
                color='red',
                ls='dashed')

    if newplot:
        pngname = '%s_full.png' % png_rootname
        fig.savefig(pngname, format='png', dpi=100, bbox_inches='tight')

    if zoomx is not None:
        ax.set_xlim(zoomx)
        if newplot:
            pngname = '%s_zoom.png' % png_rootname
            fig.savefig(pngname, format='png', dpi=100, bbox_inches='tight')
    return
Exemplo n.º 7
0
def cal_sketch(
        pointing_ang=50,  # QUBIC nominal pointing elevation angle
        D=9.0,  # horizontal distance to QUBIC from the calibration source
        Hqubic=2.571,  # vertical height of QUBIC window from the floor
        Hmirror=3.7,  # vertical height of the centre of the flat mirror
        Hsource=4.0,  # vertical height of the calibration source
        mirror_len=1.4,  # length of the mirror
        cryo_width=1.436752,  # width of the QUBIC cryostat
        cryo_height=1.542618,  # height of the QUBIC cryostat
        win_offset=0.241979,  # distance of the window from the centre axis of the cryostat
        xlength=13,  # x extent of the drawing
        ylength=7,  # y extent of the drawing
        transparency=True,
        figsize=(20, 16),
        fontsize=16):

    window_pos = [-D, Hqubic]
    cal_pos = [0, Hsource]

    pointing_ang_rad = radians(pointing_ang)

    fig = plt.figure(figsize=figsize)
    figure_window_title(fig, 'Calibration Source Sketch')
    ax = fig.add_axes((0.05, 0.05, 0.90, 0.90))

    # QUBIC window marker
    x = window_pos[0]
    y = window_pos[1]
    ax.plot(x, y, color='red', linestyle='none', marker='D')
    txt = '   QUBIC position (%.2fm, %.2fm)' % (D, Hqubic)
    ax.text(x + 0.7,
            y,
            txt,
            color='black',
            fontsize=fontsize,
            ha='left',
            va='bottom')

    # cal source position marker
    x = cal_pos[0]
    y = cal_pos[1]
    ax.plot(x, y, color='green', linestyle='none', marker='D')
    txt = 'cal source height %.2fm  ' % cal_pos[1]
    ax.text(x,
            y,
            txt,
            color='black',
            fontsize=fontsize,
            ha='right',
            va='bottom')

    # line showing QUBIC line of sight
    s = 2
    hyp = s / sin(pointing_ang_rad)
    c = hyp * cos(pointing_ang_rad)
    pt1 = window_pos
    pt2 = [window_pos[0] - c, window_pos[1] + s]

    # intersection of cal mirror height with QUBIC line of sight
    # y = mx+b : line of sight
    # y = Hmirror
    m = (pt2[1] - pt1[1]) / (pt2[0] - pt1[0])
    b = pt1[1] - m * pt1[0]

    xmirror = (Hmirror - b) / m
    mirror_pos = [xmirror, Hmirror]

    x = [window_pos[0], mirror_pos[0]]
    y = [window_pos[1], mirror_pos[1]]
    ax.plot(x, y, color='red', linewidth=3)

    # line from cal source to mirror
    x = [cal_pos[0], mirror_pos[0]]
    y = [cal_pos[1], mirror_pos[1]]
    ax.plot(x, y, color='green', linewidth=3)

    delta_s = y[0] - y[1]
    delta_c = -(x[1] - x[0])
    delta_ang_rad = atan(delta_s / delta_c)
    delta_ang = degrees(delta_ang_rad)

    # reflection angle at the mirror
    reflection_ang = delta_ang + pointing_ang

    # mirror has normal at half the reflection angle from the QUBIC pointing angle
    mirror_norm_ang = pointing_ang - 0.5 * reflection_ang
    mirror_norm_ang_rad = radians(mirror_norm_ang)
    mirror_ang = mirror_norm_ang + 90
    mirror_ang_rad = radians(mirror_ang)

    # a dashed line to show the mirror normal
    L = 1.0
    dx = L * cos(mirror_norm_ang_rad)
    dy = L * sin(mirror_norm_ang_rad)
    x2 = mirror_pos[0] + dx
    y2 = mirror_pos[1] - dy
    x = [mirror_pos[0], x2]
    y = [mirror_pos[1], y2]
    ax.plot(x, y, color='black', linestyle='dashed', linewidth=1)
    txt = 'reflection angle at mirror = %.2f$^\circ$' % reflection_ang
    ax.text(x2,
            y2,
            txt,
            color='black',
            fontsize=fontsize,
            ha='left',
            va='center')

    # a line 1.4m long to show the mirror
    mirror_dx = 0.5 * mirror_len * cos(mirror_ang_rad)
    mirror_dy = 0.5 * mirror_len * sin(mirror_ang_rad)

    x = [mirror_pos[0] + mirror_dx, mirror_pos[0] - mirror_dx]
    y = [mirror_pos[1] - mirror_dy, mirror_pos[1] + mirror_dy]
    ax.plot(x, y, color='black', linewidth=3)

    # a dashed line showing the mirror horizontal extension
    x = [mirror_pos[0] - mirror_dx, mirror_pos[0] + mirror_dx]
    y = [mirror_pos[1] + mirror_dy, mirror_pos[1] + mirror_dy]
    ax.plot(x, y, color='black', linestyle='dashed')
    #ax.plot([x[1],x[1]],[y[1],0],color='black',linestyle='dashed')

    txt = 'mirror horizontal extension = %.2fm' % abs(2 * mirror_dx)
    txt = '%.2fm' % abs(2 * mirror_dx)
    ax.text(x[0],
            y[0],
            txt,
            ha='right',
            va='bottom',
            fontsize=fontsize,
            color='black')

    if mirror_ang > 90:
        txt = '  mirror angle = %.2f$^\circ$' % (mirror_ang - 90)
    else:
        txt = '  mirror angle = %.2f$^\circ$' % mirror_ang
    ax.text(x[0],
            y[0],
            txt,
            ha='left',
            va='top',
            fontsize=fontsize,
            color='black')

    # dashed line to show mirror position
    x = [mirror_pos[0], mirror_pos[0]]
    y = [mirror_pos[1], 0]
    ax.plot(x, y, color='black', linestyle='dashed')

    x = mirror_pos[0]
    y = mirror_pos[1]
    txt = ' flat mirror at\n%.2fm, %.2fm' % (abs(mirror_pos[0]), mirror_pos[1])
    ax.text(x,
            y,
            txt,
            color='black',
            ha='right',
            va='bottom',
            fontsize=fontsize)

    # total optical path
    Dcal_mirror = sqrt((cal_pos[0] - mirror_pos[0])**2 +
                       (cal_pos[1] - mirror_pos[1])**2)
    Dqubic_mirror = sqrt((mirror_pos[0] - window_pos[0])**2 +
                         (mirror_pos[1] - window_pos[1])**2)
    optical_dist = Dcal_mirror + Dqubic_mirror

    # edge line
    x = [0, 0]
    y = [0, Hsource]
    #ax.plot(x,y,color='blue')

    # bottom line
    x = [1 - xlength, 1]
    y = [0, 0]
    ax.plot(x, y, color='black', linewidth=0.5, linestyle='dotted')

    # horizontal line at window height to compare to the drawing by Didier
    x = [1 - xlength, 1]
    y = [window_pos[1], window_pos[1]]
    ax.plot(x, y, color='black', linewidth=0.5, linestyle='dotted')

    # draw a box outline of the QUBIC cryostat
    top_centre = [
        window_pos[0] - win_offset * sin(pointing_ang_rad),
        window_pos[1] - win_offset * cos(pointing_ang_rad)
    ]
    bot_centre = [
        top_centre[0] + cryo_height * cos(pointing_ang_rad),
        top_centre[1] - cryo_height * sin(pointing_ang_rad)
    ]
    x = [bot_centre[0], top_centre[0]]
    y = [bot_centre[1], top_centre[1]]
    ax.plot(x, y, color='black', linewidth=1, linestyle='dotted')
    #ax.plot(top_centre[0],top_centre[1],marker='X',color='black')

    cryo_corner1 = (top_centre[0] - 0.5 * cryo_width * sin(pointing_ang_rad),
                    top_centre[1] - 0.5 * cryo_width * cos(pointing_ang_rad))
    cryo_corner2 = (top_centre[0] + 0.5 * cryo_width * sin(pointing_ang_rad),
                    top_centre[1] + 0.5 * cryo_width * cos(pointing_ang_rad))
    cryo_corner3 = (bot_centre[0] + 0.5 * cryo_width * sin(pointing_ang_rad),
                    bot_centre[1] + 0.5 * cryo_width * cos(pointing_ang_rad))
    cryo_corner4 = (bot_centre[0] - 0.5 * cryo_width * sin(pointing_ang_rad),
                    bot_centre[1] - 0.5 * cryo_width * cos(pointing_ang_rad))
    pts = [
        cryo_corner1, cryo_corner2, cryo_corner3, cryo_corner4, cryo_corner1
    ]
    x = [val[0] for val in pts]
    y = [val[1] for val in pts]
    ax.plot(x, y, color='black', linestyle='dotted')

    # plot extents
    ax.set_xlim(1 - xlength, 1)
    ax.set_ylim(-1, -1 + ylength)
    # equal aspect ratio
    #ax.set_aspect('equal', 'datalim')
    ax.set_aspect('equal')

    # labels
    txt = 'Total optical path length = %.2fm' % optical_dist
    ax.text(0.5,
            0.1,
            txt,
            va='top',
            ha='center',
            fontsize=fontsize,
            transform=ax.transAxes)

    ax.text(0.5,
            1.01,
            'QUBIC Calibration Source layout',
            ha='center',
            va='bottom',
            fontsize=fontsize,
            transform=ax.transAxes)
    ax.tick_params(labelsize=fontsize)

    pngname = '/home/work/qubic/pix/calsource_setup/QUBIC_calibration_source_layout_sketch.png'
    fig.savefig(pngname,
                format='png',
                dpi=300,
                bbox_inches='tight',
                transparent=transparency)
    return
Exemplo n.º 8
0
def plot_ASD(self,
             TES=None,
             timeline_index=0,
             save=True,
             ax_timeline=None,
             ax_asd=None,
             xwin=True,
             amin=None,
             amax=None,
             imin=None,
             imax=None,
             nbins=None,
             indmin=None,
             indmax=None):  #MP
    '''
    plot the Amplitude Spectral Density
    '''

    if not self.exist_timeline_data():
        print('ERROR! No timeline data!')
        return None

    ntimelines = self.ntimelines()
    if timeline_index >= ntimelines:
        print(
            'ERROR! timeline index out of range.  Enter an index between 0 and %i'
            % (ntimelines - 1))
        return None

    if TES is None:
        print('Please enter a valid TES number, between 1 and %i' %
              self.NPIXELS)
        return None
    TES_idx = TES_index(TES)

    if nbins is None: nbins = 1

    result = {}
    result['timeline_index'] = timeline_index
    result['TES'] = TES
    result['nbins'] = nbins
    timeline = self.timeline(TES, timeline_index)
    obsdate = self.tdata[timeline_index]['BEG-OBS']
    result['obsdate'] = obsdate

    tinteg = self.tinteg
    if 'INT-TIME' in self.tdata[timeline_index].keys():
        tinteg = self.tdata[timeline_index]['INT-TIME']

    Tbath = self.tdata[timeline_index]['TES_TEMP']
    result['Tbath'] = Tbath

    min_bias = self.min_bias
    if 'BIAS_MIN' in self.tdata[timeline_index].keys():
        min_bias = self.tdata[timeline_index]['BIAS_MIN']
    if min_bias is None: min_bias = self.min_bias
    result['min_bias'] = min_bias

    max_bias = self.max_bias
    if 'BIAS_MAX' in self.tdata[timeline_index].keys():
        max_bias = self.tdata[timeline_index]['BIAS_MAX']
    if max_bias is None: max_bias = self.max_bias
    result['max_bias'] = max_bias

    n_masked = self.n_masked()
    result['n_masked'] = n_masked

    current = self.ADU2I(timeline)  # uA
    timeline_npts = len(timeline)
    result['timeline_npts'] = timeline_npts

    if indmin is None: indmin = 0  #MP
    if indmax is None: indmax = timeline_npts - 1  #MP

    #    bin_npts=timeline_npts//nbins #MP
    bin_npts = (indmax - indmin + 1) // nbins  #MP
    result['bin_npts'] = bin_npts

    if 'NPIXSAMP' in self.tdata[timeline_index].keys():
        npixsampled = self.tdata[timeline_index]['NPIXSAMP']
    else:
        npixsampled = self.NPIXELS

    sample_period = self.sample_period()
    time_axis = sample_period * np.arange(timeline_npts)

    ttl = 'Timeline and Amplitude Spectral Density'
    subttl = '\nQUBIC Array %s, ASIC %i, TES #%i, T$_\mathrm{bath}$=%.1f mK' % (
        self.detector_name, self.asic, TES, 1000 * Tbath)
    pngname='QUBIC_Array-%s_ASIC%i_TES%03i_timeline%03i_AmplitudeSpectralDensity_%s.png'\
             % (self.detector_name,self.asic,TES,timeline_index,obsdate.strftime('%Y%m%dT%H%M%SUTC'))

    pngname_fullpath = self.output_filename(pngname)
    result['pngname'] = pngname_fullpath

    # setup plot if we haven't done so already
    if xwin: plt.ion()
    else: plt.ioff()
    if ax_timeline is None or ax_asd is None:
        nrows = 1
        ncols = 2
        fig, axes = plt.subplots(nrows, ncols, sharex=False, sharey=False)
        ax_timeline = axes[0]
        ax_asd = axes[1]
        if xwin: figure_window_title(fig, ttl)
        fig.suptitle(ttl + subttl, fontsize=16)
    result['ax_timeline'] = ax_timeline
    result['ax_asd'] = ax_asd

    txt_x = 0.05
    txt_y = 0.02

    time_txt = obsdate.strftime('%Y-%m-%d %H:%M:%S UTC')
    time_label = '%s Tbath=%.1fmK' % (time_txt, Tbath * 1000)
    full_label='%s\nTbath=%.1fmK\nsample period=%.3fmsec\nintegration time=%.1fsec\nnbins=%i\nmin bias=%.2fV\nmax bias=%.2fV\nNpix sampled=%i'\
                % (time_txt,1000*Tbath,1000*sample_period,tinteg,nbins,min_bias,max_bias,npixsampled)

    # sampling frequency
    fs = 1.0 / self.sample_period()

    PSD, freqs = mlab.psd(current[indmin:indmax],
                          Fs=fs,
                          NFFT=bin_npts,
                          window=mlab.window_hanning,
                          detrend='mean')

    ax_timeline.cla()
    ax_timeline.plot(time_axis[indmin:indmax], current[indmin:indmax])
    ax_timeline.text(txt_x, txt_y, time_label, transform=ax_timeline.transAxes)
    ax_timeline.set_xlabel('time  /  seconds')
    ax_timeline.set_ylabel('Current  /  $\mu$A')
    if imin is None: imin = min(current)
    if imax is None: imax = max(current)
    ax_timeline.set_ylim((imin, imax))
    if xwin: plt.pause(0.01)

    ASD = np.sqrt(PSD)  # in uA
    ax_asd.cla()
    ax_asd.loglog(freqs, ASD)
    boxprops = dict(boxstyle='round', facecolor='wheat', alpha=0.5)
    ax_asd.text(txt_x,
                txt_y,
                full_label,
                transform=ax_asd.transAxes,
                ha='left',
                va='bottom',
                bbox=boxprops)
    ax_asd.set_xlabel('frequency')
    ax_asd.set_ylabel('Amplitude / $\mu$A')
    if amin is None: amin = min(ASD)
    if amax is None: amax = max(ASD)
    ax_asd.set_ylim((amin, amax))
    if xwin: plt.pause(0.01)

    if save:
        plt.savefig(pngname_fullpath,
                    format='png',
                    dpi=100,
                    bbox_inches='tight')

    if xwin: plt.show()
    else: plt.close(fig)
    return result
Exemplo n.º 9
0
def plot_azel(self, ax=None, fontsize=12):
    '''
    plot the azimuth and elevation positions
    '''
    az = self.azimuth()
    el = self.elevation()
    t = self.timeaxis('platform')

    ttl = 'Platform position'
    pngname = self.assign_imagename(ttl.replace(' ', '_'))

    if ax is None:
        newplot = True
        ttl += '\n' + self.infotext()
        plt.ion()
        fig = plt.figure()
        figure_window_title(fig,
                            '%s for dataset %s' % (ttl, self.dataset_name))
        fig.suptitle(ttl, fontsize=fontsize)
        ax = fig.add_axes((0.05, 0.1, 0.9, 0.75))
    else:
        newplot = False
        ax.text(0.5,
                1.0,
                ttl,
                va='bottom',
                ha='center',
                fontsize=fontsize,
                transform=ax.transAxes)

    if t is None:
        ax.text(0.5,
                0.5,
                'No Platform information',
                va='center',
                ha='center',
                fontsize=2 * fontsize,
                transform=ax.transAxes)
        ax.get_yaxis().set_visible(False)
        ax.get_xaxis().set_visible(False)
        self.printmsg('No housekeeping information!', verbosity=2)
        if newplot:
            fig.savefig(pngname, format='png', dpi=100, bbox_inches='tight')
        return ax

    tdate = []
    for tstamp in t:
        tdate.append(dt.datetime.utcfromtimestamp(tstamp))

    if az is not None:
        ax.plot(tdate,
                az,
                marker='D',
                markersize=0.2 * fontsize,
                ls='none',
                color='blue',
                label='Azimuth')
    if el is not None:
        ax.plot(tdate,
                el,
                marker='D',
                markersize=0.2 * fontsize,
                ls='none',
                color='red',
                label='Elevation')

    if az is None:
        ax.text(0.5,
                0.5,
                'No azimuth information',
                va='center',
                ha='center',
                fontsize=2 * fontsize,
                transform=ax.transAxes)
    if el is None:
        ax.text(0.5,
                0.4,
                'No elevation information',
                va='center',
                ha='center',
                fontsize=2 * fontsize,
                transform=ax.transAxes)

    ax.set_ylabel('Position / Degrees', fontsize=fontsize)
    ax.set_xlabel('Date / UT', fontsize=fontsize)
    ax.legend(fontsize=fontsize)
    ax.tick_params(axis='both', labelsize=fontsize)

    if newplot:
        fig.savefig(pngname, format='png', dpi=100, bbox_inches='tight')
    return ax
Exemplo n.º 10
0
def plot_temperatures(self, ax, label, ttl, fontsize=12):
    '''
    plot a collection of temperatures
    arguments:
         ax is the plot axis (possibly None)
         label is a dictionary of HK key with sensor label
         ttl is the main title of the plot
    '''
    val = {}
    for sensor in label.keys():
        val[sensor] = self.get_hk(sensor)

    t = self.get_hk(data='RaspberryDate', hk='EXTERN_HK')

    pngname = self.assign_imagename(ttl.replace(' ', '_'))

    if ax is None:
        newplot = True
        ttl += '\n' + self.infotext()
        plt.ion()
        fig = plt.figure()
        figure_window_title(fig,
                            '%s for dataset %s' % (ttl, self.dataset_name))
        fig.suptitle(ttl, fontsize=fontsize)
        ax = fig.add_axes((0.05, 0.1, 0.9, 0.8))
    else:
        newplot = False
        ax.text(0.5,
                1.0,
                ttl,
                va='bottom',
                ha='center',
                fontsize=fontsize,
                transform=ax.transAxes)

    if t is None:
        ax.text(0.5,
                0.5,
                'No Temperature Information',
                va='center',
                ha='center',
                fontsize=2 * fontsize,
                transform=ax.transAxes)
        ax.get_yaxis().set_visible(False)
        ax.get_xaxis().set_visible(False)
        if newplot:
            fig.savefig(pngname, format='png', dpi=100, bbox_inches='tight')
        return ax

    tdate = []
    # qubic-central was changed to UTC on 2020-02-27
    if t[0] > float(qc_utc_date.strftime('%s.%f')):
        for tstamp in t:
            tdate.append(dt.datetime.utcfromtimestamp(tstamp))
    else:
        for tstamp in t:
            tdate.append(dt.datetime.fromtimestamp(tstamp))

    for key in val.keys():
        if val[key] is not None:
            plt.plot(tdate,
                     val[key],
                     label=label[key],
                     marker='D',
                     markersize=0.2 * fontsize)
    ax.set_ylabel('Temperature / K', fontsize=fontsize)
    ax.set_xlabel('Date / UT', fontsize=fontsize)
    ax.legend(fontsize=fontsize)
    ax.tick_params(axis='both', labelsize=fontsize)
    if newplot:
        fig.savefig(pngname, format='png', dpi=100, bbox_inches='tight')
    return ax
Exemplo n.º 11
0
def plot_fits_layout(filename):
    '''
    plot the QUBIC focal plane detector layout as found in the CalQubic_DetArray_...fits file
    '''
    basename = os.path.basename(filename)
    ttl = 'FITS Layout for %s' % basename

    hdulist = fits.open(filename)

    hdu_centre = hdulist[1]
    hdu_vertices = hdulist[2]
    hdu_removed = hdulist[3]
    hdu_index = hdulist[4]
    hdu_quadrant = hdulist[5]

    xmax = np.nanmax(hdu_vertices.data[:, :, :, 0])
    xmin = np.nanmin(hdu_vertices.data[:, :, :, 0])
    xspan = xmax - xmin
    plt_xmin = xmin - 0.1 * xspan
    plt_xmax = xmax + 0.1 * xspan

    ymax = np.nanmax(hdu_vertices.data[:, :, :, 1])
    ymin = np.nanmin(hdu_vertices.data[:, :, :, 1])
    yspan = ymax - ymin
    plt_ymin = ymin - 0.1 * yspan
    plt_ymax = ymax + 0.1 * yspan

    fig = plt.figure(figsize=(20, 20))
    figure_window_title(fig, basename)
    ax = fig.add_axes([0, 0, 1, 1])
    ax.set_aspect('equal')
    ax.set_xlim([plt_xmin, plt_xmax])
    ax.set_ylim([plt_ymin, plt_ymax])
    ax.text(0.5,
            1.0,
            ttl,
            va='top',
            ha='center',
            fontsize=20,
            transform=ax.transAxes)

    fp_idx = -1
    for i in range(34):
        for j in range(34):
            #fp_idx += 1
            fp_idx = 34 * i + j
            quadrant_idx = hdu_quadrant.data[i, j]
            if quadrant_idx > 3: continue
            removed = hdu_removed.data[i, j]
            if removed == 1: continue

            quadrant = quadrant_idx + 1

            fpindex = hdu_index.data[i, j]

            x = hdu_centre.data[i, j, 0]
            y = hdu_centre.data[i, j, 1]

            xpts = np.append(hdu_vertices.data[i, j, :, 0],
                             hdu_vertices.data[i, j, 0, 0])
            ypts = np.append(hdu_vertices.data[i, j, :, 1],
                             hdu_vertices.data[i, j, 0, 1])
            plt.fill(xpts, ypts, color=quadrant_colour[quadrant_idx])

            lbl = 'Q%i\n%04i\n%04i' % (quadrant, fpindex, fp_idx)
            ax.text(x,
                    y,
                    lbl,
                    fontsize=6,
                    color='white',
                    ha='center',
                    va='center')
            #ax.plot(x,y,ls='none',marker='s',markersize=10,color='black',fillstyle='none')

    return hdulist
Exemplo n.º 12
0
def quicklook(self,
              TES=(54, 54),
              xwin=True,
              savedir=None,
              filename=None,
              figsize=(10.5, 14),
              dpi=100):
    '''
    make a page with diagnostic info
    arguments: 
      - TES       : a list of TES to show as examples (one from ASIC1 and one form ASIC2)
      - xwin      : plot to screen if True, otherwise, just make a file
      - savedir   : directory name for the image file
      - filename  : override the default filename
      - figsize   : override the default figure size.  Note that the intention is for quicklook to fit on A4 size
      - dpi       : override the default dots per inch for the saved image file
    '''
    if not self.exist_data(): return None

    ttl = 'Diagnostic for %s' % self.dataset_name

    #ttl += '\n'+self.infotext()
    if xwin:
        plt.ion()
    else:
        plt.close('all')
        plt.ioff()

    fig = plt.figure(figsize=figsize)
    scalesize = np.sqrt(np.sum(np.array(figsize)**2))

    if xwin:
        figure_window_title(fig,
                            '%s for dataset %s' % (ttl, self.dataset_name))
    fig.suptitle(ttl, fontsize=10)

    fontsize = 0.3 * scalesize
    width = 0.37
    height = 0.14
    vspacing = 0.18
    hspacing = 0.51

    hpos1 = 0.07
    hpos2 = hpos1 + hspacing

    vpos = 0.80
    # calsource
    ax = fig.add_axes((hpos1, vpos, width, height))
    self.plot_calsource(ax, fontsize=fontsize)

    # platform position
    ax = fig.add_axes((hpos2, vpos, width, height))
    self.plot_azel(ax, fontsize=fontsize)

    vpos -= vspacing
    # 300mK temperatures
    ax = fig.add_axes((hpos1, vpos, width, height))
    self.plot_300mKtemperatures(ax, fontsize=fontsize)

    # 1K temperatures
    ax = fig.add_axes((hpos2, vpos, width, height))
    self.plot_1Ktemperatures(ax, fontsize=fontsize)

    vpos -= vspacing
    # horn switches activated
    ax = fig.add_axes((hpos1, vpos, width, height))
    self.plot_switchstatus(ax, fontsize=fontsize)

    ax = fig.add_axes((hpos2, vpos, width, height))
    self.plot_hwp(ax, fontsize=fontsize)

    vpos -= vspacing
    # PPS diagnostic
    ax = fig.add_axes((hpos1, vpos, width, height))
    self.plot_pps_nsamples(hk='platform', ax=ax, fontsize=fontsize)

    ax = fig.add_axes((hpos2, vpos, width, height))
    self.plot_pps_nsamples(hk='sci', asic=1, ax=ax, fontsize=fontsize)

    vpos -= vspacing
    # example timeline from ASIC 1
    ax = fig.add_axes((hpos1, vpos, width, height))
    f = self.plot_timeline(asic=1, TES=TES[0], ax=ax, fontsize=fontsize)
    if f is None:
        ax.text(0.5,
                0.5,
                'No Science Data for ASIC 1',
                va='center',
                ha='center',
                fontsize=2 * fontsize,
                transform=ax.transAxes)
        ax.get_yaxis().set_visible(False)
        ax.get_xaxis().set_visible(False)

    # example timeline from ASIC 2
    ax = fig.add_axes((hpos2, vpos, width, height))
    f = self.plot_timeline(asic=2, TES=TES[1], ax=ax, fontsize=fontsize)
    if f is None:
        ax.text(0.5,
                0.5,
                'No Science Data for ASIC 2',
                va='center',
                ha='center',
                fontsize=2 * fontsize,
                transform=ax.transAxes)
        ax.get_yaxis().set_visible(False)
        ax.get_xaxis().set_visible(False)

    # elapsed time
    delta = self.endobs - self.obsdate
    days = delta.days
    seconds = delta.seconds
    hours = seconds // 3600
    remain_secs = seconds % 3600
    mins = remain_secs // 60
    secs = remain_secs % 60
    usecs = delta.microseconds
    elapsed_time_txt = 'elapsed time:  '
    if days > 0:
        elapsed_time_txt += '%i days, ' % days
    elapsed_time_txt += '%i hours, %i minutes, %i.%06i seconds' % (hours, mins,
                                                                   secs, usecs)

    vpos -= 0.3 * vspacing
    # bottom of page to show elapsed time
    ax = fig.add_axes((hpos1, vpos, width + hspacing, 0.2 * height))
    ax.text(0.5,
            0.5,
            elapsed_time_txt,
            va='center',
            ha='center',
            fontsize=2 * fontsize,
            transform=ax.transAxes)
    ax.get_yaxis().set_visible(False)
    ax.get_xaxis().set_visible(False)

    if filename is None:
        imagename = 'QUBIC_quicklook_%s.png' % self.dataset_name
    else:
        imagename = filename

    if savedir is not None and os.path.isdir(savedir):
        image_fullname = '%s/%s' % (savedir, imagename)
    else:
        image_fullname = imagename

    fig.savefig(image_fullname, dpi=dpi, bbox_inches='tight')

    if not xwin: plt.close(fig)

    return image_fullname
Exemplo n.º 13
0
def plot_hwp(self, ax=None, fontsize=12):
    '''
    plot Half Wave Plate position
    '''

    v = self.get_hk('HWP-Position')
    t = self.timeaxis('hwp')

    ttl = 'Half Wave Plate position'
    pngname = self.assign_imagename(ttl.replace(' ', '_'))

    if ax is None:
        newplot = True
        ttl += '\n' + self.infotext()
        plt.ion()
        fig = plt.figure()
        figure_window_title(fig,
                            '%s for dataset %s' % (ttl, self.dataset_name))
        fig.suptitle(ttl, fontsize=fontsize)
        ax = fig.add_axes((0.05, 0.1, 0.9, 0.75))
    else:
        newplot = False
        ax.text(0.5,
                1.0,
                ttl,
                va='bottom',
                ha='center',
                fontsize=fontsize,
                transform=ax.transAxes)

    if t is None:
        self.printmsg('No housekeeping information!', verbosity=2)
        ax.text(0.5,
                0.5,
                'No Half Wave Plate information',
                va='center',
                ha='center',
                fontsize=2 * fontsize,
                transform=ax.transAxes)
        ax.get_yaxis().set_visible(False)
        ax.get_xaxis().set_visible(False)
        if newplot:
            fig.savefig(pngname, format='png', dpi=100, bbox_inches='tight')
        return ax

    tdate = []
    for tstamp in t:
        tdate.append(dt.datetime.utcfromtimestamp(tstamp))

    if v is not None:
        ax.plot(tdate,
                v,
                marker='D',
                markersize=0.2 * fontsize,
                ls='none',
                label='HWP Position')
        ax.set_ylim(0, 8)
        ax.set_ylabel('Position number', fontsize=fontsize)
        ax.set_xlabel('Date / UT', fontsize=fontsize)
        ax.legend(fontsize=fontsize)
        ax.tick_params(axis='both', labelsize=fontsize)

    if v is None or min(v) == 255:
        ax.text(0.5,
                0.5,
                'No Half Wave Plate information',
                va='center',
                ha='center',
                fontsize=2 * fontsize,
                transform=ax.transAxes)
        ax.get_yaxis().set_visible(False)
        ax.get_xaxis().set_visible(False)

    if newplot:
        fig.savefig(pngname, format='png', dpi=100, bbox_inches='tight')
    return ax
Exemplo n.º 14
0
def plot_calsource(self, ax=None, fontsize=12):
    '''
    plot the calibration source
    '''

    ttl = 'Calibration Source'
    pngname = self.assign_imagename('calsource')
    info = self.calsource_info()

    if info is None:
        ttl += ' NO INFORMATION'
    elif info['calsource']['status'] != 'ON':
        ttl += ' %s' % info['calsource']['status']
    else:
        ttl += ' frequency=%.2fGHz' % info['calsource']['frequency']

    if ax is None:
        newplot = True
        ttl = '%s %s' % (self.infotext(), ttl)
        plt.ion()
        fig = plt.figure()
        figure_window_title(
            fig, 'Calibration Source for dataset %s' % self.dataset_name)
        fig.suptitle(ttl, fontsize=fontsize)
        ax = fig.add_axes((0.05, 0.1, 0.9, 0.78))
    else:
        newplot = False
        #ax.text(0.5,1.0,ttl,va='bottom',ha='center',fontsize=fontsize,transform=ax.transAxes)

    ax.set_ylabel('Calibration Source Power / arbitrary units',
                  fontsize=fontsize)
    ax.set_xlabel('Date / UT', fontsize=fontsize)
    ax.tick_params(axis='both', labelsize=fontsize)
    ax.text(0.01,
            1.0,
            self.calsource_infotext(),
            va='bottom',
            ha='left',
            fontsize=fontsize,
            transform=ax.transAxes)

    t, v = self.calsource()
    if t is None:
        ax.get_yaxis().set_visible(False)
        ax.get_xaxis().set_visible(False)
        ax.text(0.5,
                0.5,
                'No Calsource Data',
                va='center',
                ha='center',
                fontsize=2 * fontsize,
                transform=ax.transAxes)
    else:
        tdate = []
        for tstamp in t:
            tdate.append(dt.datetime.utcfromtimestamp(tstamp))
        ax.plot(tdate, v)

    if newplot:
        fig.savefig(pngname, format='png', dpi=100, bbox_inches='tight')
    return ax
Exemplo n.º 15
0
t0 = min([el_t0, t_t0])
t0_date = dt.datetime.fromtimestamp(t0)

# make plots
plt.ion()
for key in rec_names.keys():
    idx_good = np.where(t_pts[key] != -1)[0]
    pngname = '%s_vertical-offset_temperature_%s.png' % (
        key.upper(), t0_date.strftime('%Y%m%d'))
    ttl = 'Temperture during Synthetic Beam Mapping: %s' % t0_date.strftime(
        '%Y-%m-%d')
    t_label = '%s Temperature' % key.upper()

    fig = plt.figure(figsize=(16, 8))
    figure_window_title(fig, 'Temperature vs Inclination')
    plt.title(ttl)

    date_pts = (t_date[idx_good] - t0) / 60
    temp_pts = t_pts[key][idx_good]

    plt.plot(date_pts,
             temp_pts,
             ls='none',
             marker='*',
             color='green',
             label=t_label)

    t_ax = fig.axes[0]
    el_ax = t_ax.twinx()
Exemplo n.º 16
0
def plot_fp(args):
    '''
    plot curves and background colour on the QUBIC focal plane
    
    the argument is a dictionary with the curves and options
    valid keywords (n is the ASIC number):
      'ASIC<n>' : the array of NPIXELS curves
      'ASIC<n> x-axis' : x-axis (use this to plot bias curves)
      'ASIC<n> bg' : the value to determine the background colour
      'ASIC<n> good' : an array of bool for each TES (good or not)
      'obsdate' : observation date (datetime object)
      'title' : plot title
      'subtitle' : plot subtitle
      'lutmin' : min value for colour look up table
      'lutmax' : max value for colour look up table
      'pngname' : name of file for saving the plot
      'nolabels' : if true, do not plot TES labels in each box
      'quadrant' : quadrant in which to plot the quarter focal plane (default=3)

    '''

    # initialize stuff
    pix_grid = assign_pix_grid()
    nrows = pix_grid.shape[0]
    ncols = pix_grid.shape[1]

    if 'figsize' in args.keys():
        figsize = args['figsize']
    else:
        figwidth = plt.rcParams['figure.figsize'][0]
        figsize = (figwidth, figwidth)
    fontsize = figsize[0]
    ttlfontsize = figsize[0] * 1.2

    quadrant = 3
    if 'quadrant' in args.keys():
        quadrant = args['quadrant']

    obsdate = None
    if 'obsdate' in args.keys():
        obsdate = args['obsdate']
    tes_grid = assign_tes_grid()

    if 'pngname' in args.keys():
        pngname = args['pngname']
    elif obsdate:
        pngname = 'QUBIC_focal_plane_%s.png' % obsdate.strftime(
            '%Y%m%dT%H%M%S')
    else:
        pngname = 'QUBIC_focal_plane.png'

    if 'title' in args.keys():
        ttl = args['title']
    else:
        ttl = 'QUBIC TES array'

    subttl = None
    if 'subtitle' in args.keys():
        subttl = args['subtitle']

    lutmin = 0.0
    if 'lutmin' in args.keys():
        lutmin = args['lutmin']
    lutmax = 10.0
    if 'lutmax' in args.keys():
        lutmax = args['lutmax']

    face_colours = {}
    face_colours['ASIC0'] = 'black'
    face_colours['ASIC1'] = 'white'
    face_colours['ASIC2'] = 'white'

    curve_colours = {}
    curve_colours['ASIC0'] = 'black'
    curve_colours['ASIC1'] = 'black'
    curve_colours['ASIC2'] = 'blue'

    label_boxprops = dict(boxstyle='round, pad=0.1',
                          facecolor='white',
                          alpha=1.0)
    label_colours = {}
    label_colours['ASIC0'] = 'black'
    label_colours['ASIC1'] = 'black'
    label_colours['ASIC2'] = 'blue'
    if 'nolabels' in args.keys() and args['nolabels']:
        print_labels = False
    else:
        print_labels = True

    plt.ion()
    fig, ax = plt.subplots(nrows, ncols, figsize=figsize)
    fig.text(0.5, 0.985, ttl, ha='center', fontsize=ttlfontsize)
    figure_window_title(fig, ttl)
    fig.suptitle(subttl, fontsize=ttlfontsize)

    for j in range(nrows):
        for i in range(ncols):

            if quadrant == 1:
                row = j
                col = i

            elif quadrant == 2:
                row = i
                col = j

            elif quadrant == 3:
                row = 16 - j
                col = 16 - i
            else:
                row = 16 - i
                col = 16 - j

            ax[row, col].get_xaxis().set_visible(False)
            ax[row, col].get_yaxis().set_visible(False)

            # the pixel identity associated with its physical location in the array
            TES = tes_grid[j, i].TES
            TES_str = '%03i' % TES
            asic = tes_grid[j, i].ASIC
            asic_str = '%i' % asic

            TES_idx = TES - 1
            pix_label = TES_str
            asic_key = 'ASIC%s' % asic_str
            asicbg_key = '%s bg' % asic_key
            asicgood_key = '%s good' % asic_key
            xaxis_key = '%s x-axis' % asic_key

            face_colour = face_colours[asic_key]
            label_colour = label_colours[asic_key]
            curve_colour = curve_colours[asic_key]

            text_x = 0.5
            text_y = 0.9
            labelfontsize = ttlfontsize

            if asic_key in args.keys() and args[asic_key] is not None:
                if xaxis_key in args.keys() and args[xaxis_key] is not None:
                    curve_x = args[xaxis_key][TES_idx]
                else:
                    curve_x = range(args[asic_key].shape[1])
                curve = args[asic_key][TES_idx]
                text_x = 0.5
                text_y = 0.9
                labelfontsize = 0.8 * fontsize
                if asicgood_key in args.keys(
                ) and not args[asicgood_key][TES_idx]:
                    face_colour = 'black'
                    label_colour = 'white'
                    curve_colour = 'white'
                elif asicbg_key in args.keys():
                    if args[asicbg_key][TES_idx] is None:
                        face_colour = 'white'
                    else:
                        face_colour = mylut(args[asicbg_key][TES_idx], lutmin,
                                            lutmax)

                ax[row, col].plot(curve_x, curve, color=curve_colour)

            #print('(%i,%i) : facecolour=%s, labelcolour=%s' % (row,col,face_colour,label_colour))
            ax[row, col].set_facecolor(face_colour)
            label_boxprops['facecolor'] = face_colour
            if print_labels:
                ax[row, col].text(text_x,
                                  text_y,
                                  pix_label,
                                  va='top',
                                  ha='center',
                                  color=label_colour,
                                  fontsize=labelfontsize,
                                  bbox=label_boxprops,
                                  transform=ax[row, col].transAxes)

    plt.savefig(pngname, format='png', dpi=100, bbox_inches='tight')
    plt.show()

    return
Exemplo n.º 17
0
def plot_timeline(self,
                  TES,
                  timeline_index=None,
                  fit=False,
                  ipeak0=None,
                  ipeak1=None,
                  plot_bias=True,
                  xwin=True,
                  timeaxis='pps',
                  ax=None,
                  fontsize=12):
    '''
    plot the timeline
    '''
    if not self.exist_timeline_data():
        self.printmsg('ERROR! No timeline data.')
        return None

    if timeline_index is None:
        # by default, plot the first one.  For QubicStudio files, there is only one timeline
        timeline_index = 0

    ntimelines = self.ntimelines()
    if timeline_index >= ntimelines:
        self.printmsg('Please enter a timeline between 0 and %i' %
                      (ntimelines - 1))
        return None

    tdata = self.tdata[timeline_index]
    keys = tdata.keys()

    warning_str = ''
    if 'WARNING' in keys and tdata['WARNING']:
        warning_str = '\n'.join(tdata['WARNING'])

    if 'R_FEEDBK' in keys:
        self.Rfeedback = tdata['R_FEEDBK']

    if 'NSAMPLES' in keys:
        self.nsamples = tdata['NSAMPLES']

    if 'DATE-OBS' in keys:
        timeline_date = tdata['DATE-OBS']
    else:
        timeline_date = self.obsdate

    if 'BEG-OBS' in keys:
        timeline_start = tdata['BEG-OBS']
    else:
        timeline_start = timeline_date

    if 'BIAS_MIN' in keys:
        self.min_bias = tdata['BIAS_MIN']
    if 'BIAS_MAX' in keys:
        self.max_bias = tdata['BIAS_MAX']

    biasphase = self.bias_phase()

    ttl = str('QUBIC Timeline curve for TES#%3i (%s)' %
              (TES, timeline_start.strftime('%Y-%b-%d %H:%M UTC')))

    if 'TES_TEMP' in keys:
        tempstr = '%.0f mK' % (1000 * tdata['TES_TEMP'])
    else:
        if self.temperature is None:
            tempstr = 'unknown'
        else:
            tempstr = str('%.0f mK' % (1000 * self.temperature))

    fbstr = ''
    if 'R_FEEDBK' in keys:
        if tdata['R_HEATER'] == 1:
            onoff = 'ON'
        else:
            onoff = 'OFF'
        fbstr = ', Feedback Relay: %.0fk$\Omega$, Heater %s' % (
            tdata['R_FEEDBK'] * 1e-3, onoff)

    subttl = str('Array %s, ASIC #%i, Pixel #%i, Temperature %s%s' %
                 (self.detector_name, self.asic, tes2pix(
                     TES, self.asic), tempstr, fbstr))

    if xwin: plt.ion()
    else: plt.ioff()

    if ax is None:
        newplot = True
        fig = plt.figure(figsize=self.figsize)
        figure_window_title(fig, ttl)
        ax = plt.gca()
    else:
        newplot = False

    ax.set_xlabel('time  /  seconds', fontsize=fontsize)
    ax.set_ylabel('Current  /  $\mu$A', fontsize=fontsize)
    ax.tick_params(axis='both', labelsize=fontsize)
    if warning_str:
        boxprops = {}
        boxprops['alpha'] = 0.4
        boxprops['color'] = 'red'
        boxprops['boxstyle'] = 'round'
        ax.text(0.5,
                0.5,
                warning_str,
                ha='center',
                va='center',
                fontsize=2 * fontsize,
                transform=ax.transAxes,
                bbox=boxprops)

    TES_idx = TES_index(TES)
    timeline = self.timeline(TES, timeline_index)
    current = self.ADU2I(timeline)  # uAmps
    timeline_npts = len(timeline)

    self.printmsg(
        'DEBUG: calling timeline_timeaxis from plot_timeline() with axistype=%s'
        % timeaxis,
        verbosity=4)
    time_axis = self.timeline_timeaxis(timeline_index, axistype=timeaxis)

    fitparms = None
    if fit:
        fitparms = self.fit_timeline(TES, timeline_index, ipeak0, ipeak1)

    ipeak0 = 0
    ipeak1 = timeline_npts - 1
    peak0 = time_axis[ipeak0]
    peak1 = time_axis[ipeak1]
    if plot_bias:
        if self.timeline_conversion is None:
            self.timeline2adu(TES=TES,
                              timeline_index=timeline_index,
                              timeaxis=timeaxis)

        if self.timeline_conversion is None or self.min_bias is None or self.max_bias is None:
            plot_bias = False
        else:
            ipeak0 = self.timeline_conversion['ipeak0']
            ipeak1 = self.timeline_conversion['ipeak1']
            peak0 = self.timeline_conversion['peak0']
            peak1 = self.timeline_conversion['peak1']
            shift = self.timeline_conversion['shift']

    if plot_bias:
        ysine = None
        if biasphase is not None:
            self.printmsg('DEBUG: taking ysine from QubicStudio FITS file',
                          verbosity=4)
            ysine = self.timeline_vbias
            sinelabel = 'V$_\mathrm{bias}$ from QubicStudio FITS file'
        elif fitparms is None:
            self.printmsg('DEBUG: taking ysine from peak to peak', verbosity=4)
            bias_period = peak1 - peak0
            amplitude = 0.5 * (self.max_bias - self.min_bias)
            offset = self.min_bias + amplitude
            sinelabel = 'sine curve period=%.2f seconds\npeaks determined from TES %i' % (
                bias_period, self.timeline_conversion['TES'])
            ysine = offset + amplitude * np.sin(
                (time_axis - peak0) * 2 * np.pi / bias_period + 0.5 * np.pi +
                shift * 2 * np.pi)
        else:
            self.printmsg(
                'DEBUG: taking ysine from timeline fit to sine curve',
                verbosity=4)
            bias_period = fitparms['period']
            amplitude = fitparms['amplitude']
            offset = fitparms['offset']
            shift = fitparms['phaseshift']
            if bias_period is not None and amplitude is not None:
                sinelabel = 'best fit sine curve: period=%.2f seconds, amplitude=%.2f $\mu$A' % (
                    bias_period, amplitude)
                ysine = self.model_timeline(time_axis, bias_period, shift,
                                            offset, amplitude)
    if ysine is None: plot_bias = False

    if newplot:
        fig.suptitle(ttl + '\n' + subttl, fontsize=fontsize)
    else:
        ax.text(0.5,
                1.0,
                ttl + '\n' + subttl,
                va='bottom',
                ha='center',
                fontsize=fontsize,
                transform=ax.transAxes)

    curve1 = ax.plot(time_axis, current, label='I-V timeline', color='blue')

    #ymax=max([current[ipeak0],current[ipeak1]])
    ymax = np.nanmax(current)
    if np.isnan(ymax):
        ymax = 1.0
    ymin = np.nanmin(current)
    if np.isnan(ymin):
        ymin = 1.0
    yrange = ymax - ymin
    if np.isnan(yrange) or yrange == 0:
        yrange = 0.1
    yminmax = (ymin - 0.02 * yrange, ymax + 0.02 * yrange)
    ax.plot([peak0, peak0], yminmax, color='red')
    ax.plot([peak1, peak1], yminmax, color='red')
    ax.set_ylim(yminmax)

    if plot_bias:
        if fitparms is None:
            ax_bias = ax.twinx()
            ax_bias.set_ylabel('Bias / V',
                               rotation=270,
                               va='bottom',
                               fontsize=fontsize)
            if self.min_bias == self.max_bias:
                ax_bias.set_ylim([self.min_bias - 1, self.max_bias + 1])
            else:
                ax_bias.set_ylim([self.min_bias, self.max_bias])
            ax_bias.tick_params(axis='both', labelsize=fontsize)
            curve2_ax = ax_bias
        else:
            curve2_ax = ax
        self.printmsg(
            'DEBUG: plotting sine curve for bias: len(time_axis)=%i, len(ysine)=%i'
            % (len(time_axis), len(ysine)),
            verbosity=4)
        curve2 = curve2_ax.plot(time_axis,
                                ysine,
                                label=sinelabel,
                                color='green')
        curves = curve1 + curve2
    else:
        curves = curve1

    labs = [l.get_label() for l in curves]
    ax.legend(curves, labs, loc=0, fontsize=fontsize)

    pngname = str('TES%03i_array-%s_ASIC%i_timeline_%s.png' %
                  (TES, self.detector_name, self.asic,
                   timeline_start.strftime('%Y%m%dT%H%M%SUTC')))
    pngname_fullpath = self.output_filename(pngname)
    if newplot and isinstance(pngname_fullpath, str):
        plt.savefig(pngname_fullpath,
                    format='png',
                    dpi=100,
                    bbox_inches='tight')
    if xwin: plt.show()
    else: plt.close('all')

    if fitparms: return fitparms
    return True
Exemplo n.º 18
0
def plot_switchstatus(self, ax=None, fontsize=12):
    '''
    plot which horn switches are closed
    '''
    v1 = self.get_hk('switch1')
    v2 = self.get_hk('switch2')
    t = self.timeaxis('INTERN_HK')

    ttl = 'Closed Horn Switches'
    pngname = self.assign_imagename(ttl.replace(' ', '_'))

    if ax is None:
        newplot = True
        ttl += '\n' + self.infotext()
        plt.ion()
        fig = plt.figure()
        figure_window_title(fig,
                            '%s for dataset %s' % (ttl, self.dataset_name))
        fig.suptitle(ttl, fontsize=fontsize)
        ax = fig.add_axes((0.05, 0.1, 0.9, 0.8))
    else:
        newplot = False
        ax.text(0.5,
                1.0,
                ttl,
                va='bottom',
                ha='center',
                fontsize=fontsize,
                transform=ax.transAxes)

    if t is None or (v1 is None and v2 is None):
        ax.text(0.5,
                0.5,
                'No Horn Switch Information',
                va='center',
                ha='center',
                fontsize=2 * fontsize,
                transform=ax.transAxes)
        ax.get_yaxis().set_visible(False)
        ax.get_xaxis().set_visible(False)
    else:
        tdate = []
        for tstamp in t:
            tdate.append(dt.datetime.utcfromtimestamp(tstamp))
        if v1 is not None:
            ax.plot(tdate,
                    v1,
                    marker='D',
                    markersize=0.2 * fontsize,
                    ls='none',
                    label='Switch 1 Closed')
        if v2 is not None:
            ax.plot(tdate,
                    v2,
                    marker='D',
                    markersize=0.2 * fontsize,
                    ls='none',
                    label='Switch 2 Closed')

        if max(v1) == 0 and max(v2) == 0:
            ax.text(0.5,
                    0.5,
                    'All horns open',
                    va='center',
                    ha='center',
                    fontsize=2 * fontsize,
                    transform=ax.transAxes)

        ax.set_ylabel('Horn number', fontsize=fontsize)
        ax.set_xlabel('Date / UT', fontsize=fontsize)
        ax.tick_params(axis='both', labelsize=fontsize)
        ax.set_ylim((-1, 65))
        ax.legend(fontsize=fontsize, loc='upper right')

    if newplot:
        fig.savefig(pngname, format='png', dpi=100, bbox_inches='tight')
    return ax