Esempio n. 1
0
def tes2pix(TES, asic):
    global TES2PIX
    if TES2PIX is None: TES2PIX = assign_pix2tes()
    TES_idx = TES_index(TES)
    if TES_idx is None: return None
    if TES_idx == -1: return -1
    PIX = TES2PIX[ASIC_index(asic), TES_idx]
    return PIX
Esempio n. 2
0
def timeline(self,TES,timeline_index=0):
    '''
    return the timeline for a given TES and timeline index
    '''
    if not self.exist_timeline_data():return None
    ntimelines=self.ntimelines()
    if timeline_index>=ntimelines:
        self.printmsg('ERROR! timeline index out of range.  Enter an index between 0 and %i' % (ntimelines-1))
        return None
    TES_idx=TES_index(TES)
    if TES_idx is None:return None
    timeline=self.tdata[timeline_index]['TIMELINE'][TES_idx,:]
    return timeline
Esempio n. 3
0
def fit_timeline(self,TES,timeline_index=None,ipeak0=None,ipeak1=None):
    '''
    fit the timeline to a sine curve
    '''
    # return a dictionary
    fit={}
    fit['TES']=TES
    fit['DET_NAME']=self.detector_name
    fit['ASIC']=self.asic
    
    if timeline_index is None:timeline_index=0    
    ntimelines=self.ntimelines()
    if timeline_index>=ntimelines:
        self.printmsg('Please enter a timeline between 0 and %i' % (ntimelines-1))
        return None
    fit['timeline_index']=timeline_index
    fit['date']=self.tdata[timeline_index]['DATE-OBS']
    fit['Tbath']=self.tdata[timeline_index]['TES_TEMP']
    
    TES_idx=TES_index(TES)
    timeline=self.timeline(TES,timeline_index)
    current=self.ADU2I(timeline)
    timeline_npts=len(timeline)

    self.printmsg('DEBUG: calling timeline_timeaxis from fit_timeline()',verbosity=4)
    time_axis=self.timeline_timeaxis(timeline_index)

    # first guess;  use the peak search algorithm
    biasmod = self.determine_bias_modulation(TES,timeline_index)
    if biasmod is None:
        self.printmsg('ERROR! Could not determine bias modulation.',verbosity=2)
        return None
    peak0 = biasmod['peak0']
    peak1 = biasmod['peak1']
    period = peak1-peak0
    amplitude = 0.5*(max(current)-min(current))
    offset = min(current)+amplitude
    phaseshift = peak0/period
    
    p0=[period,phaseshift,offset,amplitude]

    popt,pcov=curve_fit(self.model_timeline,time_axis,current,p0=p0)
    period,phaseshift,offset,amplitude=popt
    fit['period']=period
    fit['phaseshift']=phaseshift
    fit['offset']=offset
    fit['amplitude']=amplitude # this is in microAmps

    Vtes=self.Rshunt*( (self.max_bias*self.bias_factor)/self.Rbias - 1e-6*abs(amplitude) )    
    fit['R amplitude']=abs(Vtes/amplitude)
    return fit
Esempio n. 4
0
def get_ASD(self, TES=1, tinteg=None, ntimelines=10, nbins=1):
    '''
    get timeline data and plot the Amplitude Spectral Density
    timeline data is saved in FITS file, unless in monitor mode.
    in monitor mode, the plots will refresh indefinitely.  exit with Ctrl-C
    '''
    client = self.connect_QubicStudio()
    if client is None: return None

    TES_idx = TES_index(TES)
    monitor_mode = False
    if not isinstance(ntimelines, int) or ntimelines <= 0:
        monitor_mode = True
    save = not monitor_mode

    self.assign_integration_time(tinteg)
    self.assign_obsdate()

    # for noise measurements, we set the feedback resistance to 100kOhm
    self.set_Rfeedback(100)

    idx = 0
    ax_timeline = None
    ax_asd = None
    while monitor_mode or idx < ntimelines:
        self.debugmsg('ASD monitoring loop count: %i' % idx)

        # read the bath temperature at each loop
        Tbath = self.oxford_read_bath_temperature()

        timeline = self.integrate_scientific_data(
            save=True)  # have to save in memory for plotting afterwards
        self.debugmsg('ASD monitoring: ntimelines=%i' % self.ntimelines())
        timeline_index = self.ntimelines() - 1
        result = self.plot_ASD(TES,
                               timeline_index,
                               ax_timeline=ax_timeline,
                               ax_asd=ax_asd,
                               save=save,
                               nbins=nbins)
        ax_asd = result['ax_asd']
        ax_timeline = result['ax_timeline']

        # if only monitoring, get rid of the one just plotted
        if monitor_mode: del (self.tdata[-1])
        idx += 1

    if not monitor_mode: self.write_fits()

    return
