Example #1
0
    def __init__(self, specprod_dir=None, qaprod_dir=None):
        """ Class to organize and execute QA for a DESI production

        Args:
            specprod_dir(str): Path containing the exposures/ directory to use. If the value
                is None, then the value of :func:`specprod_root` is used instead.
            qaprod_dir(str): Path containing the root path for QA output
        Notes:

        Attributes:
            qa_exps : list
              List of QA_Exposure classes, one per exposure in production
            data : dict
        """
        # Init
        if specprod_dir is None:
            specprod_dir = specprod_root()
        if qaprod_dir is None:
            qaprod_dir = qaprod_root()
        #
        self.specprod_dir = specprod_dir
        self.qaprod_dir = qaprod_dir
        tmp = specprod_dir.split('/')
        self.prod_name = tmp[-1] if (len(tmp[-1]) > 0) else tmp[-2]
        # Exposure dict stored as [night][exposure]
        self.mexp_dict = {}
        # QA Exposure objects
        self.qa_exps = []
        # dict to hold QA data
        #  Data Model :  key1 = Night(s);  key2 = Expids
        self.data = {}
        #
        self.qaexp_outroot = None
Example #2
0
    def __init__(self, specprod_dir=None, qaprod_dir=None):
        """ Class to organize and execute QA for a DESI production

        Args:
            specprod_dir(str): Path containing the exposures/ directory to use. If the value
                is None, then the value of :func:`specprod_root` is used instead.
            qaprod_dir(str): Path containing the root path for QA output
        Notes:

        Attributes:
            qa_exps : list
              List of QA_Exposure classes, one per exposure in production
            data : dict
        """
        # Init
        if specprod_dir is None:
            specprod_dir = specprod_root()
        if qaprod_dir is None:
            qaprod_dir = qaprod_root()
        #
        self.specprod_dir = specprod_dir
        self.qaprod_dir = qaprod_dir
        tmp = specprod_dir.split('/')
        self.prod_name = tmp[-1] if (len(tmp[-1]) > 0) else tmp[-2]
        # Exposure dict stored as [night][exposure]
        self.mexp_dict = {}
        # QA Exposure objects
        self.qa_exps = []
        # dict to hold QA data
        #  Data Model :  key1 = Night(s);  key2 = Expids
        self.data = {}
        #
        self.qaexp_outroot = None
Example #3
0
    def __init__(self,
                 expid,
                 night,
                 flavor=None,
                 specprod_dir=None,
                 in_data=None,
                 qaprod_dir=None,
                 no_load=False,
                 multi_root=None,
                 **kwargs):
        """
        Class to organize and execute QA for a DESI Exposure

        x.flavor, x.data

        Args:
            expid: int -- Exposure ID
            night: str -- YYYYMMDD
            specprod_dir(str): Path containing the exposures/ directory to use. If the value
                is None, then the value of :func:`specprod_root` is used instead.
            in_data: dict, optional -- Input data
              Mainly for reading from disk
            no_load: bool, optional -- Do not load QA data (rare)
            multi_root: str, optional
              Load QA from a slurped file.
              This is the root and the path is qaprod_dir

        Notes:

        Attributes:
            All input args become object attributes.
        """
        # Init
        if not isinstance(expid, int):
            raise IOError("expid must be an int at instantiation")
        self.expid = expid
        self.night = night
        self.meta = {}
        # Paths
        self.specprod_dir = specprod_dir
        if qaprod_dir is None:
            qaprod_dir = qaprod_root(self.specprod_dir)
        self.qaprod_dir = qaprod_dir

        # Load meta from frame (ideally)
        frames_dict = get_files(filetype=str('frame'),
                                night=night,
                                expid=expid,
                                specprod_dir=self.specprod_dir)
        if len(frames_dict) > 0:
            frame_file = list(frames_dict.items())[0][1]  # Any one will do
            frame_meta = read_meta_frame(frame_file)
            self.load_meta(frame_meta)
            flavor = self.meta['FLAVOR']  # Over-rides any input value
        else:
            flavor = flavor

        assert flavor in desi_params[
            'frame_types'], "Unknown flavor {} for night {} expid {}".format(
                flavor, night, expid)
        if flavor in ['science']:
            self.type = 'data'
        else:
            self.type = 'calib'
        self.flavor = flavor

        # Internal dicts
        self.data = dict(flavor=self.flavor,
                         expid=self.expid,
                         night=self.night,
                         frames={})

        # Load?
        if no_load:
            return

        if in_data is None:
            self.load_qa_data(multi_root=multi_root, **kwargs)
        else:
            assert isinstance(in_data, dict)
            self.data = in_data

        # Others
        self.qa_s2n = None
