def __init__(self,
                 base='MySource',
                 configFile = False,
                 analysisConfig = dC.defaultAnalysisConfig,
                 commonConfig = dC.defaultCommonConfig):

        commonConfig['base'] = base
        
        #Fills in missing items from the config arguments with default values
        for k in dC.defaultCommonConfig:
            commonConfig.setdefault(k, dC.defaultCommonConfig[k])
        for k in dC.defaultAnalysisConfig:
            analysisConfig.setdefault(k, dC.defaultAnalysisConfig[k])

        self.logger = Logger(base, self.__class__.__name__,ll(commonConfig['verbosity'])).get()
        self.logger.info("This is quickLike version {}.".format(__version__))

        if(configFile):
            try:
                commonConfigRead,analysisConfigRead,likelihoodConfigRead,plotConfigRead,curveConfigRead = qU.readConfig(self.logger,base)
            except(qU.FileNotFound):
                self.logger.critical("One or more needed files do not exist.")
                sys.exit()
            try:
                commonConfig = qU.checkConfig(self.logger,commonConfig,commonConfigRead)
            except(KeyError):
                sys.exit()
            #Reset the verboisty from the config file if needed
            if ll(commonConfig['verbosity']) != self.logger.handlers[1].level:
                self.logger.info("Resetting the log level on the console to {}.".format(commonConfig['verbosity']))
                self.logger.handlers[1].setLevel(ll(commonConfig['verbosity']))
            try:
                analysisConfig = qU.checkConfig(self.logger,analysisConfig,analysisConfigRead)
            except(KeyError):
                sys.exit()
        
        self.commonConf = commonConfig
        self.analysisConf = analysisConfig
        
        logString = "Created quickAnalysis object: "
        for variable, value in commonConfig.iteritems():
            logString += variable+"="+str(value)+","
        for variable, value in analysisConfig.iteritems():
            logString += variable+"="+str(value)+","
        self.logger.info(logString)
