Beispiel #1
0
def median_spectrum(redshift, wave_grid, flux_rms, flux_std):

    medianSpec = spectrum()
    medianSpec.z = redshift
    medianSpec.npix = wave_grid.size
    medianSpec.wave = wave_grid

    medianSpec.flux = flux_rms['BOSS']
    medianSpec.flux_error = flux_std['BOSS']
    medianSpec.__fit_powerlaw__(type='BOSS')
    medianSpec.alpha_BOSS = medianSpec.alpha

    medianSpec.flux_corr = flux_rms['CORR']
    medianSpec.flux_error = flux_std['CORR']
    medianSpec.__fit_powerlaw__(type='CORR')
    medianSpec.alpha_CORR = medianSpec.alpha

    medianSpec.flux_corr = flux_rms['MARG']
    medianSpec.flux_error = flux_std['MARG']
    medianSpec.__fit_powerlaw__(type='CORR')
    medianSpec.alpha_MARG = medianSpec.alpha

    print '{0:>45s}'.format('SPECTRAL INDEX')
    print '{0:>33s} '.format('SI_medspec')

    print '{0:>20s} {1:15.12f}'.format('UNCORRECTED:', medianSpec.alpha_BOSS)
    print '{0:>20s} {1:15.12f}'.format('CORRECTED (Ours):',
                                       medianSpec.alpha_CORR)
    print '{0:>20s} {1:15.12f}'.format('CORRECTED (Margala):',
                                       medianSpec.alpha_MARG)

    return medianSpec
def main():
    # ======================= SETTINGS =======================
    settings = program_settings()
    settings.plot = True
    settings.smoothness = 5
    settings.resample = True
    settings.z_min = 0
    settings.z_max = 4
    settings.z_delta = 0.1
    # ======================= PARSER =======================
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument(
        '--spec-dir',
        type=str,
        default=None,
        help='full path to the directory containing the FITS files, required')
    args = parser.parse_args()
    # ======================= FILES =======================
    # from the input argument, fetch file names
    if args.spec_dir:
        spectral_list = return_spectral_list(args.spec_dir)
        numspec = len(spectral_list[0])
        uncorrected_files = spectral_list[0]
        corrected_files = spectral_list[1]
        corrected_files_m = spectral_list[2]
        # list that saves the number of files in each subfolder
        numfiles = [
            len(uncorrected_files),
            len(corrected_files),
            len(corrected_files_m)
        ]
        labels = []
        dir_basename = os.path.dirname(args.spec_dir)
        thingid = dir_basename.split('/')[7]
        # read the data from the uncorrected FITS files
        for fileList in spectral_list:
            ids = []
            for file in fileList:
                spec_basename = os.path.basename(file).split('.fits')[0]
                plate, mjd, fiberid = [
                    int(field) for field in os.path.splitext(spec_basename)
                    [0].split('-')[1:]
                ]
                ids.append('%04d-%5d-%04d' % (plate, mjd, fiberid))
            labels.append(ids)
    #data, header = fitsio.read(file,ext=0,header=True)
    # ======================= ======================== ======================
    flux_boss_list = []
    flux_corr_list = []
    flux_marg_list = []
    # ======================= UNIVERSAL WAVELENGTH GRID =======================
    loglam_grid = np.arange(start=3.55, stop=4.02, step=0.0001)
    wave_grid = np.power(10, loglam_grid)
    wave_npix = wave_grid.size
    wave_shape = wave_grid.shape

    row = np.dtype([('BOSS', 'd8', 1), ('CORR', 'd8', 1), ('MARG', 'd8', 1)])
    si_data = np.zeros(shape=(max(numfiles)), dtype=row)
    pl_flux = np.zeros(shape=(max(numfiles), wave_npix), dtype=row)
    fl_data = np.zeros(shape=(max(numfiles), wave_npix), dtype=row)
    print pl_flux[0].size
    # ======================= CALCULATIONS =======================
    for i in xrange(len(spectral_list)):
        for j, file in enumerate(spectral_list[i]):
            # ======================= READ SPECTRA =======================
            spec = spectrum()
            spec_dirname = os.path.dirname(file)
            spec_basename = os.path.basename(file)
            if 'corr' not in spec_basename:
                spec.__read_BOSS__(file)
            elif 'corr' in spec_basename:
                spec.__read_CORR__(file)

            minwav = spec.wave.min()
            maxwav = spec.wave.max()
            index_start = np.argmin(abs(wave_grid - minwav))
            index_stop = np.argmin(abs(wave_grid - maxwav))
            newpix = index_stop - index_start

            # ======================= GET SPECTRAL INDEX =======================
            if 'corr' not in spec_basename:
                spec.__fit_powerlaw__(type='BOSS')
                flux_old = spec.flux
                si_data[j]['BOSS'] = spec.alpha
                fl_data[j]['BOSS'][index_start:index_stop] = congrid.rebin_1d(
                    spec.flux, newpix)
                pl_flux[j]['BOSS'][index_start:index_stop] = congrid.rebin_1d(
                    spec.powerlaw,
                    newpix)  #10.0**(spec.delta + spec.beta*loglam_grid)
            if 'corr' in spec_basename:
                spec.__fit_powerlaw__(type='CORR')
                flux_old = spec.flux_corr
                if 'margala' not in spec_dirname:
                    si_data[j]['CORR'] = spec.alpha
                    fl_data[j]['CORR'][
                        index_start:index_stop] = congrid.rebin_1d(
                            spec.flux_corr, newpix)
                    pl_flux[j]['CORR'][
                        index_start:index_stop] = congrid.rebin_1d(
                            spec.powerlaw, newpix)
                elif 'margala' in spec_dirname:
                    si_data[j]['MARG'] = spec.alpha
                    fl_data[j]['MARG'][
                        index_start:index_stop] = congrid.rebin_1d(
                            spec.flux_corr, newpix)
                    pl_flux[j]['MARG'][
                        index_start:index_stop] = congrid.rebin_1d(
                            spec.powerlaw, newpix)
    ra = spec.ra
    dec = spec.dec
    z = spec.z
    del (spec)

    print np.median(si_data['BOSS']), np.std(si_data['BOSS'])
    print np.median(si_data['CORR']), np.std(si_data['CORR'])
    print np.median(si_data['MARG']), np.std(si_data['MARG'])
def main():
    np.set_printoptions(threshold=6000)
    # PARSER
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument(
        '--tpcorr',
        type=str,
        default=
        '/Volumes/T2TB/Isotropy/spectra/BOSScorrections/tpcorr-0.1/tpcorr.hdf5',
        help='Throughput correction filename, required')
    parser.add_argument(
        '--spec-dir',
        type=str,
        default=None,
        help='Path to directory containing individual spec files')
    parser.add_argument(
        '--all',
        action='store_true',
        help=
        'Save corrected spectra for all available objects of the given data sample'
    )
    parser.add_argument('--data',
                        choices=['QSO', 'FQSO', 'STAR'],
                        nargs=1,
                        type=str,
                        default='QSO',
                        help='Object type of the chosen spectrum')
    parser.add_argument(
        '--nobalmer',
        action='store_true',
        default=True,
        help=
        'Balmer corrections flag. If the flag is true, no Balmer corrections are applied.'
    )
    args = parser.parse_args()

    # data sample name
    sample = args.data[0]
    # MARGALA CORRECTION FILE
    tpcorr = h5py.File(args.tpcorr, 'r')
    tpcorr_wave = tpcorr['wave'].value
    # BALMER CORRECTION FILE
    if args.nobalmer == True:
        resid_corr = None
    elif args.nobalmer == False:
        resid_corr = read_resid_corr(
            '/Volumes/T2TB/Isotropy/PySDSS/residcorr_v5_4_45.dat')
    print resid_corr

    # Parse arguments: extract plate, mjd, fiberid as integers and the spec filename
    ids = []
    sid_tot = []
    if args.spec_dir:
        spectral_list = return_spectral_list(args.spec_dir)
        uncorrected_files = spectral_list[0]
        total_files = uncorrected_files
        for file in uncorrected_files:
            spec_basename = os.path.basename(file).split('.fits')[0]
            plate, mjd, fiberid = [
                int(field)
                for field in os.path.splitext(spec_basename)[0].split('-')[1:]
            ]
            ids.append((plate, mjd, fiberid))
            sid_tot.append('%04d%5d%04d' % (plate, mjd, fiberid))
    dtypedict = {'QSO': 'QUASARS', 'FQSO': 'FAILED QUASARS', 'STAR': 'STARS'}
    if args.all:
        print "CORRECTING ALL AVAILABLE SPECTRA OF {data}".format(
            data=dtypedict[sample])
        PathToSpectra = os.path.join(
            "/Volumes/T2TB/Isotropy/spectra/SDSS_DR12", sample)
        total_files = glob(os.path.join(PathToSpectra, "*.fits"))
        print "Spectra available: {0:8d}".format(len(total_files))
        for file in total_files:
            spec_basename = os.path.basename(file).split('.fits')[0]
            plate, mjd, fiberid = [
                int(field)
                for field in os.path.splitext(spec_basename)[0].split('-')[1:]
            ]
            ids.append((plate, mjd, fiberid))
            sid_tot.append('%04d%5d%04d' % (plate, mjd, fiberid))
    #else:
    #    parser.error('Must specify either a spec file using the --spec-file option or path to directory containing spec files and a target.')
    #sid_tot = np.array(sid_tot)
    sid_tot_array = np.array(sid_tot)
    sid_tot = set(sid_tot)

    if args.all:
        if args.nobalmer == False:
            dirpath = os.path.join(
                '/Volumes/T2TB/Isotropy/spectra/SDSS_DR12',
                '{data}_{name}'.format(data=sample, name='Margala'))
        elif args.nobalmer == True:
            dirpath = os.path.join(
                '/Volumes/T2TB/Isotropy/spectra/SDSS_DR12',
                '{data}_{name}_nobalmer'.format(data=sample, name='Margala'))
    else:
        dirpath = os.path.join(os.path.normpath(args.spec_dir), 'corrected',
                               'margala')
    # remove already corrected spectra from the list
    corrected_files = glob(os.path.join(dirpath, "*.fits"))
    print "Spectra previously corrected: {0:8d}".format(len(corrected_files))
    sid_corr = []
    for file in corrected_files:
        spec_basename = os.path.basename(file).split('.fits')[0]
        plate, mjd, fiberid = [
            int(field)
            for field in os.path.splitext(spec_basename)[0].split('-')[1:]
        ]
        sid_corr.append('%04d%5d%04d' % (plate, mjd, fiberid))
    sid_corr = set(sid_corr)
    sid_unc = sid_tot.difference(sid_corr)
    uncorrected_files = []
    for i, file in enumerate(total_files):
        if sid_tot_array[i] in sid_unc:
            uncorrected_files.append(file)

    print "Spectra to be corrected:     {0:8d}".format(len(uncorrected_files))
    file_array = np.array(uncorrected_files)
    for file in uncorrected_files:
        print file
        HDU = fitsio.FITS(file)
        h = HDU[0].read_header()
        flux = HDU[1]['flux'][:]
        ivar = HDU[1]['ivar'][:]
        wavelength = np.power(10, HDU[1]['loglam'][:])
        ra = HDU[2]['ra'][0][0]
        dec = HDU[2]['dec'][0][0]
        z = HDU[2]['z'][0][0]
        HDU.close()

        plate, mjd, fiberid = ids[np.argwhere(file_array == file)[0][0]]
        # Read the target's throughput correction vector
        tpcorr_key = '%s/%s/%s' % (plate, mjd, fiberid)
        try:
            correction = tpcorr[tpcorr_key].value
        except:
            print "No data on object found"
            continue
        # Create an interpolated correction function
        correction_interp = interp1d(tpcorr_wave, correction, kind='linear')

        # Sample the interpolated correction using the observation's wavelength grid
        resampled_correction = correction_interp(wavelength)

        # Apply the correction to the observed flux and ivar

        # Save the data into a fits file
        spec = spectrum()

        spec.plateid = plate
        spec.mjd = mjd
        spec.fiberid = fiberid
        spec.ra = ra
        spec.dec = dec
        spec.z = z
        spec.beginwl = h['COEFF0']

        spec.npix = np.size(wavelength)
        spec.wave = wavelength
        spec.flux = flux
        spec.ivar = ivar
        spec.flux_error = np.sqrt(1. / ivar)
        apply_resid_corr(spec, resid_corr)

        corrected_flux = spec.flux * resampled_correction
        corrected_ivar = spec.ivar / resampled_correction**2

        spec.flux_corr = corrected_flux
        spec.flux_error = np.sqrt(1. / corrected_ivar)
        spec.corr = resampled_correction

        spec.basename = os.path.basename(file)
        spec.dirname = os.path.dirname(file)

        spec.__save_fitsio__(dirpath=dirpath)
        del (spec)

    tpcorr.close()
