Exemplo n.º 1
0
def source_plot(ax, hdu, j):

    telescope = telescopes.KeckTelescope()
    fobos_fratio = 3.
    fobos_platescale = telescope.platescale*fobos_fratio/telescope.fratio

    fiber_diameter_limits = numpy.array([48., 252.])
    ax.set_xlim(fiber_diameter_limits)
    ax.set_ylim([0.0, 6.])
    ax.minorticks_on()
    ax.tick_params(which='major', length=8, direction='in')
    ax.tick_params(which='minor', length=4, direction='in')
    ax.grid(True, which='major', color='0.9', linestyle=':')
    for i in range(4):
        ax.plot(hdu['DIAM'].data[i,j,:]*1000, hdu['TOTAL'].data[i,j,:],
                color='C{0}'.format(i), linestyle='-', zorder=2)
        ax.plot(hdu['DIAM'].data[i,j,:]*1000, hdu['SKYSUB'].data[i,j,:],
                color='C{0}'.format(i), linestyle='--', zorder=2)
        m = numpy.array([numpy.argmax(hdu['TOTAL'].data[i,j,:]),
                         numpy.argmax(hdu['SKYSUB'].data[i,j,:])])
        maxsnr = numpy.array([hdu['TOTAL'].data[i,j,m[0]], 
                              hdu['SKYSUB'].data[i,j,m[1]]])
        ax.scatter(hdu['DIAM'].data[i,j,m]*1000, maxsnr,
                   marker='.', color='C{0}'.format(i), lw=0, s=100, zorder=3)
    
    ax2 = ax.twiny()
    ax2.minorticks_on()
    ax2.tick_params(which='major', length=8, direction='in')
    ax2.tick_params(which='minor', length=4, direction='in')
    ax2.set_xlim(fiber_diameter_limits/fobos_platescale/1000)

    return ax, ax2
Exemplo n.º 2
0
def test(mag, seeing, on_sky_fiber_diameter, sersic=None, exptime=1.):
    telescope = telescopes.KeckTelescope()
    detector_noise_ratio = 0. #1/3.
    re, sersicn = (None,None) if sersic is None else sersic
    size = 5.0 if re is None else max(5.0, 8*re)
    sampling = 0.05 if re is None else min(0.05, re/20)    # arcsec/pixel
    return onsky_aperture_snr(telescope, mag, seeing, on_sky_fiber_diameter,
                              detector_noise_ratio=detector_noise_ratio, sampling=sampling,
                              size=size, re=re, sersicn=sersicn, exptime=exptime, quiet=True)
Exemplo n.º 3
0
def fiddles_data_table(seeing, exptime, airmass, dmag_sky, data_file):
    mag = numpy.linspace(15, 22, 15, dtype=float)[::-1]
    apf_snr_pix = numpy.zeros_like(mag)
    apf_snr = numpy.zeros_like(mag)
    apf_saturated = numpy.zeros_like(mag, dtype=bool)

    keck_snr_pix = numpy.zeros_like(mag)
    keck_snr = numpy.zeros_like(mag)
    keck_saturated = numpy.zeros_like(mag, dtype=bool)

    keck = telescopes.KeckTelescope()
    apf = telescopes.APFTelescope()

    for i in range(mag.size):
        apf_snr_pix[i], apf_snr[i], apf_saturated[i], sky_mag \
                    = fiddles_snr(mag[i], apf, seeing, exptime, airmass=airmass,
                                  dmag_sky=dmag_sky)
        keck_snr_pix[i], keck_snr[i], keck_saturated[i], sky_mag \
                    = fiddles_snr(mag[i], keck, seeing, exptime, airmass=airmass,
                                  dmag_sky=dmag_sky)

    numpy.savetxt(
        data_file,
        numpy.transpose([
            mag, apf_snr_pix, apf_snr,
            apf_saturated.astype(int), keck_snr_pix, keck_snr,
            keck_saturated.astype(int)
        ]),
        fmt=['%5.1f', '%14.7e', '%14.7e', '%2d', '%14.7e', '%14.7e', '%2d'],
        header='Sky surface brightness: {0:.2f}'.format(sky_mag) +
        'Exposure time: {0:.1f}\n'.format(exptime) +
        'Airmass: {0:.1f}\n'.format(airmass) +
        'Seeing: {0:.1f}\n'.format(seeing) +
        '{0:>3s} {1:^32} {2:^32}\n'.format('', 'APF', 'Keck') +
        '{0:>3s} {1:^32} {2:^32}\n'.format('', '-' * 32, '-' * 32) +
        '{0:>3s} {1:>14s} {2:>14s} {3:>2s} {4:>14s} {5:>14s} {6:>2s}'.format(
            'Mg', 'SNRp', 'SNRt', 'S', 'SNRp', 'SNRt', 'S'))