Esempio n. 5
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
Esempio n. 6
0
def determine_bias_modulation(self, TES, timeline_index=None, timeaxis='pps'):
    '''
    determine the modulation of the bias voltage
    It should be close to the "bias_frequency" which is actually the period.
    '''
    if not self.exist_timeline_data(): return None
    if not isinstance(timeline_index, int): timeline_index = 0
    ntimelines = self.ntimelines()
    if timeline_index >= ntimelines:
        self.printmsg('Please enter a timeline between 0 and %i' %
                      (ntimelines - 1))
        return None

    retval = {}
    retval['TES'] = TES
    retval['timeline_index'] = timeline_index
    retval['timeaxis'] = timeaxis

    TES_idx = TES_index(TES)
    timeline = self.timeline(TES, timeline_index)
    timeline_npts = len(timeline)

    sample_period = self.sample_period(timeline_index)
    self.printmsg(
        'DEBUG: calling timeline_timeaxis from determine_bias_modulation() with axistype=%s'
        % timeaxis,
        verbosity=4)
    time_axis = self.timeline_timeaxis(timeline_index, axistype=timeaxis)
    measured_sample_period = (time_axis[-1] - time_axis[0]) / (timeline_npts -
                                                               1)
    retval['measured_sample_period'] = measured_sample_period

    # use the bias_phase if it exists
    bias_phase = self.bias_phase()
    if bias_phase is not None:
        self.printmsg('getting bias variation from the saved data',
                      verbosity=2)
        imin = np.argmin(bias_phase)
        imax = np.argmax(bias_phase)
        iperiod = 2 * abs(imax - imin)
        if imin == imax:
            imin = 0
            imax = timeline_npts - 1
            iperiod = imax - imin
        ipeak0 = min([imin, imax])
        ipeak1 = ipeak0 + iperiod
        peak0 = time_axis[ipeak0]
        if ipeak1 >= timeline_npts:
            peak1 = peak0 + iperiod * measured_sample_period
        else:
            peak1 = time_axis[ipeak1]
        self.bias_period = peak1 - peak0
        retval['ipeak0'] = ipeak0
        retval['ipeak1'] = ipeak1
        retval['peak0'] = peak0
        retval['peak1'] = peak1
        return retval

    # the so-called frequency of the bias modulation is, in fact, the period
    # In QubicStudio the selection of bias_frequency=99 changes the significance from frequency to period (confusing)
    if self.bias_frequency is None:
        period_firstguess = 92.  # based on experience
    else:
        period_firstguess = self.bias_frequency

    bias_period_npts = int(period_firstguess / sample_period)
    self.debugmsg('period npts = %i' % bias_period_npts)

    # skip the first few seconds which are often noisy
    skip = int(3.0 / sample_period)
    self.debugmsg(
        'looking for peaks in I-V timeline.  Skipping the first %i points.' %
        skip)
    peak0_range = (skip, skip + bias_period_npts)
    peak1_range_end = skip + 2 * bias_period_npts
    if peak1_range_end >= timeline_npts:
        peak1_range_end = timeline_npts - 1
    peak1_range = (skip + bias_period_npts, peak1_range_end)

    # try to find the peaks, otherwise return ipeak0=0, ipeak1=timeline_npts-1
    try:
        ipeak0 = np.argmax(timeline[peak0_range[0]:peak0_range[1]])
        ipeak0 += peak0_range[0]
    except:
        ipeak0 = 0
    peak0 = time_axis[ipeak0]

    try:
        ipeak1 = np.argmax(timeline[peak1_range[0]:peak1_range[1]])
        ipeak1 += peak1_range[0]
    except:
        ipeak1 = timeline_npts - 1
    peak1 = time_axis[ipeak1]
    self.bias_period = peak1 - peak0

    retval['ipeak0'] = ipeak0
    retval['ipeak1'] = ipeak1
    retval['peak0'] = peak0
    retval['peak1'] = peak1
    return retval