def main(args):
    # files
    pathToFile = args.list
    # read Balmer corrections
    from SDSSmodules.SDSSfiles import read_resid_corr
    resid_corr = read_resid_corr(
        '/Volumes/T2TB/Isotropy/PySDSS/residcorr_v5_4_45.dat')
    objects = []
    with open(pathToFile, 'r') as file:
        for line in file:
            plate, mjd, fiber = [
                field for field in line.rstrip('\n').split(',')
            ]
            objects.append((plate, mjd, fiber))
    k = 0
    for object in objects:
        # define a spectrum instance:
        spec = spectrum()
        # read plate, mjd, fiber:
        plate, mjd, fiber = [int(value) for value in object]
        spec.plate = plate
        spec.MJD = mjd
        spec.fiberid = fiber
        spec.dirname = savedir
        spec.basename = 'spec-{plate:4d}-{mjd:5d}-{fiber:04d}.fits'.format(
            plate=plate, mjd=mjd, fiber=fiber)
        i = fiber - 1  #systematic offset
        # Pick your plate/mjd and read the data:
        spfile = '{top}{plate}/spPlate-{plate}-{mjd}.fits'.format(top=topdir,
                                                                  plate=plate,
                                                                  mjd=mjd)
        zbfile = '{top}{plate}/v5_7_0/spZbest-{plate}-{mjd}.fits'.format(
            top=topdir, plate=plate, mjd=mjd)
        zafile = '{top}{plate}/v5_7_0/spZall-{plate}-{mjd}.fits'.format(
            top=topdir, plate=plate, mjd=mjd)

        hdulist = pf.open(spfile)
        c0 = hdulist[0].header['coeff0']
        c1 = hdulist[0].header['coeff1']
        npix = hdulist[0].header['naxis1']
        wave = 10.**(c0 + c1 * n.arange(npix))
        spec.beginwl = c0
        spec.npix = npix
        spec.wave = wave
        spec.lambda_eff = hdulist[5].data['LAMBDA_EFF'][i]

        # Following commented-out bit was needed for some of the early redux:
        #bzero = hdulist[0].header['bzero']
        bunit = hdulist[0].header['bunit']
        flux = hdulist[0].data
        ivar = hdulist[1].data
        # put Balmer _uncorrected_ flux and errors into the spectrum
        spec.flux = flux[i, :] * (ivar[i, :] > 0)
        spec.flux[spec.flux == 0] = n.nan
        spec.ivar = ivar[i, :] * (ivar[i, :] > 0)
        spec.ivar[spec.ivar == 0] = n.nan
        spec.flux_error = 1 / n.sqrt(spec.ivar) * (ivar[i, :] > 0)
        # apply Balmer corrections to the spectrum
        if args.balmer == True:
            apply_resid_corr(spec, resid_corr)
        elif args.balmer == False:
            pass
        hdulist.close()
        hdulist = 0

        hdulist = pf.open(zbfile)
        metadata = hdulist[0].header
        synflux = hdulist[2].data
        zstruc = hdulist[1].data
        hdulist.close()
        hdulist = 0

        k += 1

        spec.alt = metadata['ALT']
        spec.airtemp = metadata['AIRTEMP']
        spec.seeing50 = metadata['SEEING50']
        spec.humidity = metadata['HUMIDITY']
        spec.pressure = metadata['PRESSURE']
        spec.az = metadata['AZ']
        spec.z = zstruc[i].field('z')
        spec.ra = zstruc[i].field('plug_ra')
        spec.dec = zstruc[i].field('plug_dec')

        #for key, val in vars(spec).items():
        #    print '{key} = {val}'.format(key=key, val=val)
        #p.figure()
        # Set starting fiber point (above), then copy and paste
        # the following repeatedly to loop over spectra:
        #i+=1

        # Following commented-out bit was needed for some of the early redux:
        #p.plot(wave, (flux[i,:]-bzero) * (ivar[i,:] > 0), 'k', hold=False)
        #auxflx = flux[i,:] * (ivar[i,:] > 0)
        #p.plot(wave, spec.flux, 'k', hold=False)
        #p.plot(wave, synflux[i,:], 'g', hold=True)
        #p.xlabel('Angstroms')
        #p.ylabel(bunit)
        #p.title(zstruc[i].field('class') + ', z = ' + str(zstruc[i].field('z')))
        #p.ylim(n.percentile(auxflx,1), 1.2*n.percentile(auxflx, 99))
        #p.show()
        spec.__save_fitsio__(dirpath=savedir, filetype='valid')
Beispiel #5
0
def read_spec(filepath):
    """
    Reads a FITS file containing the spectrum of a Quasar from the input path
    and returns a 'spectrum' class object into the main program.

    Parameters:
    -----------
          filepath : Path to the FITS file

    Returns:
    --------
          spectrum : A 'spectrum' class object
    """

    spec_dirname = os.path.dirname(filepath)
    spec_basename = os.path.basename(filepath)
    #initialise spectrum
    spec = spectrum()
    spec.filename = spec_basename
    if 'corr' not in spec_basename:
        #print 'uncorrected'
        fits = fitsio.FITS(filepath)

        spec.ra = fits[2]['RA'][0]
        spec.dec = fits[2]['DEC'][0]
        spec.z = fits[2]['Z'][0]

        spec.loglam = fits[1]['LOGLAM'][:]
        spec.wav = np.power(10, spec.loglam)
        spec.flx = fits[1]['FLUX'][:]
        spec.err = fits[1]['IVAR'][:]
        spec.ivar = fits[1]['IVAR'][:]
        spec.npix = np.size(spec.loglam)

        spec.numexp = fits[-1].get_extnum(
        ) - 3  #(-4 because of the 4 standard HDUs + 1 because we start at index 0, i.e. fits[0])

        spec.loglam_start = np.min(spec.loglam)
        spec.loglam_end = np.max(spec.loglam)
    else:
        #print 'corrected'
        fits = fitsio.FITS(filepath)
        header = fits[0].read_header()

        spec.ra = header['RA']
        spec.dec = header['DEC']
        spec.z = header['Z']
        spec.npix = header['NPIX']

        spec.wav = fits[1]['WAV'][:]
        spec.flx = fits[1]['FLUX'][:]
        spec.flx_corr = fits[1]['FLUX_CORR'][:]
        spec.err = fits[1]['FLUX_ERR'][:]
        if 'margala' not in spec_dirname:
            spec.corr5400 = fits[1]['CORR5400'][:]
            spec.corr4000 = fits[1]['CORR4000'][:]
            spec.corr = spec.corr5400 / spec.corr4000

        spec.loglam_start = np.log10(spec.wav[0])
        spec.loglam_end = np.log10(spec.wav[spec.npix - 1])

    return spec
