Instruction:
Can you generate the documentation for the following Python 3 function
def select_unrectified_slitlet(image2d, islitlet, csu_bar_slit_center,
                               params, parmodel, maskonly):
    """Returns image with the indicated slitlet (zero anywhere else).

    Parameters
    ----------
    image2d : numpy array
        Initial image from which the slitlet data will be extracted.
    islitlet : int
        Slitlet number.
    csu_bar_slit_center : float
        CSU bar slit center.
    params : :class:`~lmfit.parameter.Parameters`
        Parameters to be employed in the prediction of the distorted
        boundaries.
    parmodel : str
        Model to be assumed. Allowed values are 'longslit' and
        'multislit'.
    maskonly : bool
        If True, returns simply a mask (1 in the slitlet region and
        zero anywhere else.

    Returns
    -------
    image2d_output : numpy array
        2D image with the pixel information corresponding to the
        selected slitlet and zero everywhere else.

    """

    # protection
    if image2d.shape != (EMIR_NAXIS2, EMIR_NAXIS1):
        raise ValueError("NAXIS1, NAXIS2 unexpected for EMIR detector")

    # initialize image output
    image2d_output = np.zeros_like(image2d)

    # expected slitlet frontiers
    list_expected_frontiers = expected_distorted_frontiers(
        islitlet, csu_bar_slit_center,
        params, parmodel, numpts=101, deg=5, debugplot=0
    )
    pol_lower_expected = list_expected_frontiers[0].poly_funct
    pol_upper_expected = list_expected_frontiers[1].poly_funct

    # main loop: compute for each channel the minimum and maximum scan
    for j in range(EMIR_NAXIS1):
        xchannel = j + 1
        y0_lower = pol_lower_expected(xchannel)
        y0_upper = pol_upper_expected(xchannel)
        n1, n2 = nscan_minmax_frontiers(y0_frontier_lower=y0_lower,
                                        y0_frontier_upper=y0_upper,
                                        resize=True)
        # note that n1 and n2 are scans (ranging from 1 to NAXIS2)
        if maskonly:
            image2d_output[(n1 - 1):n2, j] = np.repeat(
                [1.0], (n2 - n1 + 1)
            )
        else:
            image2d_output[(n1 - 1):n2, j] = image2d[(n1 - 1):n2, j]

    return image2d_output

Response: Select unrectified slitlet from the image2d.


Instruction:
Can you implement a function in Python 3 that
evaluates rect.+wavecal. coefficients from arc image.