Exemplo n.º 4
0
def fiddles_realization_plot(plot_file=None):
    telescope = telescopes.KeckTelescope()
    on, off = fiddles_realization(19.,
                                  telescope,
                                  0.8,
                                  60,
                                  airmass=2.,
                                  dmag_sky=-3)

    vmin = -100
    vmax = 3500

    font = {'size': 10}
    rc('font', **font)

    w, h = pyplot.figaspect(1)
    fig = pyplot.figure(figsize=(1.5 * w, 1.5 * h))

    ax = fig.add_axes([0.07, 0.35, 0.3, 0.3])
    cax = fig.add_axes([0.07, 0.72, 0.2, 0.01])
    ax.minorticks_on()
    ax.tick_params(which='major',
                   length=6,
                   direction='in',
                   top=True,
                   right=True)
    ax.tick_params(which='minor',
                   length=3,
                   direction='in',
                   top=True,
                   right=True)
    #    ax.grid(True, which='major', color='0.9', zorder=0, linestyle='-')

    im = ax.imshow(on,
                   origin='lower',
                   interpolation='nearest',
                   vmin=vmin,
                   vmax=vmax)
    pyplot.colorbar(im, cax=cax, orientation='horizontal')
    cax.text(1.1,
             0.5,
             r'Counts (e$-$)',
             ha='left',
             va='center',
             transform=cax.transAxes)

    ax.text(-0.15,
            0.5,
            r'Y (pixels)',
            ha='center',
            va='center',
            rotation='vertical',
            transform=ax.transAxes)
    ax.text(0.5,
            -0.14,
            r'X (pixels)',
            ha='center',
            va='center',
            transform=ax.transAxes)
    ax.text(0.5,
            1.05,
            r'On Source',
            ha='center',
            va='center',
            transform=ax.transAxes)

    ax = fig.add_axes([0.37, 0.35, 0.3, 0.3])
    ax.minorticks_on()
    ax.tick_params(which='major',
                   length=6,
                   direction='in',
                   top=True,
                   right=True)
    ax.tick_params(which='minor',
                   length=3,
                   direction='in',
                   top=True,
                   right=True)
    #    ax.grid(True, which='major', color='0.9', zorder=0, linestyle='-')
    ax.yaxis.set_major_formatter(ticker.NullFormatter())

    ax.imshow(off,
              origin='lower',
              interpolation='nearest',
              vmin=vmin,
              vmax=vmax)

    ax.text(0.5,
            -0.14,
            r'X (pixels)',
            ha='center',
            va='center',
            transform=ax.transAxes)
    ax.text(0.5,
            1.05,
            r'Off Source',
            ha='center',
            va='center',
            transform=ax.transAxes)

    ax = fig.add_axes([0.67, 0.35, 0.3, 0.3])
    ax.minorticks_on()
    ax.tick_params(which='major',
                   length=6,
                   direction='in',
                   top=True,
                   right=True)
    ax.tick_params(which='minor',
                   length=3,
                   direction='in',
                   top=True,
                   right=True)
    #    ax.grid(True, which='major', color='0.9', zorder=0, linestyle='-')
    ax.yaxis.set_major_formatter(ticker.NullFormatter())

    ax.imshow(on - off,
              origin='lower',
              interpolation='nearest',
              vmin=vmin,
              vmax=vmax)

    ax.text(0.5,
            -0.14,
            r'X (pixels)',
            ha='center',
            va='center',
            transform=ax.transAxes)
    ax.text(0.5,
            1.05,
            r'On-Off',
            ha='center',
            va='center',
            transform=ax.transAxes)

    if plot_file is None:
        pyplot.show()
    else:
        fig.canvas.print_figure(plot_file, bbox_inches='tight')
    fig.clear()
    pyplot.close(fig)