Beispiel #6
0
def read_spectra(path):
    np.set_printoptions(threshold=6000)
    outspec = spectrum()

    if os.path.isdir(path):
        filetype = 'dir'
    elif os.path.isfile(path):
        filetype = 'file'

    labels = []
    if os.path.isdir(path):
        spectral_list = return_spectral_list(path)
        numspec = len(spectral_list[0])
        uncorrected_files = spectral_list[0]
        corrected_files = spectral_list[1]
        corrected_files_m = spectral_list[2]
        # list that saves the number of files in each subfolder
        numfiles = [
            len(uncorrected_files),
            len(corrected_files),
            len(corrected_files_m)
        ]
        dir_basename = os.path.dirname(path)
        thingid = dir_basename.split('/')[7]
        # read the data from the uncorrected FITS files
        for file in uncorrected_files:
            spec_basename = os.path.basename(file).split('.fits')[0]
            plate, mjd, fiberid = [
                int(field)
                for field in os.path.splitext(spec_basename)[0].split('-')[1:]
            ]
            labels.append('%04d-%5d-%04d' % (plate, mjd, fiberid))
    if os.path.isfile(path):
        spectral_list = []
        spectral_list.append([path])
        numspec = 1
        dir_basename = os.path.dirname(path)
        thingid = dir_basename.split('/')[7]
        spec_basename = os.path.basename(path).split('.fits')[0]
        plate, mjd, fiberid = [
            int(field)
            for field in os.path.splitext(spec_basename)[0].split('-')[1:]
        ]
        labels.append('%04d-%5d-%04d' % (plate, mjd, fiberid))

    # ======================= UNIVERSAL WAVELENGTH GRID =======================
    loglam_grid = np.arange(start=3.55, stop=4.02, step=0.0001)
    wave_grid = np.power(10, loglam_grid)
    wave_npix = wave_grid.size
    wave_shape = wave_grid.shape
    npix = wave_npix
    # ======================= ======================== ======================
    keys = ['BOSS', 'CORR', 'MARG']
    row_flux = np.dtype([('BOSS', np.float32, 1), ('CORR', np.float32, 1),
                         ('MARG', np.float32, 1)])
    row_data = np.dtype([('WAVE', np.float32, 1), ('FLUX', row_flux, 1),
                         ('FLUX_ERR', row_flux, 1), ('POWERLAW', row_flux, 1),
                         ('POWERLAW_ERR', row_flux, 1), ('CORR', row_flux, 1)])
    row_si = np.dtype([('BOSS', np.float32, 3), ('CORR', np.float32, 3),
                       ('MARG', np.float32, 3)])

    data = np.zeros(shape=(numspec, wave_npix), dtype=row_data)
    data.fill(np.nan)
    data['WAVE'] = wave_grid
    si_data = np.ones(shape=(numspec, ), dtype=row_si)
    # ======================= ======================== ======================
    outspec.keys = keys
    outspec.npix = wave_npix
    outspec.wave = wave_grid
    # ======================= READ DATA FROM FILES =======================
    for i in xrange(len(spectral_list)):
        for j, file in enumerate(spectral_list[i]):
            # ======================= READ SPECTRA =======================
            spec = spectrum()
            spec_dirname = os.path.dirname(file)
            spec_basename = os.path.basename(file)
            filetype, fileclass = check_filetype(file)
            if filetype == 'BOSS':
                spec.__read_BOSS__(file)
                flux_boss = np.zeros(shape=wave_shape)
            elif filetype == 'CORR':
                spec.__read_CORR__(file)
                flux_corr = np.zeros(shape=wave_shape)
                # __IMPORTANT__: use corrected flux as 'flux'
                spec.flux = spec.flux_corr

            # fit a powerlaw to the spectrum
            spec.__fit_powerlaw__(type=filetype)
            # ======================= REBINNING  =======================
            minwav = spec.wave.min()
            maxwav = spec.wave.max()
            # find where in the rebinned wavelength grid to put the rebinned flux values
            index_start = np.argmin(abs(wave_grid - minwav))
            index_stop = np.argmin(abs(wave_grid - maxwav))
            # the spectra is rebinned to 'newpix' pixels
            newpix = index_stop - index_start
            # put new flux values & the powerlaw into the data structure
            data[j]['FLUX'][fileclass][
                index_start:index_stop] = congrid.rebin_1d(spec.flux, newpix)
            data[j]['FLUX_ERR'][fileclass][
                index_start:index_stop] = congrid.rebin_1d(
                    spec.flux_error, newpix)
            data[j]['POWERLAW'][fileclass][
                index_start:index_stop] = congrid.rebin_1d(
                    spec.powerlaw, newpix)
            data[j]['POWERLAW_ERR'][fileclass][
                index_start:index_stop] = congrid.rebin_1d(
                    spec.powerlaw_error, newpix)
            if len(spec.corr) > 0:
                data[j]['CORR'][fileclass][
                    index_start:index_stop] = congrid.rebin_1d(
                        spec.corr, newpix)
            #for k in xrange(spec.npix):
            #    print j, k, fileclass, spec.flux_error[k], data[j]['FLUX_ERR'][fileclass][k]
            # save the data on the spectral index & error into the si_data structure
            si_data[j][fileclass][0] = spec.alpha
            si_data[j][fileclass][1] = spec.alpha_error
            si_data[j][fileclass][2] = spec.delta

            outspec.ra = spec.ra
            outspec.dec = spec.dec
            outspec.z = spec.z

            del (spec)
    # ======================= ======================== ======================

    # ======================= ======================== ======================
    # calculate the RMS of flux for each spectrum class
    dataT = data.transpose()
    rmsFlux = np.zeros(shape=wave_shape, dtype=row_flux)
    rmsFlux.fill(np.nan)
    rmsR2 = np.zeros(shape=wave_shape, dtype=row_flux)
    rmsR2.fill(np.nan)
    rmsErr = np.zeros(shape=wave_shape, dtype=row_flux)
    rmsErr.fill(np.nan)
    rmsCorr = np.zeros(shape=wave_shape, dtype=row_si)
    rmsCorr.fill(np.nan)
    #rmsCorrE = np.zeros(shape=wave_shape, dtype=row_flux); rmsCorrE.fill(np.nan)
    rmsPL = np.zeros(shape=wave_shape, dtype=row_flux)
    rmsPL.fill(np.nan)
    rmsPLe = np.zeros(shape=wave_shape, dtype=row_flux)
    rmsPLe.fill(np.nan)
    for key in keys:
        for pix in xrange(npix):
            # calculate the variance weigthed mean and deviation from numspec values of flux
            rmsFlux[pix][key] = rms(dataT[pix]['FLUX'][key],
                                    variance=dataT[pix]['FLUX_ERR'][key]**2)
            rmsR2[pix][key] = np.sum(
                (dataT[pix]['FLUX'][key] - rmsFlux[pix][key])**2 /
                (np.nanstd(dataT[pix]['FLUX'][key]))**2)
            rmsErr[pix][key] = np.nanstd(dataT[pix]['FLUX'][key])
            rmsCorr[pix][key][0] = np.nanpercentile(dataT[pix]['CORR'][key],
                                                    50)  # MEDIAN
            rmsCorr[pix][key][1] = np.nanpercentile(dataT[pix]['CORR'][key],
                                                    36)  # LOWER RANGE
            rmsCorr[pix][key][2] = np.nanpercentile(dataT[pix]['CORR'][key],
                                                    84)  # UPPER RANGE
            rmsPL[pix][key] = rms(dataT[pix]['POWERLAW'][key],
                                  variance=dataT[pix]['POWERLAW_ERR'][key]**2)
            rmsPLe[pix][key] = np.nanstd(dataT[pix]['POWERLAW'][key])
    outspec.flux = rmsFlux  # has three keys: ['BOSS', 'CORR', 'MARG']
    outspec.flux_error = rmsErr  # has three keys: ['BOSS', 'CORR', 'MARG']
    outspec.corr = rmsCorr  # has three keys: ['BOSS', 'CORR', 'MARG']
    outspec.R2 = rmsR2  # has three keys: ['BOSS', 'CORR', 'MARG']
    outspec.powerlaw = rmsPL  # has three keys: ['BOSS', 'CORR', 'MARG']
    outspec.powerlaw_error = rmsPLe  # has three keys: ['BOSS', 'CORR', 'MARG']
    # ======================= ======================== ======================
    auxspec = copy.deepcopy(outspec)
    rmsSIalpha = np.zeros(shape=(1, ), dtype=row_si)
    rmsSIdelta = np.zeros(shape=(1, ), dtype=row_si)
    for key in keys:
        auxspec.flux = rmsFlux[key]
        auxspec.flux_error = rmsErr[key]
        auxspec.__fit_powerlaw__(type='BOSS')
        rmsSIalpha[key][0][0] = auxspec.alpha
        rmsSIalpha[key][0][1] = auxspec.alpha_error
        rmsSIdelta[key][0][0] = auxspec.delta
    del auxspec

    outspec.alpha = np.array([rmsSIalpha[key][0][0] for key in keys])
    outspec.alpha_error = np.array([rmsSIalpha[key][0][1] for key in keys])
    outspec.delta = np.array([rmsSIdelta[key][0][0] for key in keys])

    # spectrum metadata to return to the main program
    outspec.nspectra = numspec
    # spectral indices of _INDIVIDUAL_(!) spectra
    outspec.alpha_BOSS = si_data[
        'BOSS']  # has three values: [alpha, alpha_error, delta]
    outspec.alpha_CORR = si_data[
        'CORR']  # has three values: [alpha, alpha_error, delta]
    outspec.alpha_MARG = si_data[
        'MARG']  # has three values: [alpha, alpha_error, delta]

    outspec.labels = labels
    outspec.thingid = thingid
    #del(spec)
    return data, outspec