Example #4
0
def main(args) :
    # imports
    import glob
    from desispec.io import findfile, makepath
    from desispec.io import get_exposures
    from desispec.io import get_files, get_nights
    from desispec.io import get_reduced_frames
    from desispec.io import specprod_root
    from desispec.io import qaprod_root
    from desispec.qa import utils as qa_utils
    import copy
    import pdb

    # Init
    specprod_dir = specprod_root()

    # Log
    log=get_logger()
    log.info("starting")

    # Path
    if args.qaprod_dir is not None:
        qaprod_dir = args.qaprod_dir
    else:
        qaprod_dir = qaprod_root()

    # Channels
    if args.channels is not None:
        channels = [iarg for iarg in args.channels.split(',')]
    else:
        channels = ['b','r','z']

    # Sky dict
    sky_dict = dict(wave=[], skyflux=[], res=[], count=0)
    channel_dict = dict(b=copy.deepcopy(sky_dict),
                        r=copy.deepcopy(sky_dict),
                        z=copy.deepcopy(sky_dict),
                        )
    # Nights
    if args.nights is not None:
        nights = [iarg for iarg in args.nights.split(',')]
    else:
        nights = None

    # Exposure plot?
    if args.expid is not None:
        # Nights
        if nights is None:
            nights = get_nights()
        nights.sort()
        # Find the exposure
        for night in nights:
            if args.expid in get_exposures(night, specprod_dir=specprod_dir):
                frames_dict = get_files(filetype=str('cframe'), night=night,
                                    expid=args.expid, specprod_dir=specprod_dir)
                # Loop on channel
                #for channel in ['b','r','z']:
                for channel in ['z']:
                    channel_dict[channel]['cameras'] = []
                    for camera, cframe_fil in frames_dict.items():
                        if channel in camera:
                            sky_file = findfile(str('sky'), night=night, camera=camera,
                                expid=args.expid, specprod_dir=specprod_dir)
                            wave, flux, res, _ = qa_utils.get_skyres(cframe_fil)
                            # Append
                            channel_dict[channel]['wave'].append(wave)
                            channel_dict[channel]['skyflux'].append(np.log10(np.maximum(flux,1e-1)))
                            channel_dict[channel]['res'].append(res)
                            channel_dict[channel]['cameras'].append(camera)
                            channel_dict[channel]['count'] += 1
                    if channel_dict[channel]['count'] > 0:
                        from desispec.qa.qa_plots import skysub_resid_series  # Hidden to help with debugging
                        skysub_resid_series(channel_dict[channel], 'wave',
                             outfile=qaprod_dir+'/QA_skyresid_wave_expid_{:d}{:s}.png'.format(args.expid, channel))
                        skysub_resid_series(channel_dict[channel], 'flux',
                             outfile=qaprod_dir+'/QA_skyresid_flux_expid_{:d}{:s}.png'.format(args.expid, channel))
        return


    # Skyline
    if args.skyline:
        from desispec.qa.qa_plots import skyline_resid
        # Loop on channel
        for channel in channels:
            cframes = get_reduced_frames(nights=nights, channels=[channel])
            if len(cframes) > 0:
                log.info("Loading sky residuals for {:d} cframes".format(len(cframes)))
                if len(cframes) == 1:
                    log.error('len(cframes)==1; starting debugging')
                    pdb.set_trace() # Need to call differently
                else:
                    sky_wave, sky_flux, sky_res, sky_ivar = qa_utils.get_skyres(
                        cframes, flatten=False)
                # Plot
                outfile=args.outdir+'/skyline_{:s}.png'.format(channel)
                log.info("Plotting to {:s}".format(outfile))
                skyline_resid(channel, sky_wave, sky_flux, sky_res, sky_ivar,
                              outfile=outfile)
        return

    # Full Prod Plot?
    if args.prod:
        from desispec.qa.qa_plots import skysub_resid_dual
        # Loop on channel
        for channel in channels:
            cframes = get_reduced_frames(nights=nights, channels=[channel])
            if len(cframes) > 0:
                log.info("Loading sky residuals for {:d} cframes".format(len(cframes)))
                sky_wave, sky_flux, sky_res, _ = qa_utils.get_skyres(cframes)
                # Plot
                outfile=qaprod_dir+'/skyresid_prod_dual_{:s}.png'.format(channel)
                makepath(outfile)
                log.info("Plotting to {:s}".format(outfile))
                skysub_resid_dual(sky_wave, sky_flux, sky_res, outfile=outfile)
        return

    # Test sky noise for Gaussianity
    if args.gauss:
        from desispec.qa.qa_plots import skysub_gauss
        # Loop on channel
        for channel in channels:
            cframes = get_reduced_frames(nights=nights, channels=[channel])
            if len(cframes) > 0:
                # Cut down for debugging
                #cframes = [cframes[ii] for ii in range(15)]
                #
                log.info("Loading sky residuals for {:d} cframes".format(len(cframes)))
                sky_wave, sky_flux, sky_res, sky_ivar = qa_utils.get_skyres(cframes)
                # Plot
                log.info("Plotting..")
                outfile=qaprod_dir+'/skyresid_prod_gauss_{:s}.png'.format(channel)
                makepath(outfile)
                skysub_gauss(sky_wave, sky_flux, sky_res, sky_ivar,
                                  outfile=outfile)
        return