if do_sens:
    if std1dfile is None:
        msgs.error('You need either give a std1dfile to derive sensfunc')
    else:
        # run telluric.sensfunc_telluric to get the sensfile
        TelSens = telluric.sensfunc_telluric(std1dfile,
                                             telgridfile,
                                             sensfile,
                                             mask_abs_lines=True,
                                             debug=debug)

## Apply the sensfunc to all spectra (only sensfunc but not tellluric)
# TODO: change show=False to show=show
apply_sensfunc(fnames,
               sensfile,
               extinct_correct=False,
               tell_correct=False,
               debug=debug,
               show=show)

fnames_flux = [f.replace('.fits', '_flux.fits') for f in fnames]

## Let's coadd all the fluxed spectra
# you should get a coadded spectrum named as 'spec1d_stack_{:}.fits'.format(qsoname)
#                a straight merge of individual order stacked spectra named as 'spec1d_merge_{:}.fits'.format(qsoname)
#                a individual order stacked spectra (multi-extension) named as 'spec1d_order_{:}.fits'.format(qsoname)
# TODO: change the outfile to work with datapath. It's a hard coding on these names in coadd1d
wave_stack, flux_stack, ivar_stack, mask_stack = coadd1d.ech_combspec(
    fnames_flux,
    objids,
    sensfile=sensfile,
    ex_value='OPT',
def flux_coadd_telluric(spec1dfiles,
                        sensfile,
                        tell_function,
                        telloutfile,
                        outfile,
                        objids=None,
                        z_qso=None,
                        ex_value='OPT',
                        polyorder=3,
                        fit_region_min=[9200.0],
                        fit_region_max=[9700.0],
                        scale_method=None,
                        hand_scale=None,
                        const_weights=False,
                        wave_grid_min=None,
                        wave_grid_max=None,
                        mask_lyman_a=True,
                        do_flux=False,
                        do_stack=False,
                        do_tell=False,
                        use_exist_sens=True,
                        show=False,
                        debug=False):

    nfiles = len(spec1dfiles)

    if objids is None:
        objids = ['OBJ0001'] * nfiles
    elif len(objids) != nfiles:
        msgs.error(
            'The length of objids should be exactly the same as the number of spec1d files.'
        )
    #fnames = np.sort(fnames)

    ### Apply the sensfunc to all spectra (only sensfunc but not tellluric)
    if do_flux:
        apply_sensfunc(spec1dfiles,
                       sensfile,
                       extinct_correct=False,
                       tell_correct=False,
                       debug=debug,
                       show=show)
        # fnames_flux = [f.replace('.fits', '_flux.fits') for f in fnames]
    else:
        msgs.warn(
            'You skiped the fluxing step, make sure you have applied sensfunction to your 1D spectra.'
        )

    # The name of the final stacked 1d spectrum
    if len(outroot.split('.')) == 1:
        outroot = outroot + '.fits'
    elif outroot.split('.')[-1] != 'fits':
        outroot = outroot + '.fits'
    stackfile = os.path.join(sci_path, outroot)

    if do_stack:
        ## Let's coadd all the fluxed spectra
        # you should get a coadded spectrum named as '{:}_stack.fits'.format(qsoname)
        #                a straight merge of individual order stacked spectra named as '{:}_merge.fits'.format(qsoname)
        #                a individual order stacked spectra (multi-extension) named as '{:}_order.fits'.format(qsoname)
        if pypeline == 'Echelle':
            wave_stack, flux_stack, ivar_stack, mask_stack = coadd1d.ech_combspec(
                fnames,
                objids,
                show=show,
                sensfile=sensfile,
                ex_value=ex_value,
                outfile=stackfile,
                scale_method=scale_method,
                hand_scale=hand_scale,
                wave_grid_min=wave_grid_min,
                wave_grid_max=wave_grid_max,
                const_weights=const_weights,
                debug=debug)
        else:
            wave_stack, flux_stack, ivar_stack, mask_stack = coadd1d.multi_combspec(
                fnames,
                objids,
                show=show,
                ex_value=ex_value,
                outfile=stackfile,
                wave_grid_min=wave_grid_min,
                wave_grid_max=wave_grid_max,
                scale_method=scale_method,
                hand_scale=hand_scale,
                const_weights=const_weights,
                debug=debug,
                debug_scale=debug)
    elif os.path.exists(stackfile):
        msgs.info('Loading stacked 1d spectrum {:}'.format(stackfile))
    else:
        msgs.warn(
            'No stacked 1d spectrum was found. Please set do_stack=True!')

    ### Telluric correction
    if do_tell:
        apply_tell_from_file(z_qso,
                             stackfile,
                             tell_method=tell_method,
                             instrument=instrument,
                             telgridfile=telgridfile,
                             polyorder=polyorder,
                             fit_region_min=fit_region_min,
                             fit_region_max=fit_region_max,
                             mask_lyman_a=mask_lyman_a,
                             show=show,
                             debug=debug)
def flux_tell(sci_path,
              stdfile,
              spec1dfiles=None,
              std_path=None,
              fileroot=None,
              outroot=None,
              z_qso=None,
              tell_method='qso',
              instrument=None,
              star_type=None,
              star_mag=None,
              star_ra=None,
              star_dec=None,
              mask_abs_lines=True,
              sens_polyorder=8,
              objids=None,
              ex_value='OPT',
              polyorder=3,
              fit_region_min=[9200.0],
              fit_region_max=[9700.0],
              scale_method=None,
              hand_scale=None,
              const_weights=False,
              wave_grid_min=None,
              wave_grid_max=None,
              mask_lyman_a=True,
              do_sens=False,
              do_flux=False,
              do_stack=False,
              do_tell=False,
              use_exist_sens=True,
              show=False,
              debug=False):

    if std_path is None:
        std_path = sci_path
    if fileroot is None:
        fileroot = 'spec1d_flux_tell.fits'
    if outroot is None:
        outroot = fileroot

    std1dfile = os.path.join(std_path, stdfile)
    header = fits.getheader(std1dfile, 0)
    pypeline = header['PYPELINE']

    if spec1dfiles is None:
        scifiles_all = os.listdir(sci_path)
        spec1dfiles = []
        for i in range(len(scifiles_all)):
            if ('spec1d' in scifiles_all[i]) and (fileroot in scifiles_all[i]):
                spec1dfiles.append(scifiles_all[i])

    nfiles = len(spec1dfiles)
    fnames = []
    for ifile in range(nfiles):
        fnames.append(os.path.join(sci_path, spec1dfiles[ifile]))
    if objids is None:
        objids = ['OBJ0001'] * nfiles
    elif len(objids) != nfiles:
        msgs.error(
            'The length of objids should be exactly the same with the number of spec1d files.'
        )
    #fnames = np.sort(fnames)

    ### get sensfunc
    if (star_ra is None) and (star_dec is None) and (star_mag is None) and (
            star_type is None):
        star_ra, star_dec = header['RA'], header['DEC']

    if '.sens.fits' not in stdfile:
        sensfile = std1dfile.replace('.fits', '_sens.fits')
    telgridfile = None  # value it to None
    if do_sens:
        if os.path.exists(sensfile) and (use_exist_sens):
            msgs.warn(
                '{:} is already exists. Skip doing sensfunc.'.format(sensfile))
        else:
            sensfile, telgridfile = get_sens_from_file(
                std1dfile=std1dfile,
                instrument=instrument,
                star_type=star_type,
                star_mag=star_mag,
                star_ra=star_ra,
                star_dec=star_dec,
                sens_polyorder=sens_polyorder,
                mask_abs_lines=mask_abs_lines,
                show=show,
                debug=debug)
    if telgridfile is None:
        msgs.info('Loading sensfile {:}'.format(sensfile))

        if (instrument == 'GNIRS') or (instrument == 'NIRES'):
            telgridfile = os.path.join(
                basedir,
                'Dropbox/PypeIt_Redux/TelFit_MaunaKea_3100_26100_R20000.fits')
        elif (instrument == 'XSHOOTER_VIS') or (instrument == 'GMOS-S'):
            telgridfile = os.path.join(
                basedir,
                'Dropbox/PypeIt_Redux/XSHOOTER/TelFit_Paranal_VIS_4900_11100_R25000.fits'
            )
        elif instrument == 'XSHOOTER_NIR':
            telgridfile = os.path.join(
                basedir,
                'Dropbox/PypeIt_Redux/XSHOOTER/TelFit_Paranal_NIR_9800_25000_R25000.fits'
            )
        else:
            telgridfile = os.path.join(
                basedir,
                'Dropbox/PypeIt_Redux/TelFit_MaunaKea_3100_26100_R20000.fits')
            msgs.warn('No telluric grid is found. Using MaunaKea!')

    ### Apply the sensfunc to all spectra (only sensfunc but not tellluric)
    if do_flux:
        apply_sensfunc(fnames,
                       sensfile,
                       extinct_correct=False,
                       tell_correct=False,
                       debug=debug,
                       show=show)
        # fnames_flux = [f.replace('.fits', '_flux.fits') for f in fnames]
    else:
        msgs.warn(
            'You skiped the fluxing step, make sure you have applied sensfunction to your 1D spectra.'
        )

    # The name of the final stacked 1d spectrum
    if len(outroot.split('.')) == 1:
        outroot = outroot + '.fits'
    elif outroot.split('.')[-1] != 'fits':
        outroot = outroot + '.fits'
    stackfile = os.path.join(sci_path, outroot)

    if do_stack:
        ## Let's coadd all the fluxed spectra
        # you should get a coadded spectrum named as '{:}_stack.fits'.format(qsoname)
        #                a straight merge of individual order stacked spectra named as '{:}_merge.fits'.format(qsoname)
        #                a individual order stacked spectra (multi-extension) named as '{:}_order.fits'.format(qsoname)
        if pypeline == 'Echelle':
            wave_stack, flux_stack, ivar_stack, mask_stack = coadd1d.ech_combspec(
                fnames,
                objids,
                show=show,
                sensfile=sensfile,
                ex_value=ex_value,
                outfile=stackfile,
                scale_method=scale_method,
                hand_scale=hand_scale,
                wave_grid_min=wave_grid_min,
                wave_grid_max=wave_grid_max,
                const_weights=const_weights,
                debug=debug)
        else:
            wave_stack, flux_stack, ivar_stack, mask_stack = coadd1d.multi_combspec(
                fnames,
                objids,
                show=show,
                ex_value=ex_value,
                outfile=stackfile,
                wave_grid_min=wave_grid_min,
                wave_grid_max=wave_grid_max,
                scale_method=scale_method,
                hand_scale=hand_scale,
                const_weights=const_weights,
                debug=debug,
                debug_scale=debug)
    elif os.path.exists(stackfile):
        msgs.info('Loading stacked 1d spectrum {:}'.format(stackfile))
    else:
        msgs.warn(
            'No stacked 1d spectrum was found. Please set do_stack=True!')

    ### Telluric correction
    if do_tell:
        apply_tell_from_file(z_qso,
                             stackfile,
                             tell_method=tell_method,
                             instrument=instrument,
                             telgridfile=telgridfile,
                             polyorder=polyorder,
                             fit_region_min=fit_region_min,
                             fit_region_max=fit_region_max,
                             mask_lyman_a=mask_lyman_a,
                             show=show,
                             debug=debug)
if not os.path.exists(sensfile) or clobber:
    # Run sensfun_teluric to get the sensitivity function
    TelSens = telluric.sensfunc_telluric(std1dfile,
                                         telgridfile,
                                         sensfile,
                                         star_type=star_type,
                                         star_mag=Vmag,
                                         mask_abs_lines=True,
                                         debug=True)

## Apply the sensfunc to all spectra. This is flux calibration only, but not telluric correction.
spec1dfiles_flux = [f.replace('.fits', '_flux.fits') for f in spec1dfiles]
if not os.path.exists(spec1dfiles_flux[0]):
    apply_sensfunc(spec1dfiles,
                   sensfile,
                   extinct_correct=False,
                   tell_correct=False,
                   debug=False,
                   show=False)

# Now let's coadd the spectrum
spec1dfluxfile = os.path.join(mpia_path,
                              'spec1d_coadd_{:}.fits'.format(qsoname))
wave_stack, flux_stack, ivar_stack, mask_stack = coadd1d.ech_combspec(
    spec1dfiles_flux,
    objids,
    show=show,
    show_exp=True,
    sensfile=sensfile,
    ex_value='OPT',
    outfile=spec1dfluxfile,
    debug=debug)