Beispiel #7
0
def main():
    # ======================= PARSER =======================
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument(
        '--spec-dir',
        type=str,
        default=None,
        help='full path to the directory containing the FITS files, required')
    args = parser.parse_args()

    # ======================= FILES =======================
    if args.spec_dir:
        specList = glob(os.path.join(args.spec_dir, '*.fits'))
        numfiles = len(specList)
        labels = []
        dir_basename = os.path.dirname(args.spec_dir)
        thingid = dir_basename.split('/')[6]
        for file in specList:
            spec_basename = os.path.basename(file).split('.fits')[0]
            plate, mjd, fiberid = [
                int(field)
                for field in os.path.splitext(spec_basename)[0].split('-')[1:]
            ]
            #spec_filename.append(os.path.join(args.dir, 'spec-%04d-%5d-%04d.fits' % (plate, mjd, fiberid)))
            labels.append('%04d-%5d-%04d' % (plate, mjd, fiberid))
    #data, header = fitsio.read(file,ext=0,header=True)
    # ======================= UNIVERSAL WAVELENGTH GRID =======================
    loglam_grid = np.arange(start=3.55, stop=4.02, step=0.0001)
    wave_grid = np.power(10, loglam_grid)
    wave_npix = wave_grid.size
    wave_shape = wave_grid.shape
    # ======================= ======================== ======================
    flux_boss_list = []
    flux_corr_list = []
    flux_marg_list = []
    keys = ['BOSS', 'CORR', 'MARG']
    row = np.dtype([('WAVE', 'f8', 1), ('FLUX', 'f8', 1),
                    ('FLUX_ERR', 'f8', 1)])

    data = np.zeros(shape=(numfiles, wave_npix), dtype=row)
    # ======================= READ DATA FROM FILES =======================
    for i, file in enumerate(specList):
        spec = spectrum()
        spec_dirname = os.path.dirname(file)
        spec_basename = os.path.basename(file)
        if 'corr' not in spec_basename:
            #print 'uncorrected'
            spec.__read_BOSS__(file)
            key = 'BOSS'
            outfile = '../paper/plots/' + thingid + '_spectrum.pdf'
        else:
            #print 'corrected'
            spec.__read_CORR__(file)
            if 'margala' not in spec_dirname:
                key = 'CORR'
                outfile = '../paper/plots/' + thingid + '_corr_spectrum.pdf'
            else:
                key = 'MARG'
                outfile = '../paper/plots/' + thingid + '_corr_spectrum_margala.pdf'

        # ======================= REBINNING  =======================
        minwav = spec.wave.min()
        maxwav = spec.wave.max()
        index_start = np.argmin(abs(wave_grid - minwav))
        index_stop = np.argmin(abs(wave_grid - maxwav))
        newpix = index_stop - index_start
        data[i]['WAVE'][index_start:index_stop] = congrid.rebin_1d(
            spec.wave, newpix)
        if key == 'BOSS':
            data[i]['FLUX'][index_start:index_stop] = congrid.rebin_1d(
                spec.flux, newpix)
        elif (key == 'CORR' or key == 'MARG'):
            data[i]['FLUX'][index_start:index_stop] = congrid.rebin_1d(
                spec.flux, newpix)

    ra = spec.ra
    dec = spec.dec
    z = spec.z

    majorLocator = MultipleLocator(500)
    majorFormatter = FormatStrFormatter('%d')
    minorLocator = MultipleLocator(100)

    # ======================= PLOT =======================

    # PLOT
    xmin = wave_grid.min
    xmax = wave_grid.max
    xplotlim = (xmin, xmax)
    cmap = plt.get_cmap('Paired')
    line_colors = cmap(np.linspace(0, 1, numfiles))
    # ======================= DEFINING THE CANVAS =======================
    fsize = (20, 5)
    fig, axes = plt.subplots(2, 1, figsize=fsize, sharey=True)
    #plt.suptitle('PLATEID=%04d, MJD=%5d, FIBREID=%04d,   RA = %10.6f, DEC = %10.6f , z = %5.3f' % (plate, mjd, fiberid, ra, dec, z))
    fig.subplots_adjust(hspace=0.15)
    plt.suptitle('RA = %10.6f, DEC = %10.6f , z = %5.3f' % (ra, dec, z))
    # ======================= LABELS =======================
    #fig.text(0.5,0.0, r'Observed wavelength $[\AA]$', ha='center')
    fig.text(0.09,
             0.5,
             r'Flux $[10^{-17} \rm{erg/s/cm^2/\AA}]$',
             va='center',
             rotation='vertical')
    ax1, ax2 = axes.flat

    xmins = []
    xmaxs = []
    ymins = []
    ymaxs = []
    j = 0
    for i in xrange(0, numfiles):
        auxwav = wave_grid
        auxflx = data['FLUX'][i]
        # ======================= SMOOTHING =======================
        box = 5
        auxflx = smooth_array(auxflx, box)
        if np.size(auxflx) != np.size(auxwav):
            auxwav = auxwav[:np.size(auxflx)]
            #print np.size(auxwav), np.size(auxflx)
        # get the limits in y-axis

        xmin = np.min(auxwav)
        xmax = np.max(auxwav)
        xmins.append(xmin)
        xmaxs.append(xmax)

        ymin = np.percentile(auxflx, 0.5)
        ymins.append(ymin)
        ymax = 2.0 * np.percentile(auxflx, 99)
        ymaxs.append(ymax)

        ax1.plot(auxwav, auxflx, color=line_colors[j], label=labels[i])
        ax2.plot(auxwav, auxflx, color=line_colors[j], label=labels[i])
        j = j + 1

    xplotlim = (min(xmins), max(xmaxs), 0.5 * (min(xmins) + max(xmaxs)))
    yplotlim = (min(ymins), max(ymaxs))
    #print 'NEW GLOBAL MIN & MAX = ', yplotlim[0], yplotlim[1]
    ax1.set_xlim(xplotlim[0], xplotlim[2])
    ax2.set_xlim(xplotlim[2], xplotlim[1])

    ax1.set_ylim(yplotlim[0], yplotlim[1])
    ax2.set_xlabel(r'Observed wavelength $[\AA]$')
    ax1.legend(loc='upper right', prop={'size': 10})

    plt.savefig(outfile, format='pdf')
    plt.show()