class quickAnalysis:

    """This is the base class.  If you want to use this, you first
    need to create an object from this method:

    >>> qA = quickAnalysis('example_name', configFile = True)

    will create an object called qA with the <basename> of
    'example_name' and will read in all of the options from the config
    file.  You can create an example config frile via the writeConfig
    function or via the command line with the -c option.  You can also
    pass all of the variables via the intial object initialiation
    function (see below).  Once you've created this object, you can
    just execute the runAll function to execute all of the steps, or
    use the functions individually as needed.
    """

    __version__ = LAS.__version__

    def __init__(self,
                 base='MySource',
                 configFile = False,
                 analysisConfig = dC.defaultAnalysisConfig,
                 commonConfig = dC.defaultCommonConfig):

        commonConfig['base'] = base
        
        #Fills in missing items from the config arguments with default values
        for k in dC.defaultCommonConfig:
            commonConfig.setdefault(k, dC.defaultCommonConfig[k])
        for k in dC.defaultAnalysisConfig:
            analysisConfig.setdefault(k, dC.defaultAnalysisConfig[k])

        self.logger = Logger(base, self.__class__.__name__,ll(commonConfig['verbosity'])).get()
        self.logger.info("This is quickLike version {}.".format(__version__))

        if(configFile):
            try:
                commonConfigRead,analysisConfigRead,likelihoodConfigRead,plotConfigRead,curveConfigRead = qU.readConfig(self.logger,base)
            except(qU.FileNotFound):
                self.logger.critical("One or more needed files do not exist.")
                sys.exit()
            try:
                commonConfig = qU.checkConfig(self.logger,commonConfig,commonConfigRead)
            except(KeyError):
                sys.exit()
            #Reset the verboisty from the config file if needed
            if ll(commonConfig['verbosity']) != self.logger.handlers[1].level:
                self.logger.info("Resetting the log level on the console to {}.".format(commonConfig['verbosity']))
                self.logger.handlers[1].setLevel(ll(commonConfig['verbosity']))
            try:
                analysisConfig = qU.checkConfig(self.logger,analysisConfig,analysisConfigRead)
            except(KeyError):
                sys.exit()
        
        self.commonConf = commonConfig
        self.analysisConf = analysisConfig
        
        logString = "Created quickAnalysis object: "
        for variable, value in commonConfig.iteritems():
            logString += variable+"="+str(value)+","
        for variable, value in analysisConfig.iteritems():
            logString += variable+"="+str(value)+","
        self.logger.info(logString)
            
    def writeConfig(self):

        """Writes all of the initialization variables to the config
        file called <basename>.cfg."""

        qU.writeConfig(quickLogger=self.logger,
                       commonDictionary=self.commonConf,
                       analysisDictionary=self.analysisConf)

    def runSelect(self,run = True,printCmd=False, **kwargs):

        """Runs gtselect on the data using the initialization
        parameters. User selected parameters include the conversion
        type and the eventclass."""

        filter['rad'] = self.analysisConf['rad']
        filter['evclass'] = self.commonConf['eventclass']
        filter['evtype'] = self.commonConf['eventtype']
        filter['evclsmin'] = 0
        filter['evclsmax'] = 10
        filter['infile'] = "@"+self.commonConf['base']+".list"
        filter['outfile'] = self.commonConf['base']+"_filtered.fits"
        filter['ra'] = self.analysisConf['ra']
        filter['dec'] = self.analysisConf['dec']
        filter['tmin'] = self.analysisConf['tmin']
        filter['tmax'] = self.analysisConf['tmax']
        filter['emin'] = self.analysisConf['emin']
        filter['emax'] = self.analysisConf['emax']
        filter['zmax'] = self.analysisConf['zmax']
        filter['convtype'] = self.analysisConf['convtype']

        #Override the settings above with the kwargs if they exist.
        for name,value in kwargs.items():
            filter[name] = value

        qU.runCommand(filter,self.logger,run,printCmd)
        
    def runGTI(self, run = True, **kwargs):

        """Executes gtmktime with the given filter"""

        maketime['scfile'] = self.commonConf['base']+'_SC.fits'
        maketime['filter'] = self.analysisConf['filter']
        maketime['roicut'] = self.analysisConf['roicut']
        maketime['evfile'] = self.commonConf['base']+'_filtered.fits'
        maketime['outfile'] = self.commonConf['base']+'_filtered_gti.fits'
    
        #Override the settings above with the kwargs if they exist.
        for name,value in kwargs.items():
            maketime[name] = value

        qU.runCommand(maketime,self.logger,run)

    def runDIFRSP(self, run = True, **kwargs):

        """Executes gtdiffrsp with the given arguments"""

        diffResps['evfile'] = self.commonConf['base']+'_filtered_gti.fits'
        diffResps['scfile'] = self.commonConf['base']+'_SC.fits'
        diffResps['srcmdl'] = self.analysisConf['model']
        diffResps['irfs'] = self.commonConf['irfs']
    
        #Override the settings above with the kwargs if they exist.
        for name,value in kwargs.items():
            diffResps[name] = value

        qU.runCommand(diffResps,self.logger,run)


    def runLTCube(self, run=True, **kwargs):

        """Generates a livetime cube"""

        expCube['evfile'] = self.commonConf['base']+'_filtered_gti.fits'
        expCube['scfile'] = self.commonConf['base']+'_SC.fits'
        expCube['outfile'] = self.commonConf['base']+'_ltcube.fits'
        expCube['dcostheta'] = 0.025
        expCube['binsz'] = 1
        expCube['zmax'] = self.analysisConf['ltzmax']

        #Override the settings above with the kwargs if they exist.
        for name,value in kwargs.items():
            expCube[name] = value

        np = int(self.commonConf['multicore'])
        
        if(np > 0):
            import gtltcube_mp as ltmp
            ltmp.gtltcube_mp(np, expCube['scfile'], expCube['evfile'], expCube['outfile'],
                             False,expCube['zmax'], 0, 0)
        else:
            qU.runCommand(expCube,self.logger,run)

    def runExpMap(self, run=True, **kwargs):

        """Generates an exposure map that is 10 degrees larger than
        the ROI and has 120 pixels in each direction."""

        expMap['evfile'] = self.commonConf['base']+'_filtered_gti.fits'
        expMap['scfile'] = self.commonConf['base']+'_SC.fits'
        expMap['expcube'] = self.commonConf['base']+'_ltcube.fits'
        expMap['outfile'] = self.commonConf['base']+'_expMap.fits'
        expMap['irfs'] = self.commonConf['irfs']
        expMap['srcrad'] = float(self.analysisConf['rad']) + 10.
        expMap['nlong'] = 120
        expMap['nlat'] = 120
        expMap['nenergies'] = 20

        #Override the settings above with the kwargs if they exist.
        for name,value in kwargs.items():
            expMap[name] = value

        np = int(self.commonConf['multicore'])
        
        if(np > 0):
            import gtexpmap_mp as expmp
            expmp.gtexpmap_mp(expMap['nlong'],expMap['nlat'],np,1,
                              expMap['scfile'],expMap['evfile'],expMap['expcube'], 
                              expMap['irfs'],expMap['srcrad'],expMap['nenergies'],
                              expMap['outfile'],False)
        else:
            qU.runCommand(expMap,self.logger,run)

    def runCCUBE(self, run=True,nbins=30, **kwargs):

        """Generates a counts cube.  The dimensions of which are the
        largest square subtended by the ROI.  Note that if the ROI is
        exceptionally small or the bin size exceptionally large, the
        square might not be the largest posible since the npix
        calculation floors the calculated value.  The number of energy
        bins is logarithmic and is defined by the nbins variable."""
    
        if float(self.analysisConf['nxpix']) < 0 or float(self.analysisConf['nypix']) < 0:
            self.logger.info("Autocalculating nxpix and nypix.")
            self.analysisConf['nxpix'] = qU.NumberOfPixels(float(self.analysisConf['rad']),
                                                           float(self.analysisConf['binsize']))
            self.analysisConf['nypix'] = self.analysisConf['nxpix']
            print self.analysisConf['nypix']
            

        evtbin['evfile'] = self.commonConf['base']+'_filtered_gti.fits'
        evtbin['outfile'] = self.commonConf['base']+'_CCUBE.fits'
        evtbin['algorithm'] = 'CCUBE'
        evtbin['nxpix'] = self.analysisConf['nxpix']
        evtbin['nypix'] = self.analysisConf['nypix']
        evtbin['binsz'] = self.analysisConf['binsize']
        evtbin['coordsys'] = 'CEL'
        evtbin['xref'] = self.analysisConf['ra']
        evtbin['yref'] = self.analysisConf['dec']
        evtbin['axisrot'] = 0
        evtbin['proj'] = self.analysisConf['proj']
        evtbin['ebinalg'] = 'LOG'
        evtbin['emin'] = self.analysisConf['emin']
        evtbin['emax'] = self.analysisConf['emax']
        evtbin['enumbins'] = nbins
        evtbin['scfile'] = self.commonConf['base']+"_SC.fits"

	#Override settings above with kwargs if they exist
	for name, value in kwargs.items():
		evtbin[name] = value

        qU.runCommand(evtbin,self.logger,run)

    def runCMAP(self, run=True):
        
        """Generates a counts map.  The dimensions of which are the
        largest square subtended by the ROI.  Note that if the ROI is
        exceptionally small or the bin size exceptionally large, the
        square might not be the largest posible since the npix
        calculation floors the calculated value."""

        qU.runCMAP(self.logger, 
                   self.commonConf['base'],
                   self.analysisConf['rad'],
                   self.analysisConf['binsize'],
                   self.analysisConf['ra'],
                   self.analysisConf['dec'],
                   self.analysisConf['nxpix'],
                   self.analysisConf['nypix'],
				   self.analysisConf['proj'])

    def runExpCube(self,run=True,nbins=30, ExpBuffer=30, **kwargs):

        """Generates a binned exposure map that is 30 degrees larger
        than the ROI.  The binned exposure map needs to take into
        account the exposure on sources outside of the ROI.  30
        degrees is the size of the PSF at low energies plus some extra
        tens of degrees for security.  You can adjust this buffer by
        setting the ExpBuffer option.  The energy binning is
        logarithmic and the number of energy bins is defined by the
        nbins variable."""

        npix = qU.NumberOfPixels(float(self.analysisConf['rad'])+ExpBuffer, float(self.analysisConf['binsize']))

    	gtexpcube2['infile'] = self.commonConf['base']+"_ltcube.fits"
    	gtexpcube2['cmap'] = self.commonConf['base']+'_CCUBE.fits'
    	gtexpcube2['outfile'] = self.commonConf['base']+"_BinnedExpMap.fits"
    	gtexpcube2['irfs'] = self.commonConf['irfs']
    	gtexpcube2['xref'] = str(self.analysisConf['ra'])
    	gtexpcube2['yref'] = str(self.analysisConf['dec'])
    	gtexpcube2['nxpix'] = str(npix)
    	gtexpcube2['nypix'] = str(npix)
    	gtexpcube2['binsz'] = str(self.analysisConf['binsize'])
    	gtexpcube2['coordsys'] = "CEL"
    	gtexpcube2['axisrot'] = 0
    	gtexpcube2['proj'] = str(self.analysisConf['proj'])
    	gtexpcube2['ebinalg'] = "LOG"
    	gtexpcube2['emin'] = str(self.analysisConf['emin'])
    	gtexpcube2['emax'] = str(self.analysisConf['emax'])
    	gtexpcube2['enumbins'] = str(nbins)

    	#Override settings above with kwargs if they exist
    	for name, value in kwargs.items():
    		gtexpcube2[name] = value
	
    	qU.runCommand(gtexpcube2, self.logger, run)
	
	"""
        cmd = "gtexpcube2 infile="+self.commonConf['base']+"_ltcube.fits"\
            +" cmap=none"\
            +" outfile="+self.commonConf['base']+"_BinnedExpMap.fits"\
            +" irfs="+self.commonConf['irfs']\
            +" xref="+str(self.analysisConf['ra'])\
            +" yref="+str(self.analysisConf['dec'])\
            +" nxpix="+str(npix)\
            +" nypix="+str(npix)\
            +" binsz="+str(self.analysisConf['binsize'])\
            +" coordsys=CEL"\
            +" axisrot=0"\
            +" proj=AIT"\
            +" ebinalg=LOG"\
            +" emin="+str(self.analysisConf['emin'])\
            +" emax="+str(self.analysisConf['emax'])\
            +" enumbins="+str(nbins)
            
        if(run):
            os.system(cmd)
            self.logger.info(cmd)
        else:
            print cmd"""

    def generateXMLmodel(self):
        
        """Calls the quickUtils function to make an XML model of your
        region based on the 2FGL. make2FGLXml.py needs to be in your
        python path.  This needs to have the galactic and isotropic
        diffuse models in your working directory as well as the 2FGL
        catalog in FITS format.  See the corresponding function in
        quickUtils for more details."""
        
        try:
            qU.generateXMLmodel(self.logger, self.commonConf['base'])
        except(qU.FileNotFound):
            self.logger.critical("One or more needed files do not exist")
            exit()

    def runSrcMaps(self, run=True, makeModel=True, **kwargs):

        """Generates a source map for your region.  Checks to make
        sure that there's an XML model to be had and if not, creates
        one from the 2FGL."""

	if makeModel:
		self.generateXMLmodel()
	"""
	# This clashes with quickCurve. If you want this functionality back, put it in runAll() and the cli

        try:
            qU.checkForFiles(self.logger,[self.commonConf['base']+"_CCUBE.fits",
                                       self.commonConf['base']+"_ltcube.fits",
                                       self.commonConf['base']+"_BinnedExpMap.fits",
                                       self.commonConf['base']+"_SC.fits",])
        except(qU.FileNotFound):
            self.logger.critical("One or more needed files do not exist")
            sys.exit()"""

        srcMaps['scfile'] = self.commonConf['base']+"_SC.fits"
        srcMaps['expcube'] = self.commonConf['base']+"_ltcube.fits"
        srcMaps['cmap'] = self.commonConf['base']+"_CCUBE.fits"
        srcMaps['srcmdl'] = self.commonConf['base']+"_model.xml"
        srcMaps['bexpmap'] = self.commonConf['base']+"_BinnedExpMap.fits"
        srcMaps['outfile'] = self.commonConf['base']+"_srcMaps.fits"
        srcMaps['irfs'] = self.commonConf['irfs']
        srcMaps['rfactor'] = 4
        srcMaps['emapbnds'] = "yes"

	#Override settings from kwargs if they exist
	for name, value in kwargs.items():
		srcMaps[name] = value

        qU.runCommand(srcMaps,self.logger,run)

    def runModelMap(self, run=True):

        """Wrapper for the same function in quickUtils"""

        qU.runModelMap(self.logger,self.commonConf['base'],'',self.commonConf['irfs'],False,run)


    def runModelCube(self, run=True):

        """Wrapper for the same function in quickUtils"""

        qU.runModelCube(self.logger,self.commonConf['base'],'',self.commonConf['irfs'],True,run)

    def runAll(self, run=True):

        """Does a full event selection and exposure calculation.  This
        is the function called when this module is run from the
        command line.  You need to have two files to start with:
        <basename>.list and <basename>_SC.fits.  The first one is just
        a text file with a list of the raw data files (one per line)
        and the other is the spacecraft file.  <basename> is a user
        defined prefix (usually the source name but not necissarily).
        Returns an exception if any of the files are not found."""

        self.logger.info("***Checking for files***")
        try:
            qU.checkForFiles(self.logger,[self.commonConf['base']+".list",self.commonConf['base']+"_SC.fits"])
        except(qU.FileNotFound):
            self.logger.critical("One or more needed files do not exist")
            sys.exit()
        self.logger.info("***Running gtselect***")
        self.runSelect(run)
        self.logger.info("***Running gtmktime***")
        self.runGTI(run)
        self.logger.info("***Running gtltcube***")
        self.runLTCube(run)

        if(self.commonConf['binned']):
            self.logger.info("***Running gtbin***")
            self.runCCUBE(run)
            self.logger.info("***Running gtexpcube2***")
            self.runExpCube(run)
            self.logger.info("***Running gtsrcMaps***")
            self.runSrcMaps(run)
        else:
            self.logger.info("***Running gtexpmap***")
            self.runExpMap(run)