def make_spectrum(bins, index, linefile="$ATOMDB/apec_line.fits",\ cocofile="$ATOMDB/apec_coco.fits",\ binunits='keV', broadening=False, broadenunits='keV', \ elements=False, abund=False, dummyfirst=False,\ dolines = True, docont=True, dopseudo=True): r""" make_spectrum is the most generic "make me a spectrum" routine. It returns the emissivity in counts cm^3 s^-1 bin^-1. Parameters ---------- bins : array(float) The bin edges for the spectrum to be calculated on, in \ units of keV or Angstroms. Must be monotonically\ increasing. Spectrum will return len(bins)-1 values. index : int The index to plot the spectrum from. note that the AtomDB files\ the emission starts in hdu number 2. So for the first block, you\ set index=2 linefile : str The file containing all the line emission. Defaults to \ "$ATOMDB/apec_line.fits" cocofile : str The file containing all the continuum emission. Defaults to \ "$ATOMDB/apec_coco.fits" binunits : {'keV','A'} The energy units for bins. "keV" or "A". Default keV. broadening : float Line broadening to be applied broadenunits : {'keV','A'} Units of line broadening "keV" or "A". Default keV. elements : iterable of int Elements to include, listed by atomic number. if not set, include all. abund : iterable of float, length same as elements. If set, and array of length (elements) with the abundances of each\ element relative to the Andres and Grevesse values. Otherwise, assumed to\ be 1.0 for all elements dummyfirst : bool If true, add a "0" to the beginning of the return array so it is of the same length as bins (can be useful for plotting results) dolines : bool Include lines in the spectrum docont : bool Include the continuum in the spectrum dopseudo : bool Include the pseudocontinuum in the spectrum. Returns ------- array of floats Emissivity in counts cm^3 s^-1 bin^-1. """ # History # ------- # Version 0.1 - initial release # Adam Foster July 17th 2015 # # Version 0.2 # Added dummyfirst keyword # Adam Foster July 21st 2015 # # set up the bins if (sum((bins[1:]-bins[:-1])<0) > 0): print "*** ERROR: bins must be monotonically increasing. Exiting ***" return -1 if binunits.lower()=='kev': ebins = bins*1.0 elif binunits.lower() in ['a', 'angstrom', 'angstroms']: ebins = const.HC_IN_KEV_A/bins[::-1] else: print "*** ERROR: unknown binning unit %s, Must be keV or A. Exiting ***"%\ (binunits) if util.keyword_check(linefile): # ok, we should do something with this # if it is a string, look for the file name if isinstance(linefile, basestring): lfile = os.path.expandvars(linefile) if not os.path.isfile(lfile): print "*** ERROR: no such file %s. Exiting ***" %(lfile) return -1 ldat = pyfits.open(lfile) elif isinstance(linefile, pyfits.hdu.hdulist.HDUList): # no need to do anything, file is already open ldat = linefile else: print "Unknown data type for linefile. Please pass a string or an HDUList" return -1 if util.keyword_check(cocofile): if isinstance(cocofile, basestring): cfile = os.path.expandvars(cocofile) if not os.path.isfile(cfile): print "*** ERROR: no such file %s. Exiting ***" %(cfile) return -1 cdat = pyfits.open(cfile) elif isinstance(cocofile, pyfits.hdu.hdulist.HDUList): # no need to do anything, file is already open cdat = cocofile else: print "Unknown data type for cocofile. Please pass a string or an HDUList" return # lfile = os.path.expandvars(linefile) # cfile = os.path.expandvars(cocofile) # if not os.path.isfile(lfile): # print "*** ERROR: no such file %s. Exiting ***" %(lfile) # return -1 # if not os.path.isfile(cfile): # print "*** ERROR: no such file %s. Exiting ***" %(cfile) # return -1 # open the files # ldat = pyfits.open(lfile) # cdat = pyfits.open(cfile) # get the index if ((index < 2) | (index > len(ldat))): print "*** ERRROR: Index must be in range %i to %i"%(2, len(ldat)-1) return -1 lldat = ldat[index].data ccdat = cdat[index].data if not util.keyword_check(elements): Zl = util.unique(lldat['element']) Zc = util.unique(ccdat['Z']) Zlist = util.unique(numpy.append(Zl,Zc)) else: Zlist = elements if not util.keyword_check(abund): abund= numpy.ones(len(Zlist)) lspectrum = numpy.zeros(len(bins)-1, dtype=float) cspectrum = numpy.zeros(len(bins)-1, dtype=float) if dolines: for iZ, Z in enumerate(Zlist): # ADD LINES lspectrum += add_lines(Z, abund[iZ], lldat, ebins, broadening=broadening, broadenunits=broadenunits) if docont | dopseudo: for iZ, Z in enumerate(Zlist): # ADD CONTINUUM cspectrum += make_ion_index_continuum(ebins, Z, cocofile=ccdat,\ binunits=binunits, no_coco=-docont,\ no_pseudo=-dopseudo)*abund[iZ] # broaden the continuum if required: if broadening: cspectrum = broaden_continuum(ebins, cspectrum, binunits = binunits, \ broadening=broadening,\ broadenunits=broadenunits) if dummyfirst: return numpy.append([0], cspectrum+lspectrum) else: return cspectrum+lspectrum
def make_ion_spectrum(bins, index, Z,z1, linefile="$ATOMDB/apec_nei_line.fits",\ cocofile="$ATOMDB/apec_nei_comp.fits",\ binunits='keV', broadening=False, broadenunits='keV', \ abund=False, dummyfirst=False, nei = True,\ dolines = True, docont=True, dopseudo=True): r""" make_spectrum is the most generic "make me a spectrum" routine. It returns the emissivity in counts cm^3 s^-1 bin^-1. Parameters ---------- bins : array(float) The bin edges for the spectrum to be calculated on, in \ units of keV or Angstroms. Must be monotonically\ increasing. Spectrum will return len(bins)-1 values. index : int The index to plot the spectrum from. note that the AtomDB files\ the emission starts in hdu number 2. So for the first block, you\ set index=2 Z : int Element of spectrum (e.g. 6 for carbon) z1 : int Ion charge +1 for the spectrum (e.g. 3 for C III) linefile : str or HDUList The file containing all the line emission. Defaults to \ "$ATOMDB/apec_line.fits". Can also pass in the opened file, \ i.e. "linefile = pyatomdb.pyfits.open('apec_nei_line.fits')" cocofile : str or HDUList The file containing all the continuum emission. Defaults to \ "$ATOMDB/apec_coco.fits". Can also pass in the opened file, \ i.e. "cocofile = pyatomdb.pyfits.open('apec_nei_comp.fits')" binunits : {'keV','A'} The energy units for bins. "keV" or "A". Default keV. broadening : float Line broadening to be applied broadenunits : {'keV','A'} Units of line broadening "keV" or "A". Default keV. elements : iterable of int Elements to include, listed by atomic number. if not set, include all. abund : iterable of float, length same as elements. If set, and array of length (elements) with the abundances of each\ element relative to the Andres and Grevesse values. Otherwise, assumed to\ be 1.0 for all elements dummyfirst : bool If true, add a "0" to the beginning of the return array so it is of the same length as bins (can be useful for plotting results) nei : bool If set, return the spectrum from the driving ion being Z, rmJ. If not set, return the spectrum for the collisional ionization equilibrium *BUT* note that the continuum will be wrong, as it is provided for each element as a whole. dolines : bool Include lines in the spectrum docont : bool Include the continuum in the spectrum dopseudo : bool Include the pseudocontinuum in the spectrum. Returns ------- array of floats Emissivity in counts cm^3 s^-1 bin^-1. """ # History # ------- # Version 0.1 - initial release # Adam Foster July 17th 2015 # # Version 0.2 # Added dummyfirst keyword # Adam Foster July 21st 2015 # # set up the bins if (sum((bins[1:]-bins[:-1])<0) > 0): print "*** ERROR: bins must be monotonically increasing. Exiting ***" return -1 if binunits.lower()=='kev': ebins = bins*1.0 elif binunits.lower() in ['a', 'angstrom', 'angstroms']: ebins = const.HC_IN_KEV_A/bins[::-1] else: print "*** ERROR: unknown binning unit %s, Must be keV or A. Exiting ***"%\ (binunits) # check the files exist # first, check if the line file is set if util.keyword_check(linefile): # ok, we should do something with this # if it is a string, look for the file name if isinstance(linefile, basestring): if ((linefile == "$ATOMDB/apec_nei_line.fits") & (nei==False)): linefile = "$ATOMDB/apec_line.fits" lfile = os.path.expandvars(linefile) if not os.path.isfile(lfile): print "*** ERROR: no such file %s. Exiting ***" %(lfile) return -1 ldat = pyfits.open(lfile) elif isinstance(linefile, pyfits.hdu.hdulist.HDUList): # no need to do anything, file is already open ldat = linefile else: print "Unknown data type for linefile. Please pass a string or an HDUList" return -1 if util.keyword_check(cocofile): if isinstance(cocofile, basestring): if ((cocofile == "$ATOMDB/apec_nei_comp.fits") & (nei==False)): cocofile = "$ATOMDB/apec_coco.fits" cfile = os.path.expandvars(cocofile) if not os.path.isfile(cfile): print "*** ERROR: no such file %s. Exiting ***" %(cfile) return -1 cdat = pyfits.open(cfile) elif isinstance(cocofile, pyfits.hdu.hdulist.HDUList): # no need to do anything, file is already open cdat = cocofile else: print "Unknown data type for cocofile. Please pass a string or an HDUList" return # get the index if ((index < 2) | (index > len(ldat))): print "*** ERRROR: Index must be in range %i to %i"%(2, len(ldat)-1) return -1 lldat = ldat[index].data ccdat = cdat[index].data if not abund: abund= 1.0 lspectrum = numpy.zeros(len(bins)-1, dtype=float) cspectrum = numpy.zeros(len(bins)-1, dtype=float) pspectrum = numpy.zeros(len(bins)-1, dtype=float) if dolines: # ADD LINES if nei: lspectrum += add_lines(Z, abund, lldat, ebins, broadening=broadening,\ broadenunits=broadenunits,z1_drv=z1) else: lspectrum += add_lines(Z, abund, lldat, ebins,broadening, broadenunits,z1=z1) if docont: # ADD LINES if nei: cspectrum += make_ion_index_continuum(ebins, Z, cocofile=ccdat,\ ion = z1, binunits=binunits,\ no_pseudo=True)*abund else: cspectrum += make_ion_index_continuum(ebins, Z, cocofile=ccdat,\ ion = 0, binunits=binunits,\ no_pseudo=True)*abund if dopseudo: # ADD LINES if nei: pspectrum += make_ion_index_continuum(ebins, Z, cocofile=ccdat,\ ion = z1, binunits=binunits, \ no_coco=True)*abund else: pspectrum += make_ion_index_continuum(ebins, Z, cocofile=ccdat,\ ion = 0, binunits=binunits, \ no_coco=True)*abund # broaden the continuum if required: if broadening: cspectrum = broaden_continuum(ebins, cspectrum, binunits = binunits, \ broadening=broadening,\ broadenunits=broadenunits) pspectrum = broaden_continuum(ebins, pspectrum, binunits = binunits, \ broadening=broadening,\ broadenunits=broadenunits) if dummyfirst: return numpy.append([0], cspectrum+lspectrum+pspectrum) else: return cspectrum+lspectrum+pspectrum