def main():
    # ======================= PARSER =======================
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument('--spec',
                        type=str,
                        default=None,
                        help='full path to the corrected FITS file, required')
    args = parser.parse_args()

    specpath = args.spec
    save_dirname = os.path.dirname(os.path.dirname(specpath))
    sdss_flag = os.path.isdir(os.path.join(save_dirname, 'sdss'))
    if sdss_flag:
        sdss_specpath = glob(os.path.join(save_dirname, 'sdss', '*.fits'))
    #    spec_sdss     = spectrum()
    #    spec_sdss.__read_BOSS__(sdss_specpath[0])
    #    spec_sdss.__fit_powerlaw__('BOSS')
    # ======================= UNIVERSAL WAVELENGTH GRID =======================
    loglam_grid = np.arange(start=3.55, stop=4.02, step=0.0001)
    wave_grid = np.power(10, loglam_grid)
    wave_npix = wave_grid.size
    wave_shape = wave_grid.shape
    npix = wave_npix
    # ======================= ======================== ======================
    keys = ['SDSS', 'BOSS', 'CORR']
    row_flux = np.dtype([('BOSS', 'f8', 1), ('CORR', 'f8', 1),
                         ('SDSS', 'f8', 1)])
    row_data = np.dtype([('WAVE', 'f8', 1), ('FLUX', row_flux, 1),
                         ('FLUX_ERR', row_flux, 1), ('POWERLAW', row_flux, 1),
                         ('CORR', row_flux, 1)])
    row_si = np.dtype([('BOSS', 'f8', 3), ('CORR', 'f8', 3),
                       ('SDSS', 'f8', 3)])

    data = np.zeros(shape=(1, wave_npix), dtype=row_data)
    data.fill(np.nan)
    data['WAVE'] = wave_grid
    si_data = np.ones(shape=(1, ), dtype=row_si)
    for key in keys:
        spec = spectrum()
        if key == 'SDSS':
            spec.__read_BOSS__(sdss_specpath[0])
            filetype = 'BOSS'
        else:
            spec.__read_CORR__(specpath)
            filetype = key
        if key == 'CORR':
            spec.flux = spec.flux_corr
        spec.__fit_powerlaw__(filetype)
        # ======================= REBINNING  =======================
        minwav = spec.wave.min()
        maxwav = spec.wave.max()
        # find where in the rebinned wavelength grid to put the rebinned flux values
        index_start = np.argmin(abs(wave_grid - minwav))
        index_stop = np.argmin(abs(wave_grid - maxwav))
        # the spectra is rebinned to 'newpix' pixels
        newpix = index_stop - index_start
        print key, data['FLUX'][key]
        # put new flux values & the powerlaw into the data structure
        data[0]['FLUX'][key][index_start:index_stop] = congrid.rebin_1d(
            spec.flux, newpix)
        si_data[0][key][0] = spec.alpha
        si_data[0][key][1] = spec.alpha_error
        si_data[0][key][2] = spec.chisq

    print save_dirname
    # READ SPECTRUM FROM FILE & FIT POWERLAWS TO THE UNCORRECTED AND CORRECTED SPECTRA

    # PRINT SI DATA
    print '{0:-^80s}'.format(' POWER-LAW FIT ')
    print '{0:>8}{1:^14s}{2:>10s}'.format('', 'SI', 'CHI2')
    for key in keys:
        print '{key} : {0:+6.4f}+-{1:6.4f}{2:>10.4f}'.format(key=key,
                                                             *si_data[0][key])
    # CALCULATE THE CHI SQUARE OF BOSS AND CORR DATA (USING SDSS DATA AS EXPECTED VALUES)
    if sdss_flag:
        print '{0:-^80s}'.format(' AGREEMENT WITH SDSS DATA ')
        print '{0:>7s}{1:>10s}'.format('', 'CHI2')
        for key in keys:
            if key != 'SDSS':
                chisq = np.nansum(
                    (data[0]['FLUX'][key] - data[0]['FLUX']['SDSS'])**2 /
                    data[0]['FLUX']['SDSS']) / npix
                print '{key} : {0:>10.4f}'.format(chisq, key=key)
    sys.exit()

    # ======================= BASTI'S SMOOTHING FUNCTION =======================
    basti = True
    if basti:
        box = 5
        flx = smooth_array(array=spec.flux, smooth_width=box)
        flx_sdss = smooth_array(array=spec_sdss.flux, smooth_width=box)
        flx_corr = smooth_array(array=spec.flux_corr, smooth_width=box)

    # ======================= DEFINING THE CANVAS =======================
    fsize = (12, 5)
    fig = plt.figure(figsize=fsize)
    plt.suptitle(
        r'PLATE = %04d, MJD = %5d, FIBRE = %04d,    RA = %6.3f, Dec = %6.3f , z = %5.3f'
        % (spec.plateid, spec.MJD, spec.fiberid, spec.ra, spec.dec, spec.z))
    fig.subplots_adjust(hspace=0.15)

    # ======================= LABELS =======================
    #fig.text(0.5,0.0, r'Observed wavelength $[\AA]$', ha='center')
    #fig.text(0.09, 0.5, r'Flux $[10^{-17} \rm{erg/s/cm^2/\AA}]$', va='center', rotation='vertical')
    # ======================= FIRST SUBPLOT =======================

    majorLocator = MultipleLocator(500)
    majorFormatter = FormatStrFormatter('%d')
    minorLocator = MultipleLocator(250)

    #### PLOT
    ax2 = plt.subplot(223)
    ax3 = plt.subplot(224)
    ax1 = plt.subplot(211)
    ax1.plot(spec_sdss.wave,
             flx_sdss,
             color='orange',
             label='SDSS',
             linewidth=1.4)
    ax1.plot(spec.wave, flx, color='b', label='BOSS', linewidth=1.4)
    ax1.plot(spec.wave,
             flx_corr,
             color='g',
             label='Corrected BOSS',
             linewidth=1.4)

    #### SET LIMITS

    xmin = np.min(spec.wave)
    xmax = np.max(spec.wave)
    xhalf = (xmin + xmax) / 2
    ymin = min(0, np.percentile(spec.flux, 1))
    ymax = 1.1 * np.percentile(spec.flux, 99.7)

    xplotlim = (xmin, xmax)
    yplotlim = (ymin, ymax)

    ax1.set_xlim(xplotlim[0], xplotlim[1])
    ax1.set_ylim(yplotlim[0], yplotlim[1])
    ax1.xaxis.set_major_locator(majorLocator)
    ax1.xaxis.set_minor_locator(minorLocator)
    fig.text(0.5,
             0.0,
             r'Observed wavelength $[\AA]$',
             ha='center',
             va='bottom',
             rotation='horizontal')
    ax1.set_ylabel(r'Flux $[10^{-17} \rm{erg/s/cm^2/\AA}]$')

    ax1.legend(loc='upper right', prop={'size': 10})

    # ======================= SECOND SUBPLOT =======================

    majorLocator = MultipleLocator(2000)
    majorFormatter = FormatStrFormatter('%d')
    minorLocator = MultipleLocator(1000)

    #### REDEFINE PLOTTING ARRAYS
    #flxarray             = np.zeros(np.size(flx))
    #flxcorrarray_margala = flx_corr_margala - flx
    #flxcorrarray         = flx_corr - flx

    #### PLOT

    ax2.plot(spec.wave,
             spec.corr,
             color='r',
             label='Correction function',
             linewidth=2)
    ax2.set_ylabel(r'$C(\lambda)$')
    ax2.set_xlim(xplotlim[0], xplotlim[1])
    #ax2.set_xlabel(r'Observed wavelength $[\AA]$')
    ax2.xaxis.set_major_locator(majorLocator)
    ax2.xaxis.set_minor_locator(minorLocator)

    #axes[1].legend(loc='lower right',prop={'size':12})

    # ======================= THIRD SUBPLOT =======================

    majorLocator = MultipleLocator(2000)
    majorFormatter = FormatStrFormatter('%d')
    minorLocator = MultipleLocator(1000)

    #### REDEFINE PLOTTING ARRAYS
    #flxarray             = np.zeros(np.size(flx))
    #flxcorrarray_margala = flx_corr_margala - flx
    #flxcorrarray         = flx_corr - flx

    #### PLOT
    ax3.plot(spec_sdss.wave,
             spec_sdss.powerlaw,
             color='orange',
             linestyle='-',
             linewidth=2.)
    ax3.plot(spec.wave,
             spec.powerlaw_BOSS,
             color='b',
             linestyle='-',
             linewidth=2.)
    ax3.plot(spec.wave,
             spec.powerlaw_CORR,
             color='g',
             linestyle='-',
             linewidth=2.)
    colors = ['orange', 'blue', 'green']
    alpha = [spec_sdss.alpha_BOSS, spec.alpha_BOSS, spec.alpha_CORR]
    alpha_err = [
        spec_sdss.alpha_error_BOSS, spec.alpha_error_BOSS,
        spec.alpha_error_CORR
    ]

    ymin, ymax = ax3.get_ylim()
    dy = (ymax - ymin) / 10
    for i in xrange(3):
        text = r'$\alpha_{{\nu}} = {0:=+{w}.{p}f}\pm{1:{w}.{p}f} $'.format(
            alpha[i], alpha_err[i], w=7, p=4)
        ax3.text(7700, 0.8 * ymax - dy * i, text, color=colors[i])
    ax3.set_xlim(xplotlim[0], xplotlim[1])
    #ax3.set_xlabel(r'Observed wavelength $[\AA]$')
    ax3.xaxis.set_major_locator(majorLocator)
    ax3.xaxis.set_minor_locator(minorLocator)
    ax3.set_ylabel(r'Flux $[10^{-17} \rm{erg/s/cm^2/\AA}]$')
    #ax3.legend(loc='upper right',prop={'size':9})

    plt.savefig(os.path.join(
        save_dirname, '%04d-%05d-%04d-corrected_spectrum_2.pdf' %
        (spec.plateid, spec.MJD, spec.fiberid)),
                format='pdf')
    plt.show()