Exemplo n.º 5
0
def main(args):

    t = time.perf_counter()

    # Constants:
    resolution = 3500.  # lambda/dlambda
    fiber_diameter = 0.8  # Arcsec
    rn = 2.  # Detector readnoise (e-)
    dark = 0.0  # Detector dark-current (e-/s)

    # Temporary numbers that assume a given spectrograph PSF and LSF.
    # Assume 3 pixels per spectral and spatial FWHM.
    spatial_fwhm = 3.0
    spectral_fwhm = 3.0

    mags = numpy.arange(args.mag[0], args.mag[1] + args.mag[2], args.mag[2])
    times = numpy.arange(args.time[0], args.time[1] + args.time[2],
                         args.time[2])

    # Get source spectrum in 1e-17 erg/s/cm^2/angstrom. Currently, the
    # source spectrum is assumed to be
    #   - normalized by the total integral of the source flux
    #   - independent of position within the source
    wave = get_wavelength_vector(args.wavelengths[0], args.wavelengths[1],
                                 args.wavelengths[2])
    spec = get_spectrum(wave, mags[0], resolution=resolution)

    # Get the source distribution.  If the source is uniform, onsky is None.
    onsky = None

    # Get the sky spectrum
    sky_spectrum = spectrum.MaunakeaSkySpectrum()

    # Overplot the source and sky spectrum
    #    ax = spec.plot()
    #    ax = sky_spectrum.plot(ax=ax, show=True)

    # Get the atmospheric throughput
    atmospheric_throughput = efficiency.AtmosphericThroughput(
        airmass=args.airmass)

    # Set the telescope. Defines the aperture area and throughput
    # (nominally 3 aluminum reflections for Keck)
    telescope = telescopes.KeckTelescope()

    # Define the observing aperture; fiber diameter is in arcseconds,
    # center is 0,0 to put the fiber on the target center. "resolution"
    # sets the resolution of the fiber rendering; it has nothing to do
    # with spatial or spectral resolution of the instrument
    fiber = aperture.FiberAperture(0, 0, fiber_diameter, resolution=100)

    # Get the spectrograph throughput (circa June 2018; TODO: needs to
    # be updated). Includes fibers + foreoptics + FRD + spectrograph +
    # detector QE (not sure about ADC). Because this is the total
    # throughput, define a generic efficiency object.
    thru_db = numpy.genfromtxt(
        os.path.join(os.environ['ENYO_DIR'], 'data/efficiency',
                     'fobos_throughput.db'))
    spectrograph_throughput = efficiency.Efficiency(thru_db[:, 1],
                                                    wave=thru_db[:, 0])

    # System efficiency combines the spectrograph and the telescope
    system_throughput = efficiency.SystemThroughput(
        wave=spec.wave,
        spectrograph=spectrograph_throughput,
        telescope=telescope.throughput)

    # Instantiate the detector; really just a container for the rn and
    # dark current for now. QE is included in fobos_throughput.db file,
    # so I set it to 1 here.
    det = detector.Detector(rn=rn, dark=dark, qe=1.0)

    # Extraction: makes simple assumptions about the detector PSF for
    # each fiber spectrum and mimics a "perfect" extraction, including
    # an assumption of no cross-talk between fibers. Ignore the
    # "spectral extraction".
    extraction = extract.Extraction(det,
                                    spatial_fwhm=spatial_fwhm,
                                    spatial_width=1.5 * spatial_fwhm,
                                    spectral_fwhm=spectral_fwhm,
                                    spectral_width=spectral_fwhm)

    snr_label = 'S/N per {0}'.format('R element' if args.snr_units ==
                                     'resolution' else args.snr_units)

    # SNR
    g = efficiency.FilterResponse()
    r = efficiency.FilterResponse(band='r')
    snr_g = numpy.empty((mags.size, times.size), dtype=float)
    snr_r = numpy.empty((mags.size, times.size), dtype=float)
    for i in range(mags.size):
        spec.rescale_magnitude(mags[i], band=g)
        for j in range(times.size):
            print('{0}/{1} ; {2}/{3}'.format(i + 1, mags.size, j + 1,
                                             times.size),
                  end='\r')
            # Perform the observation
            obs = Observation(telescope,
                              sky_spectrum,
                              fiber,
                              times[j],
                              det,
                              system_throughput=system_throughput,
                              atmospheric_throughput=atmospheric_throughput,
                              airmass=args.airmass,
                              onsky_source_distribution=onsky,
                              source_spectrum=spec,
                              extraction=extraction,
                              snr_units=args.snr_units)

            # Construct the S/N spectrum
            snr_spec = obs.snr(sky_sub=True)
            snr_g[i,
                  j] = numpy.sum(g(snr_spec.wave) * snr_spec.flux) / numpy.sum(
                      g(snr_spec.wave))
            snr_r[i,
                  j] = numpy.sum(r(snr_spec.wave) * snr_spec.flux) / numpy.sum(
                      r(snr_spec.wave))
    print('{0}/{1} ; {2}/{3}'.format(i + 1, mags.size, j + 1, times.size))

    extent = [
        args.time[0] - args.time[2] / 2, args.time[1] + args.time[2] / 2,
        args.mag[0] - args.mag[2] / 2, args.mag[1] + args.mag[2] / 2
    ]

    w, h = pyplot.figaspect(1)
    fig = pyplot.figure(figsize=(1.5 * w, 1.5 * h))
    ax = fig.add_axes([0.15, 0.2, 0.7, 0.7])
    img = ax.imshow(snr_g,
                    origin='lower',
                    interpolation='nearest',
                    extent=extent,
                    aspect='auto',
                    norm=colors.LogNorm(vmin=snr_g.min(), vmax=snr_g.max()))
    cax = fig.add_axes([0.86, 0.2, 0.02, 0.7])
    pyplot.colorbar(img, cax=cax)
    cax.text(4,
             0.5,
             snr_label,
             ha='center',
             va='center',
             transform=cax.transAxes,
             rotation='vertical')
    ax.text(0.5,
            -0.08,
            'Exposure Time [s]',
            ha='center',
            va='center',
            transform=ax.transAxes)
    ax.text(-0.12,
            0.5,
            r'Surface Brightness [AB mag/arcsec$^2$]',
            ha='center',
            va='center',
            transform=ax.transAxes,
            rotation='vertical')
    ax.text(0.5,
            1.03,
            r'$g$-band S/N',
            ha='center',
            va='center',
            transform=ax.transAxes,
            fontsize=12)
    pyplot.show()