Response:
def rectwv_coeff_from_arc_image(reduced_image,
                                bound_param,
                                lines_catalog,
                                args_nbrightlines=None,
                                args_ymargin_bb=2,
                                args_remove_sp_background=True,
                                args_times_sigma_threshold=10,
                                args_order_fmap=2,
                                args_sigma_gaussian_filtering=2,
                                args_margin_npix=50,
                                args_poldeg_initial=3,
                                args_poldeg_refined=5,
                                args_interactive=False,
                                args_threshold_wv=0,
                                args_ylogscale=False,
                                args_pdf=None,
                                args_geometry=(0,0,640,480),
                                debugplot=0):
    """Evaluate rect.+wavecal. coefficients from arc image

    Parameters
    ----------
    reduced_image : HDUList object
        Image with preliminary basic reduction: bpm, bias, dark and
        flatfield.
    bound_param : RefinedBoundaryModelParam instance
        Refined boundary model.
    lines_catalog : Numpy array
        2D numpy array with the contents of the master file with the
        expected arc line wavelengths.
    args_nbrightlines : int
        TBD
    args_ymargin_bb : int
        TBD
    args_remove_sp_background : bool
        TBD
    args_times_sigma_threshold : float
        TBD
    args_order_fmap : int
        TBD
    args_sigma_gaussian_filtering : float
        TBD
    args_margin_npix : int
        TBD
    args_poldeg_initial : int
        TBD
    args_poldeg_refined : int
        TBD
    args_interactive : bool
        TBD
    args_threshold_wv : float
        TBD
    args_ylogscale : bool
        TBD
    args_pdf : TBD
    args_geometry : TBD
    debugplot : int
            Debugging level for messages and plots. For details see
            'numina.array.display.pause_debugplot.py'.

    Returns
    -------
    rectwv_coeff : RectWaveCoeff instance
        Rectification and wavelength calibration coefficients for the
        particular CSU configuration of the input arc image.
    reduced_55sp : HDUList object
        Image with 55 spectra corresponding to the median spectrum for
        each slitlet, employed to derived the wavelength calibration
        polynomial.

    """

    logger = logging.getLogger(__name__)

    # protections
    if args_interactive and args_pdf is not None:
        logger.error('--interactive and --pdf are incompatible options')
        raise ValueError('--interactive and --pdf are incompatible options')

    # header and data array
    header = reduced_image[0].header
    image2d = reduced_image[0].data

    # check grism and filter
    filter_name = header['filter']
    logger.info('Filter: ' + filter_name)
    if filter_name != bound_param.tags['filter']:
        raise ValueError('Filter name does not match!')
    grism_name = header['grism']
    logger.info('Grism: ' + grism_name)
    if grism_name != bound_param.tags['grism']:
        raise ValueError('Grism name does not match!')

    # read the CSU configuration from the image header
    csu_conf = CsuConfiguration.define_from_header(header)
    logger.debug(csu_conf)

    # read the DTU configuration from the image header
    dtu_conf = DtuConfiguration.define_from_header(header)
    logger.debug(dtu_conf)

    # set boundary parameters
    parmodel = bound_param.meta_info['parmodel']
    params = bound_params_from_dict(bound_param.__getstate__())
    if abs(debugplot) >= 10:
        print('-' * 83)
        print('* FITTED BOUND PARAMETERS')
        params.pretty_print()
        pause_debugplot(debugplot)

    # determine parameters according to grism+filter combination
    wv_parameters = set_wv_parameters(filter_name, grism_name)
    islitlet_min = wv_parameters['islitlet_min']
    islitlet_max = wv_parameters['islitlet_max']
    if args_nbrightlines is None:
        nbrightlines = wv_parameters['nbrightlines']
    else:
        nbrightlines = [int(idum) for idum in args_nbrightlines.split(',')]
    poly_crval1_linear = wv_parameters['poly_crval1_linear']
    poly_cdelt1_linear = wv_parameters['poly_cdelt1_linear']
    wvmin_expected = wv_parameters['wvmin_expected']
    wvmax_expected = wv_parameters['wvmax_expected']
    wvmin_useful = wv_parameters['wvmin_useful']
    wvmax_useful = wv_parameters['wvmax_useful']

    # list of slitlets to be computed
    logger.info('list_slitlets: [' + str(islitlet_min) + ',... ' +
                str(islitlet_max) + ']')

    # read master arc line wavelengths (only brightest lines)
    wv_master = read_wv_master_from_array(
        master_table=lines_catalog, lines='brightest', debugplot=debugplot
    )

    # read master arc line wavelengths (whole data set)
    wv_master_all = read_wv_master_from_array(
        master_table=lines_catalog, lines='all', debugplot=debugplot
    )

    # check that the arc lines in the master file are properly sorted
    # in ascending order
    for i in range(len(wv_master_all) - 1):
        if wv_master_all[i] >= wv_master_all[i + 1]:
            logger.error('>>> wavelengths: ' +
                         str(wv_master_all[i]) + '  ' +
                         str(wv_master_all[i+1]))
            raise ValueError('Arc lines are not sorted in master file')

    # ---

    image2d_55sp = np.zeros((EMIR_NBARS, EMIR_NAXIS1))

    # compute rectification transformation and wavelength calibration
    # polynomials

    measured_slitlets = []

    cout = '0'
    for islitlet in range(1, EMIR_NBARS + 1):

        if islitlet_min <= islitlet <= islitlet_max:

            # define Slitlet2dArc object
            slt = Slitlet2dArc(
                islitlet=islitlet,
                csu_conf=csu_conf,
                ymargin_bb=args_ymargin_bb,
                params=params,
                parmodel=parmodel,
                debugplot=debugplot
            )

            # extract 2D image corresponding to the selected slitlet, clipping
            # the image beyond the unrectified slitlet (in order to isolate
            # the arc lines of the current slitlet; otherwise there are
            # problems with arc lines from neighbour slitlets)
            image2d_tmp = select_unrectified_slitlet(
                image2d=image2d,
                islitlet=islitlet,
                csu_bar_slit_center=csu_conf.csu_bar_slit_center(islitlet),
                params=params,
                parmodel=parmodel,
                maskonly=False
            )
            slitlet2d = slt.extract_slitlet2d(image2d_tmp)

            # subtract smooth background computed as follows:
            # - median collapsed spectrum of the whole slitlet2d
            # - independent median filtering of the previous spectrum in the
            #   two halves in the spectral direction
            if args_remove_sp_background:
                spmedian = np.median(slitlet2d, axis=0)
                naxis1_tmp = spmedian.shape[0]
                jmidpoint = naxis1_tmp // 2
                sp1 = medfilt(spmedian[:jmidpoint], [201])
                sp2 = medfilt(spmedian[jmidpoint:], [201])
                spbackground = np.concatenate((sp1, sp2))
                slitlet2d -= spbackground

            # locate unknown arc lines
            slt.locate_unknown_arc_lines(
                slitlet2d=slitlet2d,
                times_sigma_threshold=args_times_sigma_threshold)

            # continue working with current slitlet only if arc lines have
            # been detected
            if slt.list_arc_lines is not None:

                # compute intersections between spectrum trails and arc lines
                slt.xy_spectrail_arc_intersections(slitlet2d=slitlet2d)

                # compute rectification transformation
                slt.estimate_tt_to_rectify(order=args_order_fmap,
                                           slitlet2d=slitlet2d)

                # rectify image
                slitlet2d_rect = slt.rectify(slitlet2d,
                                             resampling=2,
                                             transformation=1)

                # median spectrum and line peaks from rectified image
                sp_median, fxpeaks = slt.median_spectrum_from_rectified_image(
                    slitlet2d_rect,
                    sigma_gaussian_filtering=args_sigma_gaussian_filtering,
                    nwinwidth_initial=5,
                    nwinwidth_refined=5,
                    times_sigma_threshold=5,
                    npix_avoid_border=6,
                    nbrightlines=nbrightlines
                )

                image2d_55sp[islitlet - 1, :] = sp_median

                # determine expected wavelength limits prior to the wavelength
                # calibration
                csu_bar_slit_center = csu_conf.csu_bar_slit_center(islitlet)
                crval1_linear = poly_crval1_linear(csu_bar_slit_center)
                cdelt1_linear = poly_cdelt1_linear(csu_bar_slit_center)
                expected_wvmin = crval1_linear - \
                                 args_margin_npix * cdelt1_linear
                naxis1_linear = sp_median.shape[0]
                crvaln_linear = crval1_linear + \
                                (naxis1_linear - 1) * cdelt1_linear
                expected_wvmax = crvaln_linear + \
                                 args_margin_npix * cdelt1_linear
                # override previous estimates when necessary
                if wvmin_expected is not None:
                    expected_wvmin = wvmin_expected
                if wvmax_expected is not None:
                    expected_wvmax = wvmax_expected

                # clip initial master arc line list with bright lines to
                # the expected wavelength range
                lok1 = expected_wvmin <= wv_master
                lok2 = wv_master <= expected_wvmax
                lok = lok1 * lok2
                wv_master_eff = wv_master[lok]

                # perform initial wavelength calibration
                solution_wv = wvcal_spectrum(
                    sp=sp_median,
                    fxpeaks=fxpeaks,
                    poly_degree_wfit=args_poldeg_initial,
                    wv_master=wv_master_eff,
                    wv_ini_search=expected_wvmin,
                    wv_end_search=expected_wvmax,
                    wvmin_useful=wvmin_useful,
                    wvmax_useful=wvmax_useful,
                    geometry=args_geometry,
                    debugplot=slt.debugplot
                )
                # store initial wavelength calibration polynomial in current
                # slitlet instance
                slt.wpoly = np.polynomial.Polynomial(solution_wv.coeff)
                pause_debugplot(debugplot)

                # clip initial master arc line list with all the lines to
                # the expected wavelength range
                lok1 = expected_wvmin <= wv_master_all
                lok2 = wv_master_all <= expected_wvmax
                lok = lok1 * lok2
                wv_master_all_eff = wv_master_all[lok]

                # clip master arc line list to useful region
                if wvmin_useful is not None:
                    lok = wvmin_useful <= wv_master_all_eff
                    wv_master_all_eff  = wv_master_all_eff[lok]
                if wvmax_useful is not None:
                    lok = wv_master_all_eff <= wvmax_useful
                    wv_master_all_eff  = wv_master_all_eff[lok]

                # refine wavelength calibration
                if args_poldeg_refined > 0:
                    plottitle = '[slitlet#{}, refined]'.format(islitlet)
                    poly_refined, yres_summary = refine_arccalibration(
                        sp=sp_median,
                        poly_initial=slt.wpoly,
                        wv_master=wv_master_all_eff,
                        poldeg=args_poldeg_refined,
                        ntimes_match_wv=1,
                        interactive=args_interactive,
                        threshold=args_threshold_wv,
                        plottitle=plottitle,
                        ylogscale=args_ylogscale,
                        geometry=args_geometry,
                        pdf=args_pdf,
                        debugplot=slt.debugplot
                    )
                    # store refined wavelength calibration polynomial in
                    # current slitlet instance
                    slt.wpoly = poly_refined

                # compute approximate linear values for CRVAL1 and CDELT1
                naxis1_linear = sp_median.shape[0]
                crmin1_linear = slt.wpoly(1)
                crmax1_linear = slt.wpoly(naxis1_linear)
                slt.crval1_linear = crmin1_linear
                slt.cdelt1_linear = \
                    (crmax1_linear - crmin1_linear) / (naxis1_linear - 1)

                # check that the trimming of wv_master and wv_master_all has
                # preserved the wavelength range [crmin1_linear, crmax1_linear]
                if crmin1_linear < expected_wvmin:
                    logger.warning(">>> islitlet: " +str(islitlet))
                    logger.warning("expected_wvmin: " + str(expected_wvmin))
                    logger.warning("crmin1_linear.: " + str(crmin1_linear))
                    logger.warning("WARNING: Unexpected crmin1_linear < "
                                   "expected_wvmin")
                if crmax1_linear > expected_wvmax:
                    logger.warning(">>> islitlet: " +str(islitlet))
                    logger.warning("expected_wvmax: " + str(expected_wvmax))
                    logger.warning("crmax1_linear.: " + str(crmax1_linear))
                    logger.warning("WARNING: Unexpected crmax1_linear > "
                                   "expected_wvmax")

                cout += '.'

            else:

                cout += 'x'

            if islitlet % 10 == 0:
                if cout != 'x':
                    cout = str(islitlet // 10)

            if debugplot != 0:
                pause_debugplot(debugplot)

        else:

            # define Slitlet2dArc object
            slt = Slitlet2dArc(
                islitlet=islitlet,
                csu_conf=csu_conf,
                ymargin_bb=args_ymargin_bb,
                params=None,
                parmodel=None,
                debugplot=debugplot
            )

            cout += 'i'

        # store current slitlet in list of measured slitlets
        measured_slitlets.append(slt)

        logger.info(cout)

    # ---

    # generate FITS file structure with 55 spectra corresponding to the
    # median spectrum for each slitlet
    reduced_55sp = fits.PrimaryHDU(data=image2d_55sp)
    reduced_55sp.header['crpix1'] = (0.0, 'reference pixel')
    reduced_55sp.header['crval1'] = (0.0, 'central value at crpix2')
    reduced_55sp.header['cdelt1'] = (1.0, 'increment')
    reduced_55sp.header['ctype1'] = 'PIXEL'
    reduced_55sp.header['cunit1'] = ('Pixel', 'units along axis2')
    reduced_55sp.header['crpix2'] = (0.0, 'reference pixel')
    reduced_55sp.header['crval2'] = (0.0, 'central value at crpix2')
    reduced_55sp.header['cdelt2'] = (1.0, 'increment')
    reduced_55sp.header['ctype2'] = 'PIXEL'
    reduced_55sp.header['cunit2'] = ('Pixel', 'units along axis2')

    # ---

    # Generate structure to store intermediate results
    outdict = {}
    outdict['instrument'] = 'EMIR'
    outdict['meta_info'] = {}
    outdict['meta_info']['creation_date'] = datetime.now().isoformat()
    outdict['meta_info']['description'] = \
        'computation of rectification and wavelength calibration polynomial ' \
        'coefficients for a particular CSU configuration'
    outdict['meta_info']['recipe_name'] = 'undefined'
    outdict['meta_info']['origin'] = {}
    outdict['meta_info']['origin']['bound_param_uuid'] = \
        bound_param.uuid
    outdict['meta_info']['origin']['arc_image_uuid'] = 'undefined'
    outdict['tags'] = {}
    outdict['tags']['grism'] = grism_name
    outdict['tags']['filter'] = filter_name
    outdict['tags']['islitlet_min'] = islitlet_min
    outdict['tags']['islitlet_max'] = islitlet_max
    outdict['dtu_configuration'] = dtu_conf.outdict()
    outdict['uuid'] = str(uuid4())
    outdict['contents'] = {}

    missing_slitlets = []
    for slt in measured_slitlets:

        islitlet = slt.islitlet

        if islitlet_min <= islitlet <= islitlet_max:

            # avoid error when creating a python list of coefficients from
            # numpy polynomials when the polynomials do not exist (note that
            # the JSON format doesn't handle numpy arrays and such arrays must
            # be transformed into native python lists)
            if slt.wpoly is None:
                wpoly_coeff = None
            else:
                wpoly_coeff = slt.wpoly.coef.tolist()
            if slt.wpoly_longslit_model is None:
                wpoly_coeff_longslit_model = None
            else:
                wpoly_coeff_longslit_model = \
                    slt.wpoly_longslit_model.coef.tolist()

            # avoid similar error when creating a python list of coefficients
            # when the numpy array does not exist; note that this problem
            # does not happen with tt?_aij_longslit_model and
            # tt?_bij_longslit_model because the latter have already been
            # created as native python lists
            if slt.ttd_aij is None:
                ttd_aij = None
            else:
                ttd_aij = slt.ttd_aij.tolist()
            if slt.ttd_bij is None:
                ttd_bij = None
            else:
                ttd_bij = slt.ttd_bij.tolist()
            if slt.tti_aij is None:
                tti_aij = None
            else:
                tti_aij = slt.tti_aij.tolist()
            if slt.tti_bij is None:
                tti_bij = None
            else:
                tti_bij = slt.tti_bij.tolist()

            # creating temporary dictionary with the information corresponding
            # to the current slitlett that will be saved in the JSON file
            tmp_dict = {
                'csu_bar_left': slt.csu_bar_left,
                'csu_bar_right': slt.csu_bar_right,
                'csu_bar_slit_center': slt.csu_bar_slit_center,
                'csu_bar_slit_width': slt.csu_bar_slit_width,
                'x0_reference': slt.x0_reference,
                'y0_reference_lower': slt.y0_reference_lower,
                'y0_reference_middle': slt.y0_reference_middle,
                'y0_reference_upper': slt.y0_reference_upper,
                'y0_reference_lower_expected':
                    slt.y0_reference_lower_expected,
                'y0_reference_middle_expected':
                    slt.y0_reference_middle_expected,
                'y0_reference_upper_expected':
                    slt.y0_reference_upper_expected,
                'y0_frontier_lower': slt.y0_frontier_lower,
                'y0_frontier_upper': slt.y0_frontier_upper,
                'y0_frontier_lower_expected': slt.y0_frontier_lower_expected,
                'y0_frontier_upper_expected': slt.y0_frontier_upper_expected,
                'corr_yrect_a': slt.corr_yrect_a,
                'corr_yrect_b': slt.corr_yrect_b,
                'min_row_rectified': slt.min_row_rectified,
                'max_row_rectified': slt.max_row_rectified,
                'ymargin_bb': slt.ymargin_bb,
                'bb_nc1_orig': slt.bb_nc1_orig,
                'bb_nc2_orig': slt.bb_nc2_orig,
                'bb_ns1_orig': slt.bb_ns1_orig,
                'bb_ns2_orig': slt.bb_ns2_orig,
                'spectrail': {
                    'poly_coef_lower':
                        slt.list_spectrails[
                            slt.i_lower_spectrail].poly_funct.coef.tolist(),
                    'poly_coef_middle':
                        slt.list_spectrails[
                            slt.i_middle_spectrail].poly_funct.coef.tolist(),
                    'poly_coef_upper':
                        slt.list_spectrails[
                            slt.i_upper_spectrail].poly_funct.coef.tolist(),
                },
                'frontier': {
                    'poly_coef_lower':
                        slt.list_frontiers[0].poly_funct.coef.tolist(),
                    'poly_coef_upper':
                        slt.list_frontiers[1].poly_funct.coef.tolist(),
                },
                'ttd_order': slt.ttd_order,
                'ttd_aij': ttd_aij,
                'ttd_bij': ttd_bij,
                'tti_aij': tti_aij,
                'tti_bij': tti_bij,
                'ttd_order_longslit_model': slt.ttd_order_longslit_model,
                'ttd_aij_longslit_model': slt.ttd_aij_longslit_model,
                'ttd_bij_longslit_model': slt.ttd_bij_longslit_model,
                'tti_aij_longslit_model': slt.tti_aij_longslit_model,
                'tti_bij_longslit_model': slt.tti_bij_longslit_model,
                'wpoly_coeff': wpoly_coeff,
                'wpoly_coeff_longslit_model': wpoly_coeff_longslit_model,
                'crval1_linear': slt.crval1_linear,
                'cdelt1_linear': slt.cdelt1_linear
            }
        else:
            missing_slitlets.append(islitlet)
            tmp_dict = {
                'csu_bar_left': slt.csu_bar_left,
                'csu_bar_right': slt.csu_bar_right,
                'csu_bar_slit_center': slt.csu_bar_slit_center,
                'csu_bar_slit_width': slt.csu_bar_slit_width,
                'x0_reference': slt.x0_reference,
                'y0_frontier_lower_expected': slt.y0_frontier_lower_expected,
                'y0_frontier_upper_expected': slt.y0_frontier_upper_expected
            }
        slitlet_label = "slitlet" + str(islitlet).zfill(2)
        outdict['contents'][slitlet_label] = tmp_dict

    # ---

    # OBSOLETE
    '''
    # save JSON file needed to compute the MOS model
    with open(args.out_json.name, 'w') as fstream:
        json.dump(outdict, fstream, indent=2, sort_keys=True)
        print('>>> Saving file ' + args.out_json.name)
    '''

    # ---

    # Create object of type RectWaveCoeff with coefficients for
    # rectification and wavelength calibration
    rectwv_coeff = RectWaveCoeff(instrument='EMIR')
    rectwv_coeff.quality_control = numina.types.qc.QC.GOOD
    rectwv_coeff.tags['grism'] = grism_name
    rectwv_coeff.tags['filter'] = filter_name
    rectwv_coeff.meta_info['origin']['bound_param'] = \
        'uuid' + bound_param.uuid
    rectwv_coeff.meta_info['dtu_configuration'] = outdict['dtu_configuration']
    rectwv_coeff.total_slitlets = EMIR_NBARS
    rectwv_coeff.missing_slitlets = missing_slitlets
    for i in range(EMIR_NBARS):
        islitlet = i + 1
        dumdict = {'islitlet': islitlet}
        cslitlet = 'slitlet' + str(islitlet).zfill(2)
        if cslitlet in outdict['contents']:
            dumdict.update(outdict['contents'][cslitlet])
        else:
            raise ValueError("Unexpected error")
        rectwv_coeff.contents.append(dumdict)
    # debugging __getstate__ and __setstate__
    # rectwv_coeff.writeto(args.out_json.name)
    # print('>>> Saving file ' + args.out_json.name)
    # check_setstate_getstate(rectwv_coeff, args.out_json.name)
    logger.info('Generating RectWaveCoeff object with uuid=' +
                rectwv_coeff.uuid)

    return rectwv_coeff, reduced_55sp


Instruction:
How would you explain what the following Python 3 function does
def offsets_from_wcs(frames, pixref):
    '''Compute offsets between frames using WCS information.

    :parameter frames: sequence of FITS filenames or file descriptors
    :parameter pixref: numpy array used as reference pixel

    The sky world coordinates are computed on *pixref* using
    the WCS of the first frame in the sequence. Then, the
    pixel coordinates of the reference sky world-coordinates
    are computed for the rest of the frames.

    The results is a numpy array with the difference between the
    computed pixel value and the reference pixel. The first line
    of the array is [0, 0], being the offset from the first image
    to itself.

    '''

    result = numpy.zeros((len(frames), pixref.shape[1]))

    with frames[0].open() as hdulist:
        wcsh = wcs.WCS(hdulist[0].header)
        skyref = wcsh.wcs_pix2world(pixref, 1)

    for idx, frame in enumerate(frames[1:]):
        with frame.open() as hdulist:
            wcsh = wcs.WCS(hdulist[0].header)
            pixval = wcsh.wcs_world2pix(skyref, 1)
            result[idx + 1] = -(pixval[0] - pixref[0])

    return result

Response: Compute offsets between frames using WCS information.


Instruction:
Explain what the following Python 3 code does
def reference_pix_from_wcs(frames, pixref, origin=1):

    result = []

    with frames[0].open() as hdulist:
        wcsh = wcs.WCS(hdulist[0].header)
        skyref = wcsh.wcs_pix2world([pixref], origin)
        result.append(pixref)

    for idx, frame in enumerate(frames[1:]):
        with frame.open() as hdulist:
            wcsh = wcs.WCS(hdulist[0].header)
            pixval = wcsh.wcs_world2pix(skyref, origin)
            result.append(tuple(pixval[0]))

    return result

Response: Compute reference pixels between frames using WCS information.


Instruction:
Here you have a function in Python 3, explain what it does
def reference_pix_from_wcs_imgs(imgs, pixref, origin=1):

    result = []

    refimg = imgs[0]

    wcsh = wcs.WCS(refimg[0].header)
    skyref = wcsh.wcs_pix2world([pixref], origin)
    result.append(pixref)

    for idx, img in enumerate(imgs[1:]):
        wcsh = wcs.WCS(img[0].header)
        pixval = wcsh.wcs_world2pix(skyref, origin)
        result.append(tuple(pixval[0]))

    return result

Response: Compute reference pixels between frames using WCS information.


Instruction:
Can you create a Python 3 function that
processes the request and return the user s session id and session id.

Response:
def process_request(self, request=None, cookie=None, **kwargs):
        """
        Perform user logout

        :param request:
        :param cookie:
        :param kwargs:
        :return:
        """
        _cntx = self.endpoint_context
        _sdb = _cntx.sdb

        if 'post_logout_redirect_uri' in request:
            if 'id_token_hint' not in request:
                raise InvalidRequest(
                    "If post_logout_redirect_uri then id_token_hint is a MUST")
        _cookie_name = self.endpoint_context.cookie_name['session']
        try:
            part = self.endpoint_context.cookie_dealer.get_cookie_value(
                cookie, cookie_name=_cookie_name)
        except IndexError:
            raise InvalidRequest('Cookie error')
        except KeyError:
            part = None

        if part:
            # value is a base64 encoded JSON document
            _cookie_info = json.loads(as_unicode(b64d(as_bytes(part[0]))))
            logger.debug('Cookie info: {}'.format(_cookie_info))
            _sid = _cookie_info['sid']
        else:
            logger.debug('No relevant cookie')
            _sid = ''
            _cookie_info = {}

        if 'id_token_hint' in request:
            logger.debug(
                'ID token hint: {}'.format(
                    request[verified_claim_name("id_token_hint")]))

            auds = request[verified_claim_name("id_token_hint")]['aud']
            _ith_sid = ''
            _sids = _sdb.sso_db.get_sids_by_sub(
                request[verified_claim_name("id_token_hint")]['sub'])

            if _sids is None:
                raise ValueError('Unknown subject identifier')

            for _isid in _sids:
                if _sdb[_isid]['authn_req']['client_id'] in auds:
                    _ith_sid = _isid
                    break

            if not _ith_sid:
                raise ValueError('Unknown subject')

            if _sid:
                if _ith_sid != _sid:  # someone's messing with me
                    raise ValueError('Wrong ID Token hint')
            else:
                _sid = _ith_sid
        else:
            auds = []

        try:
            session = _sdb[_sid]
        except KeyError:
            raise ValueError("Can't find any corresponding session")

        client_id = session['authn_req']['client_id']
        # Does this match what's in the cookie ?
        if _cookie_info:
            if client_id != _cookie_info['client_id']:
                logger.warning(
                    'Client ID in authz request and in cookie does not match')
                raise ValueError("Wrong Client")

        if auds:
            if client_id not in auds:
                raise ValueError('Incorrect ID Token hint')

        _cinfo = _cntx.cdb[client_id]

        # verify that the post_logout_redirect_uri if present are among the ones
        # registered

        try:
            _uri = request['post_logout_redirect_uri']
        except KeyError:
            if _cntx.issuer.endswith('/'):
                _uri = "{}{}".format(_cntx.issuer,
                                     self.kwargs['post_logout_uri_path'])
            else:
                _uri = "{}/{}".format(_cntx.issuer,
                                      self.kwargs['post_logout_uri_path'])
            plur = False
        else:
            plur = True
            verify_uri(_cntx, request, 'post_logout_redirect_uri',
                       client_id=client_id)

        payload = {
            'sid': _sid, 'client_id': client_id,
            'user': session['authn_event']['uid']
        }

        # redirect user to OP logout verification page
        if plur and 'state' in request:
            _uri = '{}?{}'.format(_uri, urlencode({'state': request['state']}))
            payload['state'] = request['state']

        payload['redirect_uri'] = _uri

        logger.debug('JWS payload: {}'.format(payload))
        # From me to me
        _jws = JWT(_cntx.keyjar, iss=_cntx.issuer, lifetime=86400,
                   sign_alg=self.kwargs['signing_alg'])
        sjwt = _jws.pack(payload=payload, recv=_cntx.issuer)

        location = '{}?{}'.format(self.kwargs['logout_verify_url'],
                                  urlencode({'sjwt': sjwt}))
        return {'redirect_location': location}


Instruction:
Implement a function in Python 3 to
evaluate rect.+wavecal. coefficients from MOS library.

Response:
def rectwv_coeff_from_mos_library(reduced_image,
                                  master_rectwv,
                                  ignore_dtu_configuration=True,
                                  debugplot=0):
    """Evaluate rect.+wavecal. coefficients from MOS library

    Parameters
    ----------
    reduced_image : HDUList object
        Image with preliminary basic reduction: bpm, bias, dark and
        flatfield.
    master_rectwv : MasterRectWave instance
        Rectification and Wavelength Calibrartion Library product.
        Contains the library of polynomial coefficients necessary
        to generate an instance of RectWaveCoeff with the rectification
        and wavelength calibration coefficients for the particular
        CSU configuration.
    ignore_dtu_configuration : bool
        If True, ignore differences in DTU configuration.
    debugplot : int
        Debugging level for messages and plots. For details see
        'numina.array.display.pause_debugplot.py'.

    Returns
    -------
    rectwv_coeff : RectWaveCoeff instance
        Rectification and wavelength calibration coefficients for the
        particular CSU configuration.

    """

    logger = logging.getLogger(__name__)
    logger.info('Computing expected RectWaveCoeff from CSU configuration')

    # header
    header = reduced_image[0].header

    # read the CSU configuration from the image header
    csu_conf = CsuConfiguration.define_from_header(header)

    # read the DTU configuration from the image header
    dtu_conf = DtuConfiguration.define_from_header(header)

    # retrieve DTU configuration from MasterRectWave object
    dtu_conf_calib = DtuConfiguration.define_from_dictionary(
        master_rectwv.meta_info['dtu_configuration']
    )
    # check that the DTU configuration employed to obtain the calibration
    # corresponds to the DTU configuration in the input FITS file
    if dtu_conf != dtu_conf_calib:
        if ignore_dtu_configuration:
            logger.warning('DTU configuration differences found!')
        else:
            logger.info('DTU configuration from image header:')
            logger.info(dtu_conf)
            logger.info('DTU configuration from master calibration:')
            logger.info(dtu_conf_calib)
            raise ValueError("DTU configurations do not match!")
    else:
        logger.info('DTU configuration match!')

    # check grism and filter
    filter_name = header['filter']
    logger.debug('Filter: ' + filter_name)
    if filter_name != master_rectwv.tags['filter']:
        raise ValueError('Filter name does not match!')
    grism_name = header['grism']
    logger.debug('Grism: ' + grism_name)
    if grism_name != master_rectwv.tags['grism']:
        raise ValueError('Grism name does not match!')

    # valid slitlet numbers
    list_valid_islitlets = list(range(1, EMIR_NBARS + 1))
    for idel in master_rectwv.missing_slitlets:
        list_valid_islitlets.remove(idel)
    logger.debug('valid slitlet numbers: ' + str(list_valid_islitlets))

    # initialize intermediate dictionary with relevant information
    # (note: this dictionary corresponds to an old structure employed to
    # store the information in a JSON file; this is no longer necessary,
    # but here we reuse that dictionary for convenience)
    outdict = {}
    outdict['instrument'] = 'EMIR'
    outdict['meta_info'] = {}
    outdict['meta_info']['creation_date'] = datetime.now().isoformat()
    outdict['meta_info']['description'] = \
        'computation of rectification and wavelength calibration polynomial ' \
        'coefficients for a particular CSU configuration from a MOS model '
    outdict['meta_info']['recipe_name'] = 'undefined'
    outdict['meta_info']['origin'] = {}
    outdict['meta_info']['origin']['fits_frame_uuid'] = 'TBD'
    outdict['meta_info']['origin']['rect_wpoly_mos_uuid'] = \
        master_rectwv.uuid
    outdict['meta_info']['origin']['fitted_boundary_param_uuid'] = \
        master_rectwv.meta_info['origin']['bound_param']
    outdict['tags'] = {}
    outdict['tags']['grism'] = grism_name
    outdict['tags']['filter'] = filter_name
    outdict['dtu_configuration'] = dtu_conf.outdict()
    outdict['uuid'] = str(uuid4())
    outdict['contents'] = {}

    # compute rectification and wavelength calibration coefficients for each
    # slitlet according to its csu_bar_slit_center value
    for islitlet in list_valid_islitlets:
        cslitlet = 'slitlet' + str(islitlet).zfill(2)

        # csu_bar_slit_center of current slitlet in initial FITS image
        csu_bar_slit_center = csu_conf.csu_bar_slit_center(islitlet)

        # input data structure
        tmpdict = master_rectwv.contents[islitlet - 1]
        list_csu_bar_slit_center = tmpdict['list_csu_bar_slit_center']

        # check extrapolations
        if csu_bar_slit_center < min(list_csu_bar_slit_center):
            logger.warning('extrapolating table with ' + cslitlet)
            logger.warning('minimum tabulated value: ' +
                           str(min(list_csu_bar_slit_center)))
            logger.warning('sought value...........: ' +
                           str(csu_bar_slit_center))
        if csu_bar_slit_center > max(list_csu_bar_slit_center):
            logger.warning('extrapolating table with ' + cslitlet)
            logger.warning('maximum tabulated value: ' +
                           str(max(list_csu_bar_slit_center)))
            logger.warning('sought value...........: ' +
                           str(csu_bar_slit_center))

        # rectification coefficients
        ttd_order = tmpdict['ttd_order']
        ncoef = ncoef_fmap(ttd_order)
        outdict['contents'][cslitlet] = {}
        outdict['contents'][cslitlet]['ttd_order'] = ttd_order
        outdict['contents'][cslitlet]['ttd_order_longslit_model'] = None
        for keycoef in ['ttd_aij', 'ttd_bij', 'tti_aij', 'tti_bij']:
            coef_out = []
            for icoef in range(ncoef):
                ccoef = str(icoef).zfill(2)
                list_cij = tmpdict['list_' + keycoef + '_' + ccoef]
                funinterp_coef = interp1d(list_csu_bar_slit_center,
                                          list_cij,
                                          kind='linear',
                                          fill_value='extrapolate')
                # note: funinterp_coef expects a numpy array
                dum = funinterp_coef([csu_bar_slit_center])
                coef_out.append(dum[0])
            outdict['contents'][cslitlet][keycoef] = coef_out
            outdict['contents'][cslitlet][keycoef + '_longslit_model'] = None

        # wavelength calibration coefficients
        ncoef = tmpdict['wpoly_degree'] + 1
        wpoly_coeff = []
        for icoef in range(ncoef):
            ccoef = str(icoef).zfill(2)
            list_cij = tmpdict['list_wpoly_coeff_' + ccoef]
            funinterp_coef = interp1d(list_csu_bar_slit_center,
                                      list_cij,
                                      kind='linear',
                                      fill_value='extrapolate')
            # note: funinterp_coef expects a numpy array
            dum = funinterp_coef([csu_bar_slit_center])
            wpoly_coeff.append(dum[0])
        outdict['contents'][cslitlet]['wpoly_coeff'] = wpoly_coeff
        outdict['contents'][cslitlet]['wpoly_coeff_longslit_model'] = None

        # update cdelt1_linear and crval1_linear
        wpoly_function = np.polynomial.Polynomial(wpoly_coeff)
        crmin1_linear = wpoly_function(1)
        crmax1_linear = wpoly_function(EMIR_NAXIS1)
        cdelt1_linear = (crmax1_linear - crmin1_linear) / (EMIR_NAXIS1 - 1)
        crval1_linear = crmin1_linear
        outdict['contents'][cslitlet]['crval1_linear'] = crval1_linear
        outdict['contents'][cslitlet]['cdelt1_linear'] = cdelt1_linear

        # update CSU keywords
        outdict['contents'][cslitlet]['csu_bar_left'] = \
            csu_conf.csu_bar_left(islitlet)
        outdict['contents'][cslitlet]['csu_bar_right'] = \
            csu_conf.csu_bar_right(islitlet)
        outdict['contents'][cslitlet]['csu_bar_slit_center'] = \
            csu_conf.csu_bar_slit_center(islitlet)
        outdict['contents'][cslitlet]['csu_bar_slit_width'] = \
            csu_conf.csu_bar_slit_width(islitlet)

    # for each slitlet compute spectrum trails and frontiers using the
    # fitted boundary parameters
    fitted_bound_param_json = {
        'contents': master_rectwv.meta_info['refined_boundary_model']
    }
    parmodel = fitted_bound_param_json['contents']['parmodel']
    fitted_bound_param_json.update({'meta_info': {'parmodel': parmodel}})
    params = bound_params_from_dict(fitted_bound_param_json)
    if abs(debugplot) >= 10:
        logger.debug('Fitted boundary parameters:')
        logger.debug(params.pretty_print())
    for islitlet in list_valid_islitlets:
        cslitlet = 'slitlet' + str(islitlet).zfill(2)
        # csu_bar_slit_center of current slitlet in initial FITS image
        csu_bar_slit_center = csu_conf.csu_bar_slit_center(islitlet)
        # compute and store x0_reference value
        x0_reference = float(EMIR_NAXIS1) / 2.0 + 0.5
        outdict['contents'][cslitlet]['x0_reference'] = x0_reference
        # compute spectrum trails (lower, middle and upper)
        list_spectrails = expected_distorted_boundaries(
            islitlet, csu_bar_slit_center,
            [0, 0.5, 1], params, parmodel,
            numpts=101, deg=5, debugplot=0
        )
        # store spectrails in output JSON file
        outdict['contents'][cslitlet]['spectrail'] = {}
        for idum, cdum in zip(range(3), ['lower', 'middle', 'upper']):
            outdict['contents'][cslitlet]['spectrail']['poly_coef_' + cdum] = \
                list_spectrails[idum].poly_funct.coef.tolist()
            outdict['contents'][cslitlet]['y0_reference_' + cdum] = \
                list_spectrails[idum].poly_funct(x0_reference)
        # compute frontiers (lower, upper)
        list_frontiers = expected_distorted_frontiers(
            islitlet, csu_bar_slit_center,
            params, parmodel,
            numpts=101, deg=5, debugplot=0
        )
        # store frontiers in output JSON
        outdict['contents'][cslitlet]['frontier'] = {}
        for idum, cdum in zip(range(2), ['lower', 'upper']):
            outdict['contents'][cslitlet]['frontier']['poly_coef_' + cdum] = \
                list_frontiers[idum].poly_funct.coef.tolist()
            outdict['contents'][cslitlet]['y0_frontier_' + cdum] = \
                list_frontiers[idum].poly_funct(x0_reference)

    # store bounding box parameters for each slitlet
    xdum = np.linspace(1, EMIR_NAXIS1, num=EMIR_NAXIS1)
    for islitlet in list_valid_islitlets:
        cslitlet = 'slitlet' + str(islitlet).zfill(2)
        # parameters already available in the input JSON file
        for par in ['bb_nc1_orig', 'bb_nc2_orig', 'ymargin_bb']:
            outdict['contents'][cslitlet][par] = \
                master_rectwv.contents[islitlet - 1][par]
        # estimate bb_ns1_orig and bb_ns2_orig using the already computed
        # frontiers and the value of ymargin_bb, following the same approach
        # employed in Slitlet2dArc.__init__()
        poly_lower_frontier = np.polynomial.Polynomial(
            outdict['contents'][cslitlet]['frontier']['poly_coef_lower']
        )
        poly_upper_frontier = np.polynomial.Polynomial(
            outdict['contents'][cslitlet]['frontier']['poly_coef_upper']
        )
        ylower = poly_lower_frontier(xdum)
        yupper = poly_upper_frontier(xdum)
        ymargin_bb = master_rectwv.contents[islitlet - 1]['ymargin_bb']
        bb_ns1_orig = int(ylower.min() + 0.5) - ymargin_bb
        if bb_ns1_orig < 1:
            bb_ns1_orig = 1
        bb_ns2_orig = int(yupper.max() + 0.5) + ymargin_bb
        if bb_ns2_orig > EMIR_NAXIS2:
            bb_ns2_orig = EMIR_NAXIS2
        outdict['contents'][cslitlet]['bb_ns1_orig'] = bb_ns1_orig
        outdict['contents'][cslitlet]['bb_ns2_orig'] = bb_ns2_orig

    # additional parameters (see Slitlet2dArc.__init__)
    for islitlet in list_valid_islitlets:
        cslitlet = 'slitlet' + str(islitlet).zfill(2)
        # define expected frontier ordinates at x0_reference for the rectified
        # image imposing the vertical length of the slitlet to be constant
        # and equal to EMIR_NPIXPERSLIT_RECTIFIED
        outdict['contents'][cslitlet]['y0_frontier_lower_expected'] = \
            expected_y0_lower_frontier(islitlet)
        outdict['contents'][cslitlet]['y0_frontier_upper_expected'] = \
            expected_y0_upper_frontier(islitlet)
        # compute linear transformation to place the rectified slitlet at
        # the center of the current slitlet bounding box
        tmpdict = outdict['contents'][cslitlet]
        xdum1 = tmpdict['y0_frontier_lower']
        ydum1 = tmpdict['y0_frontier_lower_expected']
        xdum2 = tmpdict['y0_frontier_upper']
        ydum2 = tmpdict['y0_frontier_upper_expected']
        corr_yrect_b = (ydum2 - ydum1) / (xdum2 - xdum1)
        corr_yrect_a = ydum1 - corr_yrect_b * xdum1
        # compute expected location of rectified boundaries
        y0_reference_lower_expected = \
            corr_yrect_a + corr_yrect_b * tmpdict['y0_reference_lower']
        y0_reference_middle_expected = \
            corr_yrect_a + corr_yrect_b * tmpdict['y0_reference_middle']
        y0_reference_upper_expected = \
            corr_yrect_a + corr_yrect_b * tmpdict['y0_reference_upper']
        # shift transformation to center the rectified slitlet within the
        # slitlet bounding box
        ydummid = (ydum1 + ydum2) / 2
        ioffset = int(
            ydummid - (tmpdict['bb_ns1_orig'] + tmpdict['bb_ns2_orig']) / 2.0)
        corr_yrect_a -= ioffset
        # minimum and maximum row in the rectified slitlet encompassing
        # EMIR_NPIXPERSLIT_RECTIFIED pixels
        # a) scan number (in pixels, from 1 to NAXIS2)
        xdum1 = corr_yrect_a + \
                corr_yrect_b * tmpdict['y0_frontier_lower']
        xdum2 = corr_yrect_a + \
                corr_yrect_b * tmpdict['y0_frontier_upper']
        # b) row number (starting from zero)
        min_row_rectified = \
            int((round(xdum1 * 10) + 5) / 10) - tmpdict['bb_ns1_orig']
        max_row_rectified = \
            int((round(xdum2 * 10) - 5) / 10) - tmpdict['bb_ns1_orig']
        # save previous results in outdict
        outdict['contents'][cslitlet]['y0_reference_lower_expected'] = \
            y0_reference_lower_expected
        outdict['contents'][cslitlet]['y0_reference_middle_expected'] = \
            y0_reference_middle_expected
        outdict['contents'][cslitlet]['y0_reference_upper_expected'] = \
            y0_reference_upper_expected
        outdict['contents'][cslitlet]['corr_yrect_a'] = corr_yrect_a
        outdict['contents'][cslitlet]['corr_yrect_b'] = corr_yrect_b
        outdict['contents'][cslitlet]['min_row_rectified'] = min_row_rectified
        outdict['contents'][cslitlet]['max_row_rectified'] = max_row_rectified

    # ---

    # Create object of type RectWaveCoeff with coefficients for
    # rectification and wavelength calibration
    rectwv_coeff = RectWaveCoeff(instrument='EMIR')
    rectwv_coeff.quality_control = numina.types.qc.QC.GOOD
    rectwv_coeff.tags['grism'] = grism_name
    rectwv_coeff.tags['filter'] = filter_name
    rectwv_coeff.meta_info['origin']['bound_param'] = \
        master_rectwv.meta_info['origin']['bound_param']
    rectwv_coeff.meta_info['origin']['master_rectwv'] = \
        'uuid' + master_rectwv.uuid
    rectwv_coeff.meta_info['dtu_configuration'] = outdict['dtu_configuration']
    rectwv_coeff.total_slitlets = EMIR_NBARS
    for i in range(EMIR_NBARS):
        islitlet = i + 1
        dumdict = {'islitlet': islitlet}
        cslitlet = 'slitlet' + str(islitlet).zfill(2)
        if cslitlet in outdict['contents']:
            dumdict.update(outdict['contents'][cslitlet])
        else:
            dumdict.update({
                'csu_bar_left': csu_conf.csu_bar_left(islitlet),
                'csu_bar_right': csu_conf.csu_bar_right(islitlet),
                'csu_bar_slit_center': csu_conf.csu_bar_slit_center(islitlet),
                'csu_bar_slit_width': csu_conf.csu_bar_slit_width(islitlet),
                'x0_reference': float(EMIR_NAXIS1) / 2.0 + 0.5,
                'y0_frontier_lower_expected':
                    expected_y0_lower_frontier(islitlet),
                'y0_frontier_upper_expected':
                    expected_y0_upper_frontier(islitlet)
            })
            rectwv_coeff.missing_slitlets.append(islitlet)
        rectwv_coeff.contents.append(dumdict)
    # debugging __getstate__ and __setstate__
    # rectwv_coeff.writeto(args.out_rect_wpoly.name)
    # print('>>> Saving file ' + args.out_rect_wpoly.name)
    # check_setstate_getstate(rectwv_coeff, args.out_rect_wpoly.name)
    logger.info('Generating RectWaveCoeff object with uuid=' +
                rectwv_coeff.uuid)

    return rectwv_coeff


Instruction:
How would you explain what the following Python 3 function does
def median_slitlets_rectified(
        input_image,
        mode=0,
        minimum_slitlet_width_mm=EMIR_MINIMUM_SLITLET_WIDTH_MM,
        maximum_slitlet_width_mm=EMIR_MAXIMUM_SLITLET_WIDTH_MM,
        debugplot=0
    ):
    """Compute median spectrum for each slitlet.

    Parameters
    ----------
    input_image : HDUList object
        Input 2D image.
    mode : int
        Indicate desired result:
        0 : image with the same size as the input image, with the
            median spectrum of each slitlet spanning all the spectra
            of the corresponding slitlet
        1 : image with 55 spectra, containing the median spectra of
            each slitlet
        2 : single collapsed median spectrum, using exclusively the
            useful slitlets from the input image
    minimum_slitlet_width_mm : float
        Minimum slitlet width (mm) for a valid slitlet.
    maximum_slitlet_width_mm : float
        Maximum slitlet width (mm) for a valid slitlet.
    debugplot : int
        Determines whether intermediate computations and/or plots
        are displayed. The valid codes are defined in
        numina.array.display.pause_debugplot.

    Returns
    -------
    image_median : HDUList object
        Output image.

    """

    image_header = input_image[0].header
    image2d = input_image[0].data

    # check image dimensions
    naxis2_expected = EMIR_NBARS * EMIR_NPIXPERSLIT_RECTIFIED

    naxis2, naxis1 = image2d.shape
    if naxis2 != naxis2_expected:
        raise ValueError("NAXIS2={0} should be {1}".format(
            naxis2, naxis2_expected
        ))

    # check that the FITS file has been obtained with EMIR
    instrument = image_header['instrume']
    if instrument != 'EMIR':
        raise ValueError("INSTRUME keyword is not 'EMIR'!")

    # initialize output image
    if mode == 0:
        image2d_median = np.zeros((naxis2, naxis1))
    else:
        image2d_median = np.zeros((EMIR_NBARS, naxis1))

    # main loop
    for i in range(EMIR_NBARS):
        ns1 = i * EMIR_NPIXPERSLIT_RECTIFIED + 1
        ns2 = ns1 + EMIR_NPIXPERSLIT_RECTIFIED - 1
        sp_median = np.median(image2d[(ns1-1):ns2, :], axis=0)

        if mode == 0:
            image2d_median[(ns1-1):ns2, :] = np.tile(
                sp_median, (EMIR_NPIXPERSLIT_RECTIFIED, 1)
            )
        else:
            image2d_median[i] = np.copy(sp_median)

    if mode == 2:
        # get CSU configuration from FITS header
        csu_config = CsuConfiguration.define_from_header(image_header)

        # define wavelength calibration parameters
        crpix1 = image_header['crpix1']
        crval1 = image_header['crval1']
        cdelt1 = image_header['cdelt1']

        # segregate slitlets
        list_useful_slitlets = csu_config.widths_in_range_mm(
            minwidth=minimum_slitlet_width_mm,
            maxwidth=maximum_slitlet_width_mm
        )
        list_not_useful_slitlets = [i for i in list(range(1, EMIR_NBARS + 1))
                                    if i not in list_useful_slitlets]
        if abs(debugplot) != 0:
            print('>>> list_useful_slitlets....:', list_useful_slitlets)
            print('>>> list_not_useful_slitlets:', list_not_useful_slitlets)

        # define mask from array data
        mask2d, borders = define_mask_borders(image2d_median, sought_value=0)
        if abs(debugplot) % 10 != 0:
            ximshow(mask2d.astype(int), z1z2=(-.2, 1.2), crpix1=crpix1,
                    crval1=crval1, cdelt1=cdelt1, debugplot=debugplot)

        # update mask with unused slitlets
        for islitlet in list_not_useful_slitlets:
            mask2d[islitlet - 1, :] = np.array([True] * naxis1)
        if abs(debugplot) % 10 != 0:
            ximshow(mask2d.astype(int), z1z2=(-.2, 1.2), crpix1=crpix1,
                    crval1=crval1, cdelt1=cdelt1, debugplot=debugplot)

        # useful image pixels
        image2d_masked = image2d_median * (1 - mask2d.astype(int))
        if abs(debugplot) % 10 != 0:
            ximshow(image2d_masked, crpix1=crpix1, crval1=crval1,
                    cdelt1=cdelt1, debugplot=debugplot)

        # masked image
        image2d_masked = np.ma.masked_array(image2d_median, mask=mask2d)
        # median spectrum
        image1d_median = np.ma.median(image2d_masked, axis=0).data

        image_median = fits.PrimaryHDU(data=image1d_median,
                                       header=image_header)

    else:
        image_median = fits.PrimaryHDU(data=image2d_median,
                                       header=image_header)

    return fits.HDUList([image_median])

Response: Compute the median spectrum of each slitlet in the input image.


Instruction:
Can you create a Python 3 function that
gets the networks assoiated with the resource description.

Response:
def get_networks(self):
        """Get the networks assoiated with the resource description.

        Returns
            list of tuple roles, network
        """
        networks = self.c_resources["networks"]
        result = []
        for net in networks:
            _c_network = net.get("_c_network")
            if _c_network is None:
                continue
            roles = utils.get_roles_as_list(net)
            result.append((roles, _c_network))
        return result


Instruction:
Make a summary of the following Python 3 code
def get_roles(self):

        machines = self.c_resources["machines"]
        result = {}
        for desc in machines:
            roles = utils.get_roles_as_list(desc)
            hosts = self._denormalize(desc)
            for role in roles:
                result.setdefault(role, [])
                result[role].extend(hosts)
        return result

Response: Get the roles associated with the hosts.


Instruction:
Write a Python 3 script for
starting a client WS connection.

Response:
async def start_client(self,
                           sock: anyio.abc.SocketStream,
                           addr,
                           path: str,
                           headers: Optional[List] = None,
                           subprotocols: Optional[List[str]] = None):
        """Start a client WS connection on this socket.

        Returns: the AcceptConnection message.
        """
        self._sock = sock
        self._connection = WSConnection(ConnectionType.CLIENT)
        if headers is None:
            headers = []
        if subprotocols is None:
            subprotocols = []
        data = self._connection.send(
            Request(
                host=addr[0],
                target=path,
                extra_headers=headers,
                subprotocols=subprotocols))
        await self._sock.send_all(data)

        assert self._scope is None
        self._scope = True
        try:
            event = await self._next_event()
            if not isinstance(event, AcceptConnection):
                raise ConnectionError("Failed to establish a connection",
                                      event)
            return event
        finally:
            self._scope = None


Instruction:
Can you implement a function in Python 3 that
starts a server WS connection on this socket.

Response:
async def start_server(self, sock: anyio.abc.SocketStream, filter=None):  # pylint: disable=W0622
        """Start a server WS connection on this socket.

        Filter: an async callable that gets passed the initial Request.
        It may return an AcceptConnection message, a bool, or a string (the
        subprotocol to use).
        Returns: the Request message.
        """
        assert self._scope is None
        self._scope = True
        self._sock = sock
        self._connection = WSConnection(ConnectionType.SERVER)

        try:
            event = await self._next_event()
            if not isinstance(event, Request):
                raise ConnectionError("Failed to establish a connection",
                                      event)
            msg = None
            if filter is not None:
                msg = await filter(event)
                if not msg:
                    msg = RejectConnection()
                elif msg is True:
                    msg = None
                elif isinstance(msg, str):
                    msg = AcceptConnection(subprotocol=msg)
            if not msg:
                msg = AcceptConnection(subprotocol=event.subprotocols[0])
            data = self._connection.send(msg)
            await self._sock.send_all(data)
            if not isinstance(msg, AcceptConnection):
                raise ConnectionError("Not accepted", msg)
        finally:
            self._scope = None


Instruction:
Can you write a function in Python 3 where it
gets the next event from the queue.

Response:
async def _next_event(self):
        """
        Gets the next event.
        """
        while True:
            for event in self._connection.events():
                if isinstance(event, Message):
                    # check if we need to buffer
                    if event.message_finished:
                        return self._wrap_data(self._gather_buffers(event))
                    self._buffer(event)
                    break  # exit for loop
                else:
                    return event

            data = await self._sock.receive_some(4096)
            if not data:
                return CloseConnection(code=500, reason="Socket closed")
            self._connection.receive_data(data)


Instruction:
Can you generate the documentation for the following Python 3 function
async def send(self, data: Union[bytes, str], final: bool = True):
        MsgType = TextMessage if isinstance(data, str) else BytesMessage
        data = MsgType(data=data, message_finished=final)
        data = self._connection.send(event=data)
        await self._sock.send_all(data)

Response: Sends some data down the connection.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _buffer(self, event: Message):
        if isinstance(event, BytesMessage):
            self._byte_buffer.write(event.data)
        elif isinstance(event, TextMessage):
            self._string_buffer.write(event.data)

Response: Buffers an event to the internal buffer.


Instruction:
Can you tell what is the following Python 3 function doing
def _gather_buffers(self, event: Message):
        if isinstance(event, BytesMessage):
            buf = self._byte_buffer
        else:
            buf = self._string_buffer

        # yay for code shortening
        buf.write(event.data)
        buf.seek(0)
        data = buf.read()
        buf.seek(0)
        buf.truncate()
        return data

Response: Gathers all the data from a buffer.


Instruction:
Here you have a function in Python 3, explain what it does
def _wrap_data(data: Union[str, bytes]):
        MsgType = TextMessage if isinstance(data, str) else BytesMessage
        return MsgType(data=data, frame_finished=True, message_finished=True)

Response: Wraps data into the right event.


Instruction:
Write a Python 3 function that can
return the SQL for a given field with full type information.

Response:
def get_field_SQL(self, field_name, field):
        """
        returns the SQL for a given field with full type information

        http://www.sqlite.org/datatype3.html

        field_name -- string -- the field's name
        field -- Field() -- the set options for the field

        return -- string -- the field type (eg, foo BOOL NOT NULL)
        """
        field_type = ""
        is_pk = field.options.get('pk', False)

        if issubclass(field.type, bool):
            field_type = 'BOOLEAN'

        elif issubclass(field.type, long):
            if is_pk:
                field_type = 'INTEGER PRIMARY KEY'
            else:
                field_type = 'BIGINT'

        elif issubclass(field.type, int):
            field_type = 'INTEGER'
            if is_pk:
                field_type += ' PRIMARY KEY'

        elif issubclass(field.type, basestring):
            fo = field.options
            if field.is_ref():
                # TODO -- 7-8-17 - this isn't a great way to do this, ideally the Field instance
                # would combine all the options of both the current field and the
                # foreign key field and return all those when Field.options is called
                # (with the current field's options taking precedence) but there are
                # lots of circular dependency things that happen when one field is
                # trying to get the schema of another field and I don't have time
                # to sort it all out right now
                ref_s = field.schema
                fo = ref_s.pk.options

            if 'size' in fo:
                field_type = 'CHARACTER({})'.format(fo['size'])
            elif 'max_size' in fo:
                field_type = 'VARCHAR({})'.format(fo['max_size'])
            else:
                field_type = 'TEXT'

            if fo.get('ignore_case', False):
                field_type += ' COLLATE NOCASE'

            if is_pk:
                field_type += ' PRIMARY KEY'

        elif issubclass(field.type, datetime.datetime):
            #field_type = 'DATETIME'
            field_type = 'TIMESTAMP'

        elif issubclass(field.type, datetime.date):
            field_type = 'DATE'

        elif issubclass(field.type, float):
            field_type = 'REAL'
            size = field.options.get('size', field.options.get('max_size', 0))
            if size > 6:
                field_type = 'DOUBLE PRECISION'

        elif issubclass(field.type, decimal.Decimal):
            field_type = 'NUMERIC'

        elif issubclass(field.type, bytearray):
            field_type = 'BLOB'

        else:
            raise ValueError('unknown python type: {}'.format(field.type.__name__))

        if field.required:
            field_type += ' NOT NULL'
        else:
            field_type += ' NULL'

        if not is_pk:
            if field.is_ref():
                ref_s = field.schema
                if field.required: # strong ref, it deletes on fk row removal
                    field_type += ' REFERENCES {} ({}) ON UPDATE CASCADE ON DELETE CASCADE'.format(
                        ref_s,
                        ref_s.pk.name
                    )

                else: # weak ref, it sets column to null on fk row removal
                    field_type += ' REFERENCES {} ({}) ON UPDATE CASCADE ON DELETE SET NULL'.format(
                        ref_s,
                        ref_s.pk.name
                    )

        return '{} {}'.format(self._normalize_name(field_name), field_type)


Instruction:
Make a summary of the following Python 3 code
def _set_table(self, schema, **kwargs):
        query_str = []
        query_str.append("CREATE TABLE {} (".format(self._normalize_table_name(schema)))

        query_fields = []
        for field_name, field in schema.fields.items():
            query_fields.append('  {}'.format(self.get_field_SQL(field_name, field)))

        query_str.append(",{}".format(os.linesep).join(query_fields))
        query_str.append(')')
        query_str = os.linesep.join(query_str)
        ret = self._query(query_str, ignore_result=True, **kwargs)

Response: Set the table in the database.


Instruction:
Can you create a Python 3 function that
creates an index for the current record.

Response:
def _set_index(self, schema, name, fields, **index_options):
        """
        https://www.sqlite.org/lang_createindex.html
        """
        query_str = "CREATE {}INDEX IF NOT EXISTS '{}_{}' ON {} ({})".format(
            'UNIQUE ' if index_options.get('unique', False) else '',
            schema,
            name,
            self._normalize_table_name(schema),
            ', '.join((self._normalize_name(f) for f in fields))
        )

        return self._query(query_str, ignore_result=True, **index_options)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _get_indexes(self, schema, **kwargs):
        # http://www.sqlite.org/pragma.html#schema
        # http://www.mail-archive.com/sqlite-users@sqlite.org/msg22055.html
        # http://stackoverflow.com/questions/604939/
        ret = {}
        rs = self._query('PRAGMA index_list({})'.format(self._normalize_table_name(schema)), **kwargs)
        if rs:
            for r in rs:
                iname = r['name']
                ret.setdefault(iname, [])
                indexes = self._query('PRAGMA index_info({})'.format(r['name']), **kwargs)
                for idict in indexes:
                    ret[iname].append(idict['name'])

        return ret

Response: return all the indexes for the given schema


Instruction:
Write a Python 3 function that can
return all the fields for the given table

Response:
def _get_fields(self, table_name, **kwargs):
        """return all the fields for the given table"""
        ret = {}
        query_str = 'PRAGMA table_info({})'.format(self._normalize_table_name(table_name))
        fields = self._query(query_str, **kwargs)
        #pout.v([dict(d) for d in fields])

        query_str = 'PRAGMA foreign_key_list({})'.format(self._normalize_table_name(table_name))
        fks = {f["from"]: f for f in self._query(query_str, **kwargs)}
        #pout.v([dict(d) for d in fks.values()])

        pg_types = {
            "INTEGER": int,
            "BIGINT": long,
            "DOUBLE PRECISION": float,
            "FLOAT": float,
            "REAL": float,
            "NUMERIC": decimal.Decimal,
            "BOOLEAN": bool,
            "DATE": datetime.date,
            "TIMESTAMP": datetime.datetime,
            "CHARACTER": str,
            "VARCHAR": str,
            "TEXT": str,
            "BLOB": bytearray,
        }

        # the rows we can set: field_type, name, field_required, min_size, max_size,
        #   size, unique, pk, <foreign key info>
        # These keys will roughly correspond with schema.Field
        # TODO -- we could actually use "type" to get the size because SQLite returns
        # a value like VARCHAR[32]
        for row in fields:
            field = {
                "name": row["name"],
                "field_required": bool(row["notnull"]) or bool(row["pk"]),
                "pk": bool(row["pk"]),
            }

            for tname, ty in pg_types.items():
                if row["type"].startswith(tname):
                    field["field_type"] = ty
                    break

            if field["pk"] and field["field_type"] is int:
                # we compensate for SQLite internally setting pk to int
                field["field_type"] = long

            if row["name"] in fks:
                field["schema_table_name"] = fks[row["name"]]["table"]
                field["ref_table_name"] = fks[row["name"]]["table"]

            ret[field["name"]] = field

        return ret


Instruction:
How would you explain what the following Python 3 function does
def _normalize_date_SQL(self, field_name, field_kwargs, symbol):
        fstrs = []
        k_opts = {
            'day': "CAST(strftime('%d', {}) AS integer)",
            'hour': "CAST(strftime('%H', {}) AS integer)",
            'doy': "CAST(strftime('%j', {}) AS integer)", # day of year
            'julian_day': "strftime('%J', {})", # YYYY-MM-DD
            'month': "CAST(strftime('%m', {}) AS integer)",
            'minute': "CAST(strftime('%M', {}) AS integer)",
            'dow': "CAST(strftime('%w', {}) AS integer)", # day of week 0 = sunday
            'week': "CAST(strftime('%W', {}) AS integer)",
            'year': "CAST(strftime('%Y', {}) AS integer)"
        }

        for k, v in field_kwargs.items():
            fstrs.append([k_opts[k].format(self._normalize_name(field_name)), self.val_placeholder, v])

        return fstrs

Response:
allow extracting information from date
            http://www. sqlite. org / lang_datefunc. html


Instruction:
Can you generate the documentation for the following Python 3 function
def _normalize_sort_SQL(self, field_name, field_vals, sort_dir_str):
        fvi = None
        if sort_dir_str == 'ASC':
            fvi = (t for t in enumerate(field_vals))

        else:
            fvi = (t for t in enumerate(reversed(field_vals)))

        query_sort_str = ['  CASE {}'.format(self._normalize_name(field_name))]
        query_args = []
        for i, v in fvi:
            query_sort_str.append('    WHEN {} THEN {}'.format(self.val_placeholder, i))
            query_args.append(v)

        query_sort_str.append('  END')
        query_sort_str = "\n".join(query_sort_str)
        return query_sort_str, query_args

Response: This function returns a SQL sort string and a list of query arguments.


Instruction:
Create a Python 3 function to
register new calculations and meta data.

Response:
def register(self, new_calc, *args, **kwargs):
        """
        Register calculations and meta data.

        * ``dependencies`` - list of prerequisite calculations
        * ``always_calc`` - ``True`` if calculation ignores thresholds
        * ``frequency`` - frequency of calculation in intervals or units of time

        :param new_calc: register new calculation
        """
        kwargs.update(zip(self.meta_names, args))
        # dependencies should be a list of other calculations
        if isinstance(kwargs['dependencies'], basestring):
            kwargs['dependencies'] = [kwargs['dependencies']]
        # call super method, now meta can be passed as args or kwargs.
        super(CalcRegistry, self).register(new_calc, **kwargs)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def slits_to_ds9_reg(ds9reg, slits):

    # open output file and insert header

    ds9reg.write('# Region file format: DS9 version 4.1\n')
    ds9reg.write(
        'global color=green dashlist=8 3 width=1 font="helvetica 10 '
        'normal roman" select=1 highlite=1 dash=0 fixed=0 edit=1 '
        'move=1 delete=1 include=1 source=1\n')
    ds9reg.write('physical\n')

    for idx, slit in enumerate(slits, 1):
        xpos1, y2, xpos2, y2, xpos2, y1, xpos1, y1 = slit
        xc = 0.5 * (xpos1 + xpos2) + 1
        yc = 0.5 * (y1 + y2) + 1
        xd = (xpos2 - xpos1)
        yd = (y2 - y1)
        ds9reg.write('box({0},{1},{2},{3},0)\n'.format(xc, yc, xd, yd))
        ds9reg.write('# text({0},{1}) color=red text={{{2}}}\n'.format(xpos1 - 5, yc, idx))
        ds9reg.write('# text({0},{1}) color=red text={{{2}}}\n'.format(xpos2 + 5, yc, idx + EMIR_NBARS))

Response: Transform fiber traces to ds9 - region format.


Instruction:
Can you generate the documentation for the following Python 3 function
def id_maker(obj):
    dtfmt = '%Y%m%d-%H%M%S'
    return '%s-%s' % (obj.__class__.__name__, datetime.now().strftime(dtfmt))

Response: Makes an ID from the object s class name and the datetime now in ISO format.


Instruction:
Here you have a function in Python 3, explain what it does
def register(self, sim, *args, **kwargs):
        kwargs.update(zip(self.meta_names, args))
        # call super method, now meta can be passed as args or kwargs.
        super(SimRegistry, self).register(sim, **kwargs)

Response: register simulation and metadata.


Instruction:
Write a Python 3 function for
checking if data loaded for all sources in data layer.

Response:
def check_data(self, data):
        """
        Check if data loaded for all sources in data layer.

        :param data: data layer from model
        :type data: :class:`~simkit.core.layer.Data`
        :return: dictionary of data sources and objects or `None` if not loaded
        """
        data_objs = {
            data_src: data.objects.get(data_src) for data_src in data.layer
        }
        self._is_data_loaded = all(data_objs.values())
        return data_objs


Instruction:
Make a summary of the following Python 3 code
def initialize(self, calc_reg):
        self._isinitialized = True
        # TODO: if calculations are edited, loaded, added, etc. then reset
        self.calc_order = topological_sort(calc_reg.dependencies)

Response: Initializes the simulation by dependency.


Instruction:
Can you tell what is the following Python 3 function doing
def index_iterator(self):
        idx = 0  # index
        while idx < self.number_intervals:
            new_idx = yield idx
            idx += 1
            if new_idx:
                idx = new_idx - 1

Response: Generator that returns the index of the items in the index.


Instruction:
Can you write a function in Python 3 where it
starts the simulation from time zero.

Response:
def start(self, model, progress_hook=None):
        """
        Start the simulation from time zero.

        :param model: Model with layers and registries containing parameters
        :type: :class:`~simkit.core.models.Model`
        :param progress_hook: A function that receives either a string or a
            list containing the index followed by tuples of the data or outputs
            names and values specified by ``write_fields`` in the simfile.
        :type progress_hook: function

        The model registries should contain the following layer registries:
        * :class:`~simkit.core.data_sources.DataRegistry`,
        * :class:`~simkit.core.formulas.FormulaRegistry`,
        * :class:`~simkit.core.outputs.OutputRegistry`,
        * :class:`~simkit.core.calculation.CalcRegistry`
        """
        # check if data loaded
        data_objs = self.check_data(model.data)
        if not self.is_data_loaded:
            raise MissingDataError([ds for ds in data_objs if ds is None])
        # get layer registries
        data_reg = model.registries['data']
        formula_reg = model.registries['formulas']
        out_reg = model.registries['outputs']
        calc_reg = model.registries['calculations']
        # initialize
        if not self.isinitialized:
            self.initialize(calc_reg)
        # default progress hook
        if not progress_hook:
            progress_hook = functools.partial(
                sim_progress_hook, display_header=True
            )
        # start, resume or restart
        if self.ispaused:
            # if paused, then resume, do not resize outputs again.
            self._ispaused = False  # change pause state
            progress_hook('resume simulation')
        elif self.iscomplete:
            # if complete, then restart, do not resize outputs again.
            self._iscomplete = False  # change pause state
            progress_hook('restart simulation')
            self.idx_iter = self.index_iterator()
        else:
            # resize outputs
            # assumes that self.write_frequency is immutable
            # TODO: allow self.write_frequency to be changed
            # only resize outputs first time simulation is started
            # repeat output rows to self.write_frequency
            # put initial conditions of outputs last so it's copied when
            # idx == 0
            progress_hook('resize outputs')  # display progress
            for k in out_reg:
                if out_reg.isconstant[k]:
                    continue
                # repeat rows (axis=0)
                out_reg[k] = out_reg[k].repeat(self.write_frequency, 0)
                _initial_value = out_reg.initial_value[k]
                if not _initial_value:
                    continue
                if isinstance(_initial_value, basestring):
                    # initial value is from data registry
                    # assign in a scalar to a vector fills in the vector, yes!
                    out_reg[k][-1] = data_reg[_initial_value]
                else:
                    out_reg[k][-1] = _initial_value * out_reg[k].units
            progress_hook('start simulation')
        # check and/or make SimKit_Simulations and simulation ID folders
        mkdir_p(self.path)
        sim_id_path = os.path.join(self.path, self.ID)
        mkdir_p(sim_id_path)
        # header & units for save files
        data_fields = self.write_fields.get('data', [])  # any data fields
        out_fields = self.write_fields.get('outputs', [])  # any outputs fields
        save_header = tuple(data_fields + out_fields)  # concatenate fields
        # get units as strings from data & outputs
        data_units = [str(data_reg[f].dimensionality) for f in data_fields]
        out_units = [str(out_reg[f].dimensionality) for f in out_fields]
        save_units = tuple(data_units + out_units)  # concatenate units
        # string format for header & units
        save_str = ('%s' + ',%s' * (len(save_header) - 1)) + '\n'  # format
        save_header = (save_str * 2) % (save_header + save_units)  # header
        save_header = save_header[:-1]  # remove trailing new line
        # ===================
        # Static calculations
        # ===================
        progress_hook('static calcs')
        for calc in self.calc_order:
            if not calc_reg.is_dynamic[calc]:
                calc_reg.calculator[calc].calculate(
                    calc_reg[calc], formula_reg, data_reg, out_reg
                )
        # ====================
        # Dynamic calculations
        # ====================
        progress_hook('dynamic calcs')
        # TODO: assumes that interval size and indices are same, but should
        # interpolate for any size interval or indices
        for idx_tot in self.idx_iter:
            self.interval_idx = idx_tot  # update simulation interval counter
            idx = idx_tot % self.write_frequency
            # update properties
            for k, v in out_reg.isproperty.iteritems():
                # set properties from previous interval at night
                if v:
                    out_reg[k][idx] = out_reg[k][idx - 1]
            # night if any threshold exceeded
            if self.thresholds:
                night = not all(limits[0] < data_reg[data][idx] < limits[1] for
                                data, limits in self.thresholds.iteritems())
            else:
                night = None
            # daytime or always calculated outputs
            for calc in self.calc_order:
                # Determine if calculation is scheduled for this timestep
                # TODO: add ``start_at`` parameter combined with ``frequency``
                freq = calc_reg.frequency[calc]
                if not freq.dimensionality:
                    is_scheduled = (idx_tot % freq) == 0
                else:
                    # Frequency with units of time
                    is_scheduled = ((idx_tot * self.interval) % freq) == 0
                is_scheduled = (
                    is_scheduled and (not night or calc_reg.always_calc[calc])
                )
                if calc_reg.is_dynamic[calc] and is_scheduled:
                    calc_reg.calculator[calc].calculate(
                        calc_reg[calc], formula_reg, data_reg, out_reg,
                        timestep=self.interval, idx=idx
                    )
            # display progress
            if not (idx % self.display_frequency):
                progress_hook(self.format_progress(idx, data_reg, out_reg))
                # disp_head = False
            # create an index for the save file, 0 if not saving
            if not ((idx_tot + 1) % self.write_frequency):
                savenum = (idx_tot + 1) / self.write_frequency
            elif idx_tot == self.number_intervals - 1:
                # save file index should be integer!
                savenum = int(np.ceil((idx_tot + 1) /
                                      float(self.write_frequency)))
            else:
                savenum = 0  # not saving this iteration
            # save file to disk
            if savenum:
                savename = self.ID + '_' + str(savenum) + '.csv'  # filename
                savepath = os.path.join(sim_id_path, savename)  # path
                # create array of all data & outputs to save
                save_array = self.format_write(data_reg, out_reg, idx + 1)
                # save as csv using default format & turn comments off
                np.savetxt(savepath, save_array, delimiter=',',
                           header=save_header, comments='')
            try:
                cmd = self.cmd_queue.get_nowait()
            except Queue.Empty:
                continue
            if cmd == 'pause':
                self._ispaused = True
                return
        self._iscomplete = True


Instruction:
Can you create a Python 3 function that
pauses the simulation. How is this different from stopping it? Maintain info sufficient to restart simulation. Sets ``is_paused`` to True. Will this state allow analysis? changing parameters? What can you do with a paused simulation? Should be capable of saving paused simulation for loading/resuming later, that is the main usage. EG: someone else need computer, or power goes out, so on battery backup quickly pause simulation, and save. Is save automatic? Should there be a parameter for auto save changed?

Response:
def pause(self, progress_hook=None):
        """
        Pause the simulation. How is this different from stopping it? Maintain
        info sufficient to restart simulation. Sets ``is_paused`` to True.
        Will this state allow analysis? changing parameters? What can you do
        with a paused simulation?
        Should be capable of saving paused simulation for loading/resuming
        later, that is the main usage. EG: someone else need computer, or power
        goes out, so on battery backup quickly pause simulation, and save.
        Is save automatic? Should there be a parameter for auto save changed?
        """
        # default progress hook
        if progress_hook is None:
            progress_hook = sim_progress_hook
        progress_hook('simulation paused')
        self.cmd_queue.put('pause')
        self._ispaused = True


Instruction:
Write a Python 3 function for
saving ds9 region output info filename.

Response:
def save_ds9(output, filename):
    """Save ds9 region output info filename.

    Parameters
    ----------
    output : str
        String containing the full output to be exported as a ds9 region
        file.
    filename : str
        Output file name.

    """

    ds9_file = open(filename, 'wt')
    ds9_file.write(output)
    ds9_file.close()


Instruction:
Can you tell what is the following Python 3 function doing
def save_four_ds9(rectwv_coeff, debugplot=0):

    for limits, rectified, suffix in zip(
        ['frontiers', 'frontiers', 'boundaries', 'boundaries'],
        [False, True, False, True],
        ['rawimage', 'rectified', 'rawimage', 'rectified']
    ):
        output = rectwv_coeff_to_ds9(rectwv_coeff=rectwv_coeff,
                                     limits=limits,
                                     rectified=rectified)
        filename = 'ds9_' + limits + '_' + suffix + '.reg'
        if abs(debugplot) >= 10:
            print('>>> Saving: ', filename)
        save_ds9(output, filename)

Response: Save the 4 possible ds9 region files.


Instruction:
Here you have a function in Python 3, explain what it does
def rectwv_coeff_to_ds9(rectwv_coeff,
                        limits=None,
                        rectified=False,
                        numpix=100):
    """Generate ds9 region output with requested slitlet limits

    Parameters
    ----------
    rectwv_coeff : RectWaveCoeff instance
        Rectification and wavelength calibration coefficients for the
        particular CSU configuration.
    limits : str
        Region to be saved: the only two possibilities are 'boundaries'
        and 'frontiers'.
    rectified : bool
        If True, the regions correspond to the rectified image.
    numpix : int
        Number of points in which the X-range interval is subdivided
        in order to save each boundary as a connected set of line
        segments. This option is only relevant when rectified=False.

    Returns
    -------
    output : str
        String containing the full output to be exported as a ds9 region
        file.
    """

    # protections
    if limits not in ['boundaries', 'frontiers']:
        raise ValueError('Unexpect limits=' + str(limits))

    # retrieve relevant wavelength calibration parameters
    grism_name = rectwv_coeff.tags['grism']
    filter_name = rectwv_coeff.tags['filter']
    wv_parameters = set_wv_parameters(filter_name, grism_name)
    naxis1_enlarged = wv_parameters['naxis1_enlarged']
    crpix1_enlarged = wv_parameters['crpix1_enlarged']
    crval1_enlarged = wv_parameters['crval1_enlarged']
    cdelt1_enlarged = wv_parameters['cdelt1_enlarged']

    ds9_output = '# Region file format: DS9 version 4.1\n' \
                 'global color=green dashlist=2 4 width=2 ' \
                 'font="helvetica 10 normal roman" select=1 ' \
                 'highlite=1 dash=1 fixed=0 edit=1 ' \
                 'move=1 delete=1 include=1 source=1\nphysical\n#\n'

    ds9_output += '#\n# uuid (rectwv_coeff): {0}\n'.format(rectwv_coeff.uuid)
    ds9_output += \
        '# grism...............: {0}\n'.format(rectwv_coeff.tags['grism'])
    ds9_output += \
        '# filter..............: {0}\n'.format(rectwv_coeff.tags['filter'])

    for islitlet in range(1, EMIR_NBARS + 1):
        if islitlet not in rectwv_coeff.missing_slitlets:
            dumdict = rectwv_coeff.contents[islitlet - 1]
            if islitlet % 2 == 0:
                if limits == 'frontiers':
                    colorbox = '#0000ff'  # '#ff77ff'
                else:
                    colorbox = '#ff00ff'  # '#ff77ff'
            else:
                if limits == 'frontiers':
                    colorbox = '#0000ff'  # '#4444ff'
                else:
                    colorbox = '#00ffff'  # '#4444ff'

            ds9_output += '#\n# islitlet...........: {0}\n'.format(islitlet)
            ds9_output += '# csu_bar_slit_center: {0}\n'.format(
                dumdict['csu_bar_slit_center']
            )
            if rectified:
                crpix1_linear = 1.0
                crval1_linear = dumdict['crval1_linear']
                cdelt1_linear = dumdict['cdelt1_linear']
                if limits == 'frontiers':
                    ydum_lower = dumdict['y0_frontier_lower_expected']
                    ydum_upper = dumdict['y0_frontier_upper_expected']
                else:
                    ydum_lower = dumdict['y0_reference_lower_expected']
                    ydum_upper = dumdict['y0_reference_upper_expected']
                wave_ini = crval1_linear + \
                           (0.5 - crpix1_linear) * cdelt1_linear
                xdum_ini = (wave_ini - crval1_enlarged) / cdelt1_enlarged
                xdum_ini += crpix1_enlarged
                wave_end = crval1_linear + \
                           (EMIR_NAXIS1 + 0.5 - crpix1_linear) * cdelt1_linear
                xdum_end = (wave_end - crval1_enlarged) / cdelt1_enlarged
                xdum_end += crpix1_enlarged
                for ydum in [ydum_lower, ydum_upper]:
                    ds9_output += \
                        'line {0} {1} {2} {3}'.format(
                            xdum_ini, ydum,
                            xdum_end, ydum
                        )
                    ds9_output += ' # color={0}\n'.format(colorbox)
                # slitlet label
                ydum_label = (ydum_lower + ydum_upper) / 2.0
                xdum_label = EMIR_NAXIS1 / 2 + 0.5
                wave_center = crval1_linear + \
                              (xdum_label - crpix1_linear) * cdelt1_linear
                xdum_label = (wave_center - crval1_enlarged) / cdelt1_enlarged
                xdum_label += crpix1_enlarged
                ds9_output += 'text {0} {1} {{{2}}} # color={3} ' \
                              'font="helvetica 10 bold ' \
                              'roman"\n'.format(xdum_label, ydum_label,
                                                islitlet, colorbox)
            else:
                if limits == 'frontiers':
                    pol_lower = Polynomial(
                        dumdict['frontier']['poly_coef_lower']
                    )
                    pol_upper = Polynomial(
                        dumdict['frontier']['poly_coef_upper']
                    )
                else:
                    pol_lower = Polynomial(
                        dumdict['spectrail']['poly_coef_lower']
                    )
                    pol_upper = Polynomial(
                        dumdict['spectrail']['poly_coef_upper']
                    )
                xdum = np.linspace(1, EMIR_NAXIS1, num=numpix)
                ydum = pol_lower(xdum)
                for i in range(len(xdum) - 1):
                    ds9_output += \
                        'line {0} {1} {2} {3}'.format(
                            xdum[i], ydum[i],
                            xdum[i + 1], ydum[i + 1]
                        )
                    ds9_output += ' # color={0}\n'.format(colorbox)
                ydum = pol_upper(xdum)
                for i in range(len(xdum) - 1):
                    ds9_output += \
                        'line {0} {1} {2} {3}'.format(
                            xdum[i], ydum[i],
                            xdum[i + 1], ydum[i + 1]
                        )
                    ds9_output += ' # color={0}\n'.format(colorbox)
                # slitlet label
                xdum_label = EMIR_NAXIS1 / 2 + 0.5
                ydum_lower = pol_lower(xdum_label)
                ydum_upper = pol_upper(xdum_label)
                ydum_label = (ydum_lower + ydum_upper) / 2.0
                ds9_output += 'text {0} {1} {{{2}}} # color={3} ' \
                              'font="helvetica 10 bold ' \
                              'roman"\n'.format(xdum_label, ydum_label,
                                                islitlet, colorbox)

    return ds9_output

Response: Generate a DS9 region file from a RectWaveCoeff instance.


Instruction:
Can you write a function in Python 3 where it
saves expected location of arc OH airglow to ds9 region files.

Response:
def save_spectral_lines_ds9(rectwv_coeff, debugplot=0):
    """Save expected location of arc and OH airglow to ds9 region files.

    Parameters
    ----------
    rectwv_coeff : RectWaveCoeff instance
        Rectification and wavelength calibration coefficients for the
        particular CSU configuration.
    debugplot : int
            Debugging level for messages and plots. For details see
            'numina.array.display.pause_debugplot.py'.

    """

    for spectral_lines, rectified, suffix in zip(
        ['arc', 'arc', 'oh', 'oh'],
        [False, True, False, True],
        ['rawimage', 'rectified', 'rawimage', 'rectified']
    ):
        output = spectral_lines_to_ds9(rectwv_coeff=rectwv_coeff,
                                       spectral_lines=spectral_lines,
                                       rectified=rectified)
        filename = 'ds9_' + spectral_lines + '_' + suffix + '.reg'
        if abs(debugplot) >= 10:
            print('>>> Saving: ', filename)
        save_ds9(output, filename)