def main():
    # ======================= SETTINGS =======================
    settings = program_settings()
    settings.plot = True
    settings.smoothness = 5
    settings.resample = True
    # ======================= PARSER =======================
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument(
        '--spec-dir',
        type=str,
        default=None,
        help='full path to the directory containing the FITS files, required')
    args = parser.parse_args()

    # ======================= FILES =======================
    # from the input argument, fetch file names
    if args.spec_dir:
        spectral_list = return_spectral_list(args.spec_dir)
        uncorrected_files = spectral_list[0]
        corrected_files = spectral_list[1]
        corrected_files_m = spectral_list[2]
        # list that saves the number of files in each subfolder
        numfiles = [
            len(uncorrected_files),
            len(corrected_files),
            len(corrected_files_m)
        ]
        labels = []
        dir_basename = os.path.dirname(args.spec_dir)
        thingid = dir_basename.split('/')[7]
        # read the data from the uncorrected FITS files
        ids = []
        for file in uncorrected_files:
            spec_basename = os.path.basename(file).split('.fits')[0]
            plate, mjd, fiberid = [
                int(field)
                for field in os.path.splitext(spec_basename)[0].split('-')[1:]
            ]
            ids.append('%04d-%5d-%04d' % (plate, mjd, fiberid))
        labels.append(ids)
        # read the data from the corrected FITS files
        ids = []
        for file in corrected_files:
            spec_basename = os.path.basename(file).split('.fits')[0]
            plate, mjd, fiberid = [
                int(field)
                for field in os.path.splitext(spec_basename)[0].split('-')[1:]
            ]
            ids.append('%04d-%5d-%04d' % (plate, mjd, fiberid))
        labels.append(ids)
        # read the data from the corrected FITS files (Margala)
        ids = []
        for file in corrected_files_m:
            spec_basename = os.path.basename(file).split('.fits')[0]
            plate, mjd, fiberid = [
                int(field)
                for field in os.path.splitext(spec_basename)[0].split('-')[1:]
            ]
            ids.append('%04d-%5d-%04d' % (plate, mjd, fiberid))
        labels.append(ids)

    #data, header = fitsio.read(file,ext=0,header=True)
    # ======================= ======================== ======================
    wav_all = []
    wav_ucorr = []
    wav_corr = []
    wav_corr_m = []
    flx_all = []
    flx_ucorr = []
    flx_corr = []
    flx_corr_m = []
    npix_all = []
    npix_ucorr = []
    npix_corr = []
    npix_corr_m = []
    loglam_start_all = []
    loglam_start_ucorr = []
    loglam_start_corr = []
    loglam_start_corr_m = []
    loglam_end_all = []
    loglam_end_ucorr = []
    loglam_end_corr = []
    loglam_end_corr_m = []
    # ======================= READ DATA FROM FILES =======================
    # uncorrected spectra
    npix = []
    for file in uncorrected_files:
        spec = spectrum()
        spec.__read_BOSS__(file)
        wav_ucorr.append(spec.wave)
        flx_ucorr.append(spec.flux)
        npix_ucorr.append(spec.npix)
        loglam_start_ucorr.append(spec.beginwl)
        loglam_end_ucorr.append(spec.beginwl + (spec.npix * spec.deltawl))
    ra = spec.ra
    dec = spec.dec
    z = spec.z
    wav_all.append(wav_ucorr)
    flx_all.append(flx_ucorr)
    npix_all.append(npix_ucorr)
    loglam_start_all.append(loglam_start_ucorr)
    loglam_end_all.append(loglam_end_ucorr)
    del spec
    # corrected spectra
    for file in corrected_files:
        spec = spectrum()
        spec.__read_CORR__(file)
        wav_corr.append(spec.wave)
        #flx_corr.append(spec.corr_flux)
        flx_corr.append(spec.flux_corr)
        npix_corr.append(spec.npix)
        loglam_start_corr.append(np.log10(np.min(spec.wave)))
        loglam_end_corr.append(np.log10(np.max(spec.wave)))
        del spec
    wav_all.append(wav_corr)
    flx_all.append(flx_corr)
    npix_all.append(npix_corr)
    loglam_start_all.append(loglam_start_corr)
    loglam_end_all.append(loglam_end_corr)
    # corrected margala spectra
    for file in corrected_files_m:
        spec = spectrum()
        spec.__read_CORR__(file)
        wav_corr_m.append(spec.wave)
        flx_corr_m.append(spec.flux_corr)
        npix_corr_m.append(spec.npix)
        loglam_start_corr_m.append(np.log10(np.min(spec.wave)))
        loglam_end_corr_m.append(np.log10(np.max(spec.wave)))
        del spec
    wav_all.append(wav_corr_m)
    flx_all.append(flx_corr_m)
    npix_all.append(npix_corr_m)
    loglam_start_all.append(loglam_start_corr_m)
    loglam_end_all.append(loglam_end_corr_m)

    # ======================= RESAMPLING THE FLUX ARRAYS =======================
    # Each spectrum has a different number of pixels, 'starting' and 'end' wavelengths. We need to resample them a common pixel grid.
    if settings.resample == True:
        flx_all_resampled = []
        # reshaped = transposed
        flx_all_resampled_reshaped = []
        # create a resampled array in wavelengths: take minimum of 'starting' and maximum of 'end' wavelengths
        loglam_start = np.min(np.array(loglam_start_all))
        loglam_end = np.max(np.array(loglam_end_all))
        loglam_step = 0.0001
        loglam_resampled = np.arange(loglam_start, loglam_end, loglam_step)
        wav_resampled = ma.power(10, loglam_resampled)
        ## # RESAMPLING THE FLUXES
        for i in xrange(np.size(numfiles)):
            # i goes over 3 indices: uncorrected, corrected, corrected_margala
            flx_kind = []
            for j in xrange(numfiles[i]):
                # j goes over the spectra
                # locate the minimum and maximum of the wavelength array for this spectrum
                minwav = np.min(wav_all[i][j])
                maxwav = np.max(wav_all[i][j])
                # define auxiliarry arrays
                index = np.where((wav_resampled >= minwav)
                                 & (wav_resampled <= maxwav))[0]

                # find the interpolation function from data in the FITS file
                intfunc = interp1d(wav_all[i][j], flx_all[i][j])
                # apply the interpolation (but only within the proper boundaries)
                # defining a masked array flx_resampled with the same mask as the wavelength array
                flx_resampled = ma.array(np.full(wav_resampled.size,
                                                 np.nan))  #,mask = wav_mask)
                # changing the values of the flx_resampled array, but only for indices that are not masked
                flx_resampled[index] = intfunc(wav_resampled[index])

                # define a mask in wavelengths not covered by the j-th spectrum
                wav_mask = ma.masked_outside(wav_resampled, minwav,
                                             maxwav).mask
                # define a mask of outliers (further than nsigma)
                nsigma = 8
                outliers_boolean = is_outlier(flx_resampled, nsigma)
                outliers_mask = ma.make_mask(outliers_boolean)

                # combine the masks into a new mask and attach it to the flx_resampled
                mask = ma.mask_or(wav_mask, outliers_mask)
                flx_resampled.mask = mask

                #for k in xrange(np.size(wav_resampled)):
                #   print i,j,k, wav_resampled[k], flx_resampled[k]

                flx_kind.append(flx_resampled)

            # append the arrays
            flx_kind = ma.array(flx_kind)
            flx_all_resampled.append(flx_kind)
            flx_kind = ma.array(flx_kind).T
            flx_all_resampled_reshaped.append(flx_kind)

    # ======================= CALCULATE THE VARIANCE =======================
    flx_resampled_array = ma.array(flx_all_resampled_reshaped)
    print 'Calculating the variance'

    medFlux = []
    devFlux = []
    for i in xrange(np.size(numfiles)):
        # i goes over the uncorrected, corrected, corrected_margala
        median_i = []
        dev_i = []
        for j in xrange(np.size(flx_resampled_array[i]) / numfiles[i]):
            # j goes over the pixels
            fluxes = []
            for k in xrange(numfiles[i]):
                # k goes over individual exposures (spectra)
                fluxes.append(flx_resampled_array[i][j][k])
            median = np.nanmedian(fluxes)
            dev = np.nanstd(fluxes)
            median_i.append(median)
            dev_i.append(dev)
        medFlux.append(median_i)
        devFlux.append(dev_i)

    medFluxArray = np.array(medFlux)
    devFluxArray = np.array(devFlux)
    print '{0:>50s}'.format('STANDARD DEVIATION OF FLUX')
    print '{0:>31s} {1:>15s}'.format('MEDIAN', 'STD')
    print '{0:>20s} {1:15.12f} {2:15.12f}'.format(
        'UNCORRECTED:', np.nanmedian(devFluxArray[0]),
        np.nanstd(devFluxArray[0]))
    print '{0:>20s} {1:15.12f} {2:15.12f}'.format(
        'CORRECTED (Ours):', np.nanmedian(devFluxArray[1]),
        np.nanstd(devFluxArray[1]))
    print '{0:>20s} {1:15.12f} {2:15.12f}'.format(
        'CORRECTED (Margala):', np.nanmedian(devFluxArray[2]),
        np.nanstd(devFluxArray[2]))

    # RMS IN THE LYMAN ALPHA FOREST
    index = np.where(wav_resampled <= 1215.67 * (1 + z))[0]

    medFluxArray_LyA = medFluxArray[:, index]
    devFluxArray_LyA = devFluxArray[:, index]
    if medFluxArray_LyA.size != 0:
        print '{0:>50s}'.format(
            'STANDARD DEVIATION OF FLUX IN THE LYMAN ALPHA FOREST')
        print '{0:>31s} {1:>15s} {2:>15s} {3:>15s}'.format(
            'MEDIAN', 'STD', 'MIN', 'MAX')
        print '{0:>20s} {1:15.12f} {2:15.12f} {3:15.12f} {4:15.12f}'.format(
            'UNCORRECTED:', np.nanmedian(devFluxArray_LyA[0]),
            np.nanstd(devFluxArray_LyA[0]), np.nanmin(devFluxArray_LyA[0]),
            np.nanmax(devFluxArray_LyA[0]))
        print '{0:>20s} {1:15.12f} {2:15.12f} {3:15.12f} {4:15.12f}'.format(
            'CORRECTED (Ours):', np.nanmedian(devFluxArray_LyA[1]),
            np.nanstd(devFluxArray_LyA[1]), np.nanmin(devFluxArray_LyA[1]),
            np.nanmax(devFluxArray_LyA[1]))
        print '{0:>20s} {1:15.12f} {2:15.12f} {3:15.12f} {4:15.12f}'.format(
            'CORRECTED (Margala):', np.nanmedian(devFluxArray_LyA[2]),
            np.nanstd(devFluxArray_LyA[2]), np.nanmin(devFluxArray_LyA[2]),
            np.nanmax(devFluxArray_LyA[2]))

    settings.plot = True
    if settings.plot == True:
        # ======================= PLOT =======================
        majorLocator = MultipleLocator(500)
        majorFormatter = FormatStrFormatter('%d')
        minorLocator = MultipleLocator(100)
        # PLOT NAME
        outfile = os.path.join(args.spec_dir,
                               '%s_rms_triple_panel.pdf' % thingid)
        # PLOT PARAMETERS
        cmap = plt.cm.Spectral
        line_colors = cmap(np.linspace(0, 1, len(uncorrected_files)))
        #colors = ['Black','Crimson','Gold','Green','Navy','DarkMagenta','CornflowerBlue','Sienna','Green','Purple','Teal','MediumSpringGreen','Turquoise','FireBrick','Brown','Bisque','Yellow','Coral','Linen']
        # ======================= DEFINING THE CANVAS =======================
        # PLOT SIZE
        fsize = (12, 8)
        # MAKE SUBPLOTS
        fig, axes = plt.subplots(3, 1, figsize=fsize, sharey=True)
        fig.subplots_adjust(hspace=0.02)
        ax1, ax2, ax3 = axes.flat
        # SET TITLE
        plt.suptitle('THING ID = %9s' % (thingid))
        # plt.suptitle('RA = %10.6f, DEC = %10.6f , z = %5.3f' %(ra,dec,z))
        # ======================= AXES LABELS =======================
        #fig.text(0.5,0.0, r'Observed wavelength $[\AA]$', ha='center')
        fig.text(0.08,
                 0.5,
                 r'Flux $[10^{-17} \rm{erg/s/cm^2/\AA}]$',
                 va='center',
                 rotation='vertical')

        xmins = []
        xmaxs = []
        ymins = []
        ymaxs = []

        # PLOTTING DATA
        box = settings.smoothness
        for i in xrange(np.size(numfiles)):
            # i goes over the uncorrected, corrected, corrected_margala
            k = 0
            auxmedian = smooth_array(np.array(medFlux[i]), box)
            auxdev = smooth_array(np.array(devFlux[i]), box)

            for j in xrange(numfiles[i]):
                # j goes over the spectra
                auxwav = ma.array(wav_resampled,
                                  mask=flx_all_resampled[i][j].mask)
                auxflx = flx_all_resampled[i][j]

                # ======================= SMOOTHING =======================

                auxflx = smooth_array(auxflx, box)
                #if np.size(auxflx)!=np.size(auxwav):

                #auxwav = auxwav[:np.size(auxflx)]

                # get the limits in y-axis

                xmin = np.min(auxwav)
                xmax = np.max(auxwav)
                xmins.append(xmin)
                xmaxs.append(xmax)

                ymin = np.percentile(auxflx, 0.5)
                ymins.append(ymin)
                ymax = 1.2 * np.percentile(auxflx, 99)
                ymaxs.append(ymax)

                if i == 0:
                    ax1.plot(auxwav,
                             auxflx,
                             color=line_colors[k],
                             label=labels[i][j],
                             linestyle=':',
                             alpha=0.6)
                elif i == 1:
                    ax2.plot(auxwav,
                             auxflx,
                             color=line_colors[k],
                             label=labels[i][j],
                             linestyle=':',
                             alpha=0.6)
                elif i == 2:
                    ax3.plot(auxwav,
                             auxflx,
                             color=line_colors[k],
                             label=labels[i][j],
                             linestyle=':',
                             alpha=0.6)
                k = k + 1
            if i == 0:
                sigma = ma.array(devFluxArray[0],
                                 mask=flx_all_resampled[i][j].mask)
                # PLOT MEDIAN FLUX AND RMS
                ax1.plot(auxwav, auxmedian, color='Green', linewidth=1.3)
                ax1.plot(auxwav, auxdev, color='Red', linewidth=1)
                # FILL AREA OF RMS
                ax1.fill_between(auxwav,
                                 auxmedian - sigma,
                                 auxmedian + sigma,
                                 color="PaleGreen")
                # FILL AREA OF LY A FOREST
                ax1.axvspan(10**loglam_start,
                            1215.67 * (1 + z),
                            alpha=0.3,
                            color="SkyBlue")
                print 10**loglam_start, 1215.67 * (1 + z)
            elif i == 1:
                sigma = ma.array(devFluxArray[1],
                                 mask=flx_all_resampled[i][j].mask)
                ax2.plot(auxwav, auxmedian, color='Green', linewidth=1.3)
                ax2.plot(auxwav, auxdev, color='Red', linewidth=1)
                ax2.fill_between(auxwav,
                                 auxmedian - sigma,
                                 auxmedian + sigma,
                                 color="PaleGreen")
                ax2.axvspan(10**loglam_start,
                            1215.67 * (1 + z),
                            alpha=0.5,
                            color="SkyBlue")
            elif i == 2:
                sigma = ma.array(devFluxArray[2],
                                 mask=flx_all_resampled[i][j].mask)
                ax3.plot(auxwav, auxmedian, color='Green', linewidth=1.3)
                ax3.plot(auxwav, auxdev, color='Red', linewidth=1)
                ax3.fill_between(auxwav,
                                 auxmedian - sigma,
                                 auxmedian + sigma,
                                 color="PaleGreen")
                ax3.axvspan(10**loglam_start,
                            1215.67 * (1 + z),
                            alpha=0.5,
                            color="SkyBlue")

        xplotlim = (min(xmins), max(xmaxs), 0.5 * (min(xmins) + max(xmaxs)))
        yplotlim = (min(ymins), max(ymaxs))

        # AXES FINE TUNING

        ax1.text(6000, 0.85 * yplotlim[1], 'UNCORRECTED spectra')
        ax1.text(6000, 0.70 * yplotlim[1], 'RMS in the LyA forest')
        ax1.text(
            6000, 0.55 * yplotlim[1],
            '{0:>5s} {1:5.2f} {2:2s} {3:5.2f}'.format(
                '$\sigma$ = ', np.nanmedian(devFluxArray_LyA[0]), '$\pm$',
                np.nanstd(devFluxArray_LyA[0])))

        ax2.text(6000, 0.85 * yplotlim[1], 'CORRECTED spectra (this paper)')
        ax2.text(6000, 0.70 * yplotlim[1], 'RMS in the LyA forest')
        ax2.text(
            6000, 0.55 * yplotlim[1],
            '{0:>5s} {1:5.2f} {2:2s} {3:5.2f}'.format(
                '$\sigma$ = ', np.nanmedian(devFluxArray_LyA[1]), '$\pm$',
                np.nanstd(devFluxArray_LyA[1])))

        ax3.text(6000, 0.85 * yplotlim[1], 'CORRECTED spectra (Margala)')
        ax3.text(6000, 0.70 * yplotlim[1], 'RMS in the LyA forest')
        ax3.text(
            6000, 0.55 * yplotlim[1],
            '{0:>5s} {1:5.2f} {2:2s} {3:5.2f}'.format(
                '$\sigma$ = ', np.nanmedian(devFluxArray_LyA[2]), '$\pm$',
                np.nanstd(devFluxArray_LyA[2])))

        ax1.set_xlim(xplotlim[0], xplotlim[1])
        ax2.set_xlim(xplotlim[0], xplotlim[1])
        ax3.set_xlim(xplotlim[0], xplotlim[1])

        ax1.set_ylim(yplotlim[0], yplotlim[1])
        ax3.set_xlabel(r'Observed wavelength $[\AA]$')

        # LEGEND
        ax1.legend(loc='upper right', prop={'size': 9})

        plt.savefig(outfile, format='pdf')
        plt.show()