Exemplo n.º 6
0
def main(args):

    if args.sky_err < 0 or args.sky_err > 1:
        raise ValueError(
            '--sky_err option must provide a value between 0 and 1.')

    t = time.perf_counter()

    # Constants:
    resolution = 3500.  # lambda/dlambda
    fiber_diameter = 0.8  # Arcsec
    rn = 2.  # Detector readnoise (e-)
    dark = 0.0  # Detector dark-current (e-/s)

    # Temporary numbers that assume a given spectrograph PSF and LSF.
    # Assume 3 pixels per spectral and spatial FWHM.
    spatial_fwhm = args.spot_fwhm
    spectral_fwhm = args.spot_fwhm

    # Get source spectrum in 1e-17 erg/s/cm^2/angstrom. Currently, the
    # source spectrum is assumed to be
    #   - normalized by the total integral of the source flux
    #   - independent of position within the source
    dw = 1 / spectral_fwhm / resolution / numpy.log(10)
    wavelengths = [3100, 10000, dw]
    wave = get_wavelength_vector(wavelengths[0], wavelengths[1],
                                 wavelengths[2])
    emline_db = None if args.emline is None else read_emission_line_database(
        args.emline)
    spec = get_spectrum(wave,
                        args.mag,
                        mag_band=args.mag_band,
                        mag_system=args.mag_system,
                        spec_file=args.spec_file,
                        spec_wave=args.spec_wave,
                        spec_wave_units=args.spec_wave_units,
                        spec_flux=args.spec_flux,
                        spec_flux_units=args.spec_flux_units,
                        spec_res_indx=args.spec_res_indx,
                        spec_res_value=args.spec_res_value,
                        spec_table=args.spec_table,
                        emline_db=emline_db,
                        redshift=args.redshift,
                        resolution=resolution)

    # Get the source distribution.  If the source is uniform, onsky is None.
    onsky = get_source_distribution(args.fwhm, args.uniform, args.sersic)

    # Show the rendered source
    #    if onsky is not None:
    #        pyplot.imshow(onsky.data, origin='lower', interpolation='nearest')
    #        pyplot.show()

    # Get the sky spectrum
    sky_spectrum = get_sky_spectrum(args.sky_mag,
                                    mag_band=args.sky_mag_band,
                                    mag_system=args.sky_mag_system)

    # Overplot the source and sky spectrum
    #    ax = spec.plot()
    #    ax = sky_spectrum.plot(ax=ax, show=True)

    # Get the atmospheric throughput
    atmospheric_throughput = efficiency.AtmosphericThroughput(
        airmass=args.airmass)

    # Set the telescope. Defines the aperture area and throughput
    # (nominally 3 aluminum reflections for Keck)
    telescope = telescopes.KeckTelescope()

    # Define the observing aperture; fiber diameter is in arcseconds,
    # center is 0,0 to put the fiber on the target center. "resolution"
    # sets the resolution of the fiber rendering; it has nothing to do
    # with spatial or spectral resolution of the instrument
    fiber = aperture.FiberAperture(0, 0, fiber_diameter, resolution=100)

    # Get the spectrograph throughput (circa June 2018; TODO: needs to
    # be updated). Includes fibers + foreoptics + FRD + spectrograph +
    # detector QE (not sure about ADC). Because this is the total
    # throughput, define a generic efficiency object.
    thru_db = numpy.genfromtxt(
        os.path.join(os.environ['ENYO_DIR'], 'data/efficiency',
                     'fobos_throughput.db'))
    spectrograph_throughput = efficiency.Efficiency(thru_db[:, 1],
                                                    wave=thru_db[:, 0])

    # System efficiency combines the spectrograph and the telescope
    system_throughput = efficiency.SystemThroughput(
        wave=spec.wave,
        spectrograph=spectrograph_throughput,
        telescope=telescope.throughput)

    # Instantiate the detector; really just a container for the rn and
    # dark current for now. QE is included in fobos_throughput.db file,
    # so I set it to 1 here.
    det = detector.Detector(rn=rn, dark=dark, qe=1.0)

    # Extraction: makes simple assumptions about the detector PSF for
    # each fiber spectrum and mimics a "perfect" extraction, including
    # an assumption of no cross-talk between fibers. Ignore the
    # "spectral extraction".
    extraction = extract.Extraction(det,
                                    spatial_fwhm=spatial_fwhm,
                                    spatial_width=1.5 * spatial_fwhm,
                                    spectral_fwhm=spectral_fwhm,
                                    spectral_width=spectral_fwhm)

    # Perform the observation
    obs = Observation(telescope,
                      sky_spectrum,
                      fiber,
                      args.time,
                      det,
                      system_throughput=system_throughput,
                      atmospheric_throughput=atmospheric_throughput,
                      airmass=args.airmass,
                      onsky_source_distribution=onsky,
                      source_spectrum=spec,
                      extraction=extraction,
                      snr_units=args.snr_units)

    # Construct the S/N spectrum
    snr = obs.snr(sky_sub=True, sky_err=args.sky_err)
    if args.ipython:
        embed()

    snr_label = 'S/N per {0}'.format('R element' if args.snr_units ==
                                     'resolution' else args.snr_units)

    if args.plot:
        w, h = pyplot.figaspect(1)
        fig = pyplot.figure(figsize=(1.5 * w, 1.5 * h))

        ax = fig.add_axes([0.1, 0.5, 0.8, 0.4])
        ax.set_xlim([wave[0], wave[-1]])
        ax.minorticks_on()
        ax.tick_params(which='major',
                       length=8,
                       direction='in',
                       top=True,
                       right=True)
        ax.tick_params(which='minor',
                       length=4,
                       direction='in',
                       top=True,
                       right=True)
        ax.grid(True, which='major', color='0.8', zorder=0, linestyle='-')
        ax.xaxis.set_major_formatter(ticker.NullFormatter())
        ax.set_yscale('log')

        ax = spec.plot(ax=ax, label='Object')
        ax = sky_spectrum.plot(ax=ax, label='Sky')
        ax.legend()
        ax.text(-0.1,
                0.5,
                r'Flux [10$^{-17}$ erg/s/cm$^2$/${\rm \AA}$]',
                ha='center',
                va='center',
                transform=ax.transAxes,
                rotation='vertical')

        ax = fig.add_axes([0.1, 0.1, 0.8, 0.4])
        ax.set_xlim([wave[0], wave[-1]])
        ax.minorticks_on()
        ax.tick_params(which='major',
                       length=8,
                       direction='in',
                       top=True,
                       right=True)
        ax.tick_params(which='minor',
                       length=4,
                       direction='in',
                       top=True,
                       right=True)
        ax.grid(True, which='major', color='0.8', zorder=0, linestyle='-')

        ax = snr.plot(ax=ax)

        ax.text(0.5,
                -0.1,
                r'Wavelength [${\rm \AA}$]',
                ha='center',
                va='center',
                transform=ax.transAxes)
        ax.text(-0.1,
                0.5,
                snr_label,
                ha='center',
                va='center',
                transform=ax.transAxes,
                rotation='vertical')

        pyplot.show()

    # Report
    g = efficiency.FilterResponse(band='g')
    r = efficiency.FilterResponse(band='r')
    iband = efficiency.FilterResponse(band='i')
    print('-' * 70)
    print('{0:^70}'.format('FOBOS S/N Calculation (v0.2)'))
    print('-' * 70)
    print('Compute time: {0} seconds'.format(time.perf_counter() - t))
    print('Object g- and r-band AB magnitude: {0:.1f} {1:.1f}'.format(
        spec.magnitude(band=g), spec.magnitude(band=r)))
    print('Sky g- and r-band AB surface brightness: {0:.1f} {1:.1f}'.format(
        sky_spectrum.magnitude(band=g), sky_spectrum.magnitude(band=r)))
    print('Exposure time: {0:.1f} (s)'.format(args.time))
    if not args.uniform:
        print('Aperture Loss: {0:.1f}%'.format(
            (1 - obs.aperture_factor) * 100))
    print('Extraction Loss: {0:.1f}%'.format(
        (1 - obs.extraction.spatial_efficiency) * 100))
    print('Median {0}: {1:.1f}'.format(snr_label, numpy.median(snr.flux)))
    print('g-band weighted mean {0} {1:.1f}'.format(
        snr_label,
        numpy.sum(g(snr.wave) * snr.flux) / numpy.sum(g(snr.wave))))
    print('r-band weighted mean {0} {1:.1f}'.format(
        snr_label,
        numpy.sum(r(snr.wave) * snr.flux) / numpy.sum(r(snr.wave))))
    print('i-band weighted mean {0} {1:.1f}'.format(
        snr_label,
        numpy.sum(iband(snr.wave) * snr.flux) / numpy.sum(iband(snr.wave))))