Esempio n. 7
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
Esempio n. 8
0
def get_iv_data(self, replay=False, TES=None, monitor=False):
    '''
    get IV data and make a running plot
    optionally, replay saved data.

    you can monitor the progress of a given TES by the keyword TES=<number>

    setting monitor=True will monitor *all* the TES, but this slows everything down
    enormously!  Not recommended!!

    '''
    client = self.connect_QubicStudio()
    if client is None: return None

    monitor_iv = False
    if isinstance(TES, int):
        monitor_TES_index = TES_index(TES)
        monitor_iv = True

    if replay:
        if not isinstance(self.adu, np.ndarray):
            print('Please read an I-V data file, or run a new measurement!')
            return None
        if not isinstance(self.vbias, np.ndarray):
            print('There appears to be I-V data, but no Vbias info.')
            print(
                'Please run make_Vbias() with the correct max and min values')
            return None
        adu = self.adu
    else:
        client = self.connect_QubicStudio()
        if client is None: return None
        self.assign_obsdate(dt.datetime.utcnow())
        if not isinstance(self.vbias, np.ndarray):
            vbias = make_Vbias()
        nbias = len(self.vbias)
        adu = np.empty((self.NPIXELS, nbias))
        self.oxford_read_bath_temperature()

    vbias = self.vbias
    nbias = len(self.vbias)

    # figavg=self.setup_plot_Vavg()
    if monitor_iv: figiv, axiv = self.setup_plot_iv(TES)
    if monitor:
        nrows = 16
        ncols = 8
        figmulti, axmulti = self.setup_plot_iv_multi()

    for j in range(nbias):
        self.debugmsg("Vbias=%gV " % vbias[j])
        if not replay:
            self.set_VoffsetTES(vbias[j], 0.0)
            self.wait_a_bit()
            Vavg = self.get_mean()
            adu[:, j] = Vavg
            self.oxford_read_bath_temperature()
        else:
            Vavg = adu[:, j]

        # print ("a sample of V averages :  %g %g %g " %(Vavg[0], Vavg[43], Vavg[73]) )
        # plt.figure(figavg.number)
        # self.plot_Vavg(Vavg,vbias[j])
        if monitor_iv:
            plt.figure(figiv.number)
            I_tes = adu[monitor_TES_index, 0:j + 1]
            Iadjusted = self.ADU2I(I_tes)
            self.draw_iv(Iadjusted, axis=axiv)

        if monitor:
            # monitor all the I-V curves:  Warning!  Extremely slow!!!
            TES_idx = 0
            for row in range(nrows):
                for col in range(ncols):
                    axmulti[row, col].get_xaxis().set_visible(False)
                    axmulti[row, col].get_yaxis().set_visible(False)

                    Iadjusted = self.ADU2I(self.adu[TES_idx, 0:j + 1])
                    self.draw_iv(Iadjusted,
                                 colour='blue',
                                 axis=axmulti[row, col])
                    text_y = min(Iadjusted)
                    axmulti[row, col].text(max(self.vbias),
                                           text_y,
                                           str('%i' % (TES_idx + 1)),
                                           va='bottom',
                                           ha='right',
                                           color='black')

                    TES_idx += 1

    # plt.show()
    self.endobs = dt.datetime.utcnow()
    self.assign_ADU(adu)
    if not replay:
        self.write_fits()

    return adu