def main():

    # PARSER
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument(
        '--tpcorr',
        type=str,
        default=
        '/Volumes/Transcend/Isotropy/spectra/BOSScorrections/tpcorr-0.1/tpcorr.hdf5',
        help='throughput correction filename, required')
    parser.add_argument('--all',
                        action='store_true',
                        help='save corrected spectra for all available QSOs')
    args = parser.parse_args()

    # MARGALA CORRECTION FILE
    tpcorr = h5py.File(args.tpcorr, 'r')
    tpcorr_wave = tpcorr['wave'].value

    # DIRECTORY TO SAVE THE CORRECTED SPECTRA TO, USER-DEFINED
    dirpath = os.path.normpath(
        '/Volumes/Transcend/Isotropy/spectra/SDSS_DR12/QSO_Margala')
    # -------------------------------------------------------------------------------------
    # Parse arguments: extract plate, mjd, fiberid as integers and the spec filename
    # ids = list of tuples   : (plate,mjd,fiberid)
    # sid = list of strings  : string(plate+mjd+fiberid)  ---> used to check already corrected spectra
    ids = []
    sid_tot = []
    if args.all:
        print "CORRECTING ALL AVAILABLE SPECTRA"
        # CREATE A LIST OF ALL FILES TO BE CORRECTED : total_files
        PathToSpectra = os.path.normpath(
            "/Volumes/Transcend/Isotropy/spectra/SDSS_DR12/QSO")
        total_files = glob(os.path.join(PathToSpectra, "*.fits"))
        print "Spectra available: {0:8d}".format(len(total_files))
        for file in total_files:
            # APPEND THE UNIQUE IDENTIFIER TO sid_tot
            spec_basename = os.path.basename(file).split('.fits')[0]
            plate, mjd, fiberid = [
                int(field)
                for field in os.path.splitext(spec_basename)[0].split('-')[1:]
            ]
            ids.append((plate, mjd, fiberid))
            sid_tot.append('%04d%5d%04d' % (plate, mjd, fiberid))

    # CREATE A PYTHON SET OBJECT FOR ALL SIDs (ALLOWS INTERSECTION, DIFERENCE)
    sid_tot_array = np.array(sid_tot)
    sid_tot = set(sid_tot)

    # CREATE A LIST OF ALL FILES ALREADY CORRECTED AND PRESENT IN THE OUTPUT DIRECTORY: corrected_files
    corrected_files = glob(os.path.join(dirpath, "*.fits"))
    print "Spectra corrected: {0:8d}".format(len(corrected_files))
    sid_corr = []
    for file in corrected_files:
        # APPEND THE UNIQUE IDENTIFIERS TO sid_corr
        spec_basename = os.path.basename(file).split('.fits')[0]
        plate, mjd, fiberid = [
            int(field)
            for field in os.path.splitext(spec_basename)[0].split('-')[1:]
        ]
        sid_corr.append('%04d%5d%04d' % (plate, mjd, fiberid))
    # CREATE A PYTHON SET OBJECT FOR CORRECTED SIDs
    sid_corr = set(sid_corr)
    sid_unc = sid_tot.difference(sid_corr)

    # FIND THE DIFFERENCE OF THE TWO SETS (sid_tot - sid_corr)
    # APPEND SIDs TO uncorrected_files ---> used later
    uncorrected_files = []
    for i, file in enumerate(total_files):
        if sid_tot_array[i] in sid_unc:
            uncorrected_files.append(file)

    # ITERATE OVER FILES IN uncorrected_files AND APPLY THE CORRECTION
    print "To be corrected:  {0:8d}".format(len(uncorrected_files))
    file_array = np.array(uncorrected_files)
    for file in uncorrected_files:
        HDU = fitsio.FITS(file)
        flux = HDU[1]['flux'][:]
        ivar = HDU[1]['ivar'][:]
        wavelength = np.power(10, HDU[1]['loglam'][:])
        ra = HDU[2]['ra'][0][0]
        dec = HDU[2]['dec'][0][0]
        z = HDU[2]['z'][0][0]
        HDU.close()

        plate, mjd, fiberid = ids[np.argwhere(file_array == file)[0][0]]
        # Read the target's throughput correction vector
        tpcorr_key = '%s/%s/%s' % (plate, mjd, fiberid)
        try:
            correction = tpcorr[tpcorr_key].value
        except:
            print "No data on object found"
            continue
        # Create an interpolated correction function
        correction_interp = interp1d(tpcorr_wave, correction, kind='linear')

        # Sample the interpolated correction using the observation's wavelength grid
        resampled_correction = correction_interp(wavelength)

        # Apply the correction to the observed flux and ivar
        corrected_flux = flux * resampled_correction
        corrected_ivar = ivar / resampled_correction**2
        # Save the data into a fits file
        spec = spectrum()

        spec.plateid = plate
        spec.mjd = mjd
        spec.fiberid = fiberid
        spec.ra = ra
        spec.dec = dec
        spec.z = z

        spec.npix = np.size(wavelength)
        spec.wave = wavelength
        spec.flux = flux
        spec.ivar = ivar
        spec.flux_corr = corrected_flux
        spec.flux_error = np.sqrt(1. / corrected_ivar)
        spec.corr = resampled_correction

        spec.basename = os.path.basename(file)
        spec.dirname = os.path.dirname(file)

        spec.__save_fitsio__(dirpath=dirpath)
        del (spec)

    tpcorr.close()
def main():
    # ======================= SETTINGS =======================
    settings = program_settings()
    settings.plot = True
    settings.smoothness = 5
    settings.resample = True
    # ======================= PARSER =======================
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument('--spec-dir', type=str, default=None, 
        help='full path to the directory containing the FITS files, required')
    parser.add_argument('--panels', type=int, default=3,
        help='number of panels, default = 3')
    args = parser.parse_args()

    # ======================= FILES =======================
    # from the input argument, fetch file names
    if args.spec_dir:
        spectral_list       = return_spectral_list(args.spec_dir)
        numspec             = len(spectral_list[0])
        uncorrected_files   = spectral_list[0]
        corrected_files     = spectral_list[1]
        corrected_files_m   = spectral_list[2]
        # list that saves the number of files in each subfolder
        numfiles = [len(uncorrected_files),len(corrected_files),len(corrected_files_m)]
        labels = []
        dir_basename = os.path.dirname(args.spec_dir)
        thingid = dir_basename.split('/')[7]
        # read the data from the uncorrected FITS files
        ids = []
        for file in uncorrected_files:
            spec_basename = os.path.basename(file).split('.fits')[0]
            plate, mjd, fiberid = [int(field) for field in os.path.splitext(spec_basename)[0].split('-')[1:]]
            ids.append('%04d-%5d-%04d' % (plate, mjd, fiberid))
        labels.append(ids)
        # read the data from the corrected FITS files
        ids = []
        for file in corrected_files:
            spec_basename = os.path.basename(file).split('.fits')[0]
            plate, mjd, fiberid = [int(field) for field in os.path.splitext(spec_basename)[0].split('-')[1:]]
            ids.append('%04d-%5d-%04d' % (plate, mjd, fiberid))
        labels.append(ids)
        # read the data from the corrected FITS files (Margala)
        ids = []
        for file in corrected_files_m:
            spec_basename = os.path.basename(file).split('.fits')[0]
            plate, mjd, fiberid = [int(field) for field in os.path.splitext(spec_basename)[0].split('-')[1:]]
            ids.append('%04d-%5d-%04d' % (plate, mjd, fiberid))
        labels.append(ids)
        
    #data, header = fitsio.read(file,ext=0,header=True)
    # ======================= UNIVERSAL WAVELENGTH GRID =======================
    loglam_grid = np.arange(start=3.55, stop = 4.02, step = 0.0001)
    wave_grid   = np.power(10, loglam_grid)
    wave_npix   = wave_grid.size
    wave_shape  = wave_grid.shape
    # ======================= ======================== ======================
    flux_boss_list = []; flux_corr_list = []; flux_marg_list = []
    keys         = ['BOSS','CORR','MARG']
    row          = np.dtype([('BOSS','f8',1),('CORR','f8',1),('MARG','f8',1)])

    flux_data    = np.zeros(shape = (max(numfiles),wave_npix), dtype=row)
    si_data      = np.zeros(shape = (max(numfiles)), dtype=row)
    pwrlaw_data  = np.zeros(shape = (max(numfiles),wave_npix), dtype=row)
    # ======================= READ DATA FROM FILES =======================
    for i in xrange(len(spectral_list)):
        for j,file in enumerate(spectral_list[i]):
            # ======================= READ SPECTRA =======================
            spec = spectrum()
            spec_dirname  = os.path.dirname(file)
            spec_basename = os.path.basename(file)
            if 'corr' not in spec_basename:
                spec.__read_BOSS__(file)
                flux_boss = np.zeros(shape=wave_shape)
            elif 'corr' in spec_basename:
                spec.__read_CORR__(file)
                flux_corr = np.zeros(shape=wave_shape)
            # ======================= REBINNING  =======================
            minwav = spec.wave.min() ; maxwav = spec.wave.max()
            index_start = np.argmin(abs(wave_grid-minwav))
            index_stop  = np.argmin(abs(wave_grid-maxwav))
            newpix = index_stop - index_start
            
            if 'corr' not in spec_basename:
                spec.__fit_powerlaw__(type='BOSS')
                si_data[j]['BOSS'] = spec.alpha
                flux_data[j]['BOSS'][index_start:index_stop] = congrid.rebin_1d(spec.flux, newpix)
                pwrlaw_data[j]['BOSS'][index_start:index_stop] = congrid.rebin_1d(spec.powerlaw, newpix)
            if 'corr' in spec_basename:
                spec.__fit_powerlaw__(type='CORR')
                if 'margala' not in spec_dirname:
                    si_data[j]['CORR'] = spec.alpha
                    flux_data[j]['CORR'][index_start:index_stop] = congrid.rebin_1d(spec.flux_corr, newpix)
                    pwrlaw_data[j]['CORR'][index_start:index_stop] = congrid.rebin_1d(spec.powerlaw, newpix)
                elif 'margala' in spec_dirname:
                    si_data[j]['MARG'] = spec.alpha
                    flux_data[j]['MARG'][index_start:index_stop] = congrid.rebin_1d(spec.flux_corr, newpix)
                    pwrlaw_data[j]['MARG'][index_start:index_stop] = congrid.rebin_1d(spec.powerlaw, newpix)
    ra = spec.ra ; dec = spec.dec; z = spec.z
    del(spec)
    # TRANSPOSE THE FLUXES TO CALCULATE RMS 
    flux = np.transpose(flux_data)
    
    # ======================= CALCULATE THE VARIANCE =======================
    print 'Calculating the variance'

    
    flux_rms  = np.zeros(shape = wave_shape, dtype = row)
    flux_std  = np.zeros(shape = wave_shape, dtype = row)

    for pix in xrange(wave_npix):
        flux_rms[pix]['BOSS'] = np.sqrt(np.mean(np.square(flux['BOSS'][pix]))); flux_std[pix]['BOSS'] = np.std(flux['BOSS'][pix])
        flux_rms[pix]['CORR'] = np.sqrt(np.mean(np.square(flux['CORR'][pix]))); flux_std[pix]['CORR'] = np.std(flux['CORR'][pix])
        flux_rms[pix]['MARG'] = np.sqrt(np.mean(np.square(flux['MARG'][pix]))); flux_std[pix]['MARG'] = np.std(flux['MARG'][pix])

    medianSpec = median_spectrum(z, wave_grid, flux_rms, flux_std)
    print '{0:>50s}'.format('STANDARD DEVIATION OF FLUX')
    print '{0:>31s} {1:>15s}'.format('RMS','STD')
    print '{0:>20s} {1:15.12f} {2:15.12f}'.format('UNCORRECTED:',         np.nanmedian(flux_rms['BOSS']), np.nanstd(flux_rms['BOSS']))
    print '{0:>20s} {1:15.12f} {2:15.12f}'.format('CORRECTED (Ours):',    np.nanmedian(flux_rms['CORR']), np.nanstd(flux_rms['CORR']))
    print '{0:>20s} {1:15.12f} {2:15.12f}'.format('CORRECTED (Margala):', np.nanmedian(flux_rms['MARG']), np.nanstd(flux_rms['MARG']))



    settings.plot=True
    if settings.plot==True:
        npanels = args.panels
    # ======================= PLOT =======================
        majorLocator   = MultipleLocator(500)
        majorFormatter = FormatStrFormatter('%d')
        minorLocator   = MultipleLocator(100)
        # PLOT NAME
        if   npanels == 1:
            outfile = os.path.join(args.spec_dir,'%s_rms_single_panel.pdf' %thingid)
            fsize = (12,3)
        elif npanels == 2:
            outfile = os.path.join(args.spec_dir,'%s_rms_double_panel.pdf' %thingid)
            fsize = (12,5)
        elif npanels == 3:
            outfile = os.path.join(args.spec_dir,'%s_rms_triple_panel.pdf' %thingid)
            fsize = (12,7)
        # PLOT PARAMETERS
        cmap = plt.get_cmap('Paired')
        line_colors = cmap(np.linspace(0,1,len(uncorrected_files)))
        # ======================= DEFINING THE CANVAS =======================
        # PLOT SIZE
        fsize = (12,5)
        # MAKE SUBPLOTS
        fig, axs = plt.subplots(npanels,1,figsize=fsize,sharey=True)
        ax      = np.array(axs)
        fig.subplots_adjust(hspace=0.02)
        # SET TITLE
        plt.suptitle('THING ID = %9s' %(thingid))
       # plt.suptitle('RA = %10.6f, DEC = %10.6f , z = %5.3f' %(ra,dec,z))    
        # ======================= AXES LABELS =======================
        #fig.text(0.5,0.0, r'Observed wavelength $[\AA]$', ha='center')
        fig.text(0.08, 0.5, r'Flux $[10^{-17} \rm{erg/s/cm^2/\AA}]$', va='center', rotation='vertical')

        xmins = []
        xmaxs = []
        ymins = []
        ymaxs = []

        # PLOTTING DATA
        box=settings.smoothness
        auxwav = wave_grid
        for i, key in zip(xrange(npanels),keys[0:npanels]):
            print 'PLOTTING {0:s}'.format(key)
            # i goes over the uncorrected, corrected, corrected_margala
            k = 0
            # ======================= SMOOTHING =======================
            auxmedian = smooth_array(flux_rms[key],box)
            auxdev  = smooth_array(flux_std[key],box)
            
            for j in xrange(numfiles[i]):
                # j goes over the spectra
                auxflx = smooth_array(flux_data[j][key], box)
            
                if np.size(auxflx)!=np.size(auxwav):
                    print 'error'
                    print auxwav.shape
                    print auxflx.shape
                    sys.exit()
                    #auxwav = auxwav[:np.size(auxflx)]
            
                # get the limits in y-axis
                ymin = np.percentile(auxflx,  0.5); ymins.append(ymin)
                ymax = 1.2*np.percentile(auxflx, 99.5);   ymaxs.append(ymax)             
                ax[i].plot(auxwav,auxflx,color=line_colors[k],label=labels[i][j],linestyle=':', alpha=0.6)
                k = k+1
            # PLOT MEDIAN FLUX AND RMS
            sigma = flux_std[key]
            ax[i].plot(auxwav,auxmedian,color='Green',linewidth=1.3)
            ax[i].plot(auxwav,auxdev,color='Red',linewidth=1)
            # FILL AREA OF RMS
            ax[i].fill_between(auxwav, auxmedian - sigma, auxmedian + sigma, color="Green", alpha=0.3)
            # FILL AREA OF LY A FOREST
            #ax[i].axvspan(wave_grid.min(), 1215.67*(1+z), alpha=0.3, color="SkyBlue")
        xplotlim = (wave_grid.min(), wave_grid.max())
        yplotlim = (min(ymins),max(ymaxs))
        for i in xrange(npanels):
            ax[i].set_xlim(xplotlim[0],xplotlim[1])
            ax[i].set_ylim(yplotlim[0],yplotlim[1])
        ax[npanels-1].set_xlabel(r'Observed wavelength $[\AA]$')

        #0.08, 0.5, r'Flux $[10^{-17} \rm{erg/s/cm^2/\AA}]$', va='center', rotation='vertical')
        ax[0].text(0.96,0.5,'UNCORRECTED spectra', va='center', rotation='vertical')
        fig.text(6000,0.85*yplotlim[1],'CORRECTED spectra (this paper)')
        fig.text(6000,0.85*yplotlim[1],'CORRECTED spectra (Margala)')

        plt.savefig(outfile, format = 'pdf')
        print 'PLOT SAVED TO {0:s}'.format(outfile)
        plt.show()