Exemplo n.º 7
0
def build_data(mag, ofile):

#    dmag_sky = None     # Dark time
#
#    dmag_sky = -3.0     # Bright time...

    seeing = [0.4, 0.6, 0.8, 1.0]
    sersic = [None, (0.1,1), (0.1,4), (0.2,1), (0.2,4), (0.4,1), (0.4,4), (0.8,1), (0.8,4)]
#    seeing = [0.4, 0.6]
#    sersic = [None]

    telescope = telescopes.KeckTelescope()
    dmag_sky = None
    fobos_fratio = 3.
    detector_noise_ratio = 0. #1/3.

    fiber_diameter = numpy.linspace(0.05, 0.25, 41)
    fobos_platescale = telescope.platescale*fobos_fratio/telescope.fratio

    outshape = (len(seeing), len(sersic), len(fiber_diameter))

    atmseeing = numpy.zeros(outshape, dtype=float)
    profile = numpy.zeros(outshape, dtype=int)
    fibdiam = numpy.zeros(outshape, dtype=float)
    total_snr = numpy.zeros(outshape, dtype=float)
    skysub_snr = numpy.zeros(outshape, dtype=float)

    for i in range(len(seeing)):
        atmseeing[i,:,:] = seeing[i]
        for j in range(len(sersic)):
            print('Seeing {0}/{1}'.format(i+1, len(seeing)))
            print('Profile {0}/{1}'.format(j+1, len(sersic)))

            profile[i,j,:] = j

            if sersic[j] is None:
                re = None
                sersicn = None
            else:
                re, sersicn = sersic[j]

            size = 5.0 if re is None else max(5.0, 8*re)
            sampling = 0.05 if re is None else min(0.05, re/20)    # arcsec/pixel

            for k in range(len(fiber_diameter)):
                fibdiam[i,j,k] = fiber_diameter[k]
                print('Calculating {0}/{1}'.format(k+1, fiber_diameter.size), end='\r')
                total_snr[i,j,k], skysub_snr[i,j,k] = \
                    aperture_snr(telescope, mag, seeing[i], fiber_diameter[k], dmag_sky=dmag_sky,
                                 fobos_fratio=fobos_fratio,
                                 detector_noise_ratio=detector_noise_ratio, sampling=sampling,
                                 size=size, re=re, sersicn=sersicn, quiet=True)
            print('Calculating {0}/{0}'.format(fiber_diameter.size))

    fits.HDUList([ fits.PrimaryHDU(),
                   fits.ImageHDU(data=atmseeing, name='SEEING'),
                   fits.ImageHDU(data=profile, name='PROF'),
                   fits.ImageHDU(data=fibdiam, name='DIAM'),
                   fits.ImageHDU(data=total_snr, name='TOTAL'),
                   fits.ImageHDU(data=skysub_snr, name='SKYSUB')
                 ]).writeto(ofile, overwrite=True)
                   
    return

    i = numpy.argmax(total_snr)
    print('Max total: {0:.3f} {1:.3f}'.format(fiber_diameter[i], total_snr[i]))
    i = numpy.argmax(skysub_snr)
    print('Max skysub: {0:.3f} {1:.3f}'.format(fiber_diameter[i], skysub_snr[i]))

    print('Calculating {0}/{0}'.format(fiber_diameter.size))
    pyplot.plot(fiber_diameter*1000, total_snr)
    pyplot.plot(fiber_diameter*1000, skysub_snr)
    pyplot.xlabel('Fiber Diameter (micron)')
    pyplot.ylabel(r'S/N [(photons/s) / $\sqrt{{\rm photons}^2/{\rm s}^2}$]')
    pyplot.show()