def set_arrays(filename, args, fields=None, ascii=True, clobber=False): if os.path.isfile(filename) and not clobber: raise IOErr("filefound", filename) if not numpy.iterable(args) or len(args) == 0: raise IOErr('noarrayswrite') if not numpy.iterable(args[0]): raise IOErr('noarrayswrite') size = len(args[0]) for arg in args: if not numpy.iterable(arg): raise IOErr('noarrayswrite') elif len(arg) != size: raise IOErr('arraysnoteq') if ascii and '[' not in filename and ']' not in filename: filename += "[opt kernel=text/simple]" tbl = pycrates.TABLECrate() if fields is None: fields = ['col%i' % (ii + 1) for ii in range(len(args))] if len(args) != len(fields): raise IOErr('toomanycols', str(len(fields)), str(len(args))) for val, name in izip(args, fields): _set_column(tbl, name, val) pycrates.write_file(tbl, filename, clobber=True) close_crate_dataset(tbl.get_dataset())
def set_table_data(filename, data, col_names, hdr=None, hdrnames=None, ascii=False, clobber=False, packup=False): if not packup and os.path.isfile(filename) and not clobber: raise IOErr("filefound", filename) tbl = pycrates.TABLECrate() col_names = [name for name in col_names if data[name] is not None] col_names.remove('name') try: for name in col_names: if data[name] is None: continue _set_column(tbl, name, data[name]) finally: if packup: return tbl if ascii and '[' not in filename and ']' not in filename: filename += "[opt kernel=text/simple]" # pycrates.write_file(tbl, filename) tbl.write(filename, clobber=True) close_crate_dataset(tbl.get_dataset())
def _arrays_to_crate(arrays, colnames=None): """Create a TABLECrate that contains the contents of the columns in arrays (each element is a column). If colnames is not None then they are used as the column names, otherwise values of col1 to colN are used. The data arrays used in the crate are references of the input values (i.e. they are not copied, unlike _sarray_to_crate). Not all data types are necessarily supported. """ na = len(arrays) if colnames is None: colnames = ["col{}".format(i) for i in range(1, na + 1)] else: nc = len(colnames) if nc != na: raise ValueError("Number of columns ({}) and column names ({}) does not match.".format(nc, na)) cr = pycrates.TABLECrate() cr.name = "TABLE" for (col, name) in zip(arrays, colnames): add_colvals(cr, name, col) return cr
def set_table_data(filename, data, col_names, hdr=None, hdrnames=None, ascii=False, clobber=False, packup=False): if not packup and not clobber and os.path.isfile(filename): raise IOErr("filefound", filename) tbl = pycrates.TABLECrate() try: for name in col_names: _set_column(tbl, name, data[name]) finally: if packup: return tbl if ascii and '[' not in filename and ']' not in filename: filename += "[opt kernel=text/simple]" # pycrates.write_file(tbl, filename) tbl.write(filename, clobber=True)
def __init__(self, fov, pixsize=1): """Read in the data from the file or crate fov. An IOError is thrown if the input does not contain the necessary information. pixsize is the pixelsize to use for the axis grids; it must be > 0 """ if isinstance(fov, pycrates.TABLECrate): cr = fov # Unfortunately we lose any filter applied to the # filename by the caller using this approach. # fname = cr.get_filename() else: cr = pycrates.TABLECrate(fov, mode="r") fname = fov if pixsize <= 0: raise ValueError("pixsize must be > 0, not {}".format(pixsize)) self.filename = os.path.abspath(fname) self.pixsize = pixsize self._read_input(cr)
def _dict_to_crate(d, colnames=None): """Create a TABLECrate that contains the contents of the dictionary. If colnames is not None then it it an array of names that determines the order to add the columns to the crate (and can be used to filter out columns). Use of collections.OrderedDict rather than a normal dictionary can also be used to determine the order of the columns. The data arrays used in the crate are references of the input values (i.e. they are not copied, unlike _sarray_to_crate). Not all data types are necessarily supported. """ cr = pycrates.TABLECrate() cr.name = "TABLE" if colnames is None: names = d.keys() else: names = colnames for cname in names: add_colvals(cr, cname, d[cname]) return cr
def _sarray_to_crate(sa, colnames=None): """Create a TABLECrate that contains the contents of the supplied structured/rec array. If colnames is not None then it it an array of names that determines the order to add the columns to the crate (and can be used to filter out columns in sa). The arrays in the structured array are explicitly copied into the crate to avoid some memory issues seen in CIAO 4.4 testing. However, this may not resolve all issues so it is suggested that this routine is not used at this time. Not all data types are necessarily supported. """ cr = pycrates.TABLECrate() cr.name = "TABLE" if colnames is None: names = sa.dtype.names else: names = colnames for cname in names: # We copy the values to avoid an issue on writing out the # crate; not sure if this is a Crates or NumPy problem # and whether this has been fixed since CIAO 4.4 when it # was seen # add_colvals(cr, cname, sa[cname].copy()) return cr
def set_pha_data(filename, data, col_names, header=None, ascii=False, clobber=False, packup=False): if not packup and os.path.isfile(filename) and not clobber: raise IOErr("filefound", filename) phadataset = pycrates.phacratedataset.PHACrateDataset() # FIXME: Placeholder for pycrates2 bug phadataset.set_rw_mode('rw') pha = pycrates.TABLECrate() pha.name = "SPECTRUM" try: # Write header values using CrateKey objects for key in header.keys(): if header[key] is None: continue _set_key(pha, key, header[key]) # Write column values using CrateData objects for name in col_names: if data[name] is None: continue _set_column(pha, name, data[name]) finally: phadataset.add_crate(pha) if packup: return phadataset if ascii and '[' not in filename and ']' not in filename: filename += "[opt kernel=text/simple]" # pycrates.write_pha(phadataset, filename) phadataset.write(filename, clobber=True) close_crate_dataset(phadataset)
def get_caldb_installed(caldb=None): """What CIAO CALDB is installed (version and release date)? Parameters ---------- caldb : str, optional If set, the directory to search in, otherwise the CALDB environment variable is used. Returns ------- version, date The CIAO CALDB version, as a string, and the release date of the version (as a date object) of the installed CIAO CALDB. See Also -------- get_caldb_installed_date, get_caldb_installed_version """ if caldb is None: caldb = get_caldb_dir() fname = os.path.join(caldb, "docs/chandra/caldb_version/caldb_version.fits") cr = pycrates.TABLECrate(fname, mode='r') for cname in ["CALDB_VER", "CALDB_DATE"]: if not cr.column_exists(cname): raise IOError( "Unable to find the {} column in the CALDB version file.". format(cname)) cversion = pycrates.copy_colvals(cr, "CALDB_VER")[-1] cdate = pycrates.copy_colvals(cr, "CALDB_DATE")[-1] cversion = cversion.strip() cdate = cdate.strip() return (cversion, todate(cdate))
def write_draws(draws, outfile, params=None, format="ascii"): """Writes the draws (except for iteration number 0) to the file outfile. Over-writes the file if it exists. If params is given then it should be the output of get_parameter_info and is used to add extra information to the output file (well, it will do, for now it does not). The output format is determined by the format parameter; it can be one of "fits" - FITS binary table "ascii" - simple ASCII table (two comment lines then data) "dtf" - ASCII file in CIAO TEXT/DTF format (CIAO tools can treat it similarly to a FITS table) None - let Crates determine, probably because you have specified an option within the outfile name (specialised use only) """ formats = {"ascii": "text/simple", "dtf": "text/dtf", "fits": "fits"} if format != None and not formats.has_key(format.lower()): raise RuntimeError, "Unknown output format '%s'" % format # Use crates to create the output file. # cr = crates.TABLECrate() # We need to store the crate data objects so that they are not # garbage collected until after the write_file() call. # store = {} def create_col(cname, cval): store[cname] = crates.CrateData() store[cname].name = cname if 1 != store[cname].load(cval, 1): raise RuntimeError, "Unable to add column %s to the Crate Data object." % cname if 1 != crates.add_col(cr, store[cname]): raise RuntimeError, "Unable to add column %s to the Crates." % cname def create_key(kname, kval, desc=None): store[kname] = crates.CrateKey() store[kname].name = kname if desc != None: store[kname].desc = desc if 1 != store[kname].load(kval): raise RuntimeError, "Unable to set key %s to %g" % (name, kval) if 1 != crates.add_key(cr, store[kname]): raise RuntimeError, "Unable to add key %s to Crates." % kname # Column data, and then keywords. # Note that we do not write out any iteration numbered 0 as this is # assumed to be the "best-fit" position. # idx = draws["iteration"] > 0 for cname in ["iteration", "accept", "statistic", "alphas"]: create_col(cname, draws[cname][idx]) for cname in draws["parnames"]: create_col(cname, draws[cname][idx]) if params == None: create_key("statmin", draws["statistic"][0], "statistic at best-fit location") for k in draws["parnames"]: create_key("P_%s" % k, draws[k][0], "best-fit value") else: create_key("statmin", params["statval"], "statistic at best-fit location") create_key("sigma", params["sigma"], "sigma value for lower/upper limits") for (k, v, l, h) in zip(params["parnames"], params["parvals"], params["parmins"], params["parmaxes"]): create_key("p_%s" % k, v, "best-fit value") create_key("dl_%s" % k, l, "best-fit lower limit") create_key("dh_%s" % k, h, "best-fit upper limit") # Write out the file # if format == None: outname = outfile else: outname = outfile + "[opt kernel=%s]" % formats[format.lower()] if 1 != crates.write_file(cr, outname): raise IOError, "Unable to write data out to '%s'" % outname print "Created: %s" % outfile
def _estimate_expmap(self, *args): """Estimate the exposure map given an ARF. Although the arguments are listed with parameter names below, the function **does not** accept named arguments. It uses positional arguments and type checks to determine the parameters. Parameters ---------- crate A TABLECrate, containing ``energ_lo``, ``energ_hi``, and ``specresp`` columns. filename : string The name of an ARF file xlo, xhi, y : arrays of numbers The arrays taken to be the ``energ_lo``, ``energ_hi``, and ``specresp`` columns Return ------ expmap : number An estimate of the exposure map at the position of the source, and has units of cm^2 count / self.fluxtype Notes ----- The ARF is linearly interpolated onto the energy grid of the dataset and the weighted sum calculated. The ARF is assumed to have units of cm^2 count / photon, and be defined on a grid given in keV. The ``estimate_instmap()`` method should be called in preference to this routine. """ nargs = len(args) if nargs == 3: elo = args[0] ehi = args[1] specresp = args[2] if len(elo) == 1 or len(ehi) == 1 or len(specresp) == 1: emsg = "Expected three arrays of the same " + \ "length, with more than one element in" raise TypeError(emsg) if len(elo) != len(ehi) or len(elo) != len(specresp): emsg = "Expected three arrays of the same length" raise ValueError(emsg) elif nargs != 1: emsg = "_estimate_expmap() takes 2 or 4 arguments " + \ "({} given)".format(nargs + 1) raise TypeError(emsg) else: if isinstance(args[0], pycrates.TABLECrate): cr = args[0] else: cr = pycrates.TABLECrate(args[0], mode="r") try: elo = cr.get_column("ENERG_LO").values.copy() ehi = cr.get_column("ENERG_HI").values.copy() specresp = cr.get_column("SPECRESP").values.copy() except ValueError as e: fname = cr.get_filename() raise ValueError("Crate {} - {}".format(fname, e)) # Interpolate using the mid-point of the ARF # onto the mid-point of the grid if necessary. # emid = 0.5 * (elo + ehi) if emid.shape == self.xmid.shape and \ np.all(emid == self.xmid): arf = specresp else: arf = su.interpolate(self.xmid, emid, specresp) arf = np.asarray(arf, dtype=self.weight.dtype) arf[arf < 0] = 0.0 return np.sum(self.weight * arf)
def dump_qa(ensemble, outdir, ctr, outline, creator=None, revision=1, color='green'): """Dump the QA data to a region-like FITS file The output files are qa.<ctr>.v<version>.[fits|reg], where the integers are written as 3-character, zero-padded values. Parameters ---------- ensemble : string The ensemble value, written to the header as the ENSEMBLE keyword. outdir : string This output directory ctr : int Used for the file name and added to the header as the HULLCPT keyword. outline : dict The hull data to write out. creator : None or str, optional The name to use for the CREATOR field in the header. revision : int The value to write out to the header as the CHSVER keyword. color : str The color for the DS9 region files. Notes ------ I'd like to add a transform to POS but it is a little-bit involved and I don't have time to dig up the code, so just add an explicit column instead of a virtual one. It should be the case that the base stack is the same for each row, but leave as a column rather than move to a header keyword for now. """ assert chs_status.is_qa(outline['status']) assert outline['eqpos'] is not None assert outline['pos'] is not None assert outline['base_stack'] is not None idx = outline['status'].find('-') if idx == -1: reason = "unknown" else: reason = outline['status'][idx + 1:] outfile = os.path.join(outdir, 'qa.{:03d}.v{:03d}.fits'.format(ctr, revision)) cr = pycrates.TABLECrate() cr.name = 'QACASE' utils.add_standard_header(cr, creator=creator, revision=revision) utils.add_header(cr, [('ENSEMBLE', ensemble, 'The ensemble'), ('HULLCPT', ctr, 'The Master_Id of the hull'), ('QREASON', reason, 'Why is this a QA case?')]) eqpos = outline['eqpos'] pos = outline['pos'] assert len(pos) == len(eqpos) ncpts = len(pos) utils.add_col(cr, 'COMPONENT', np.arange(1, ncpts + 1)) utils.add_col(cr, 'SHAPE', ['Polygon'] * ncpts) utils.add_col(cr, 'BASE_STK', [outline['base_stack']] * ncpts, desc='The stack used for SKY coord system, or NONE') nvertex = [] for poly in pos: x = poly[0] y = poly[1] xidx = np.isfinite(x) yidx = np.isfinite(y) assert (xidx == yidx).all() nvertex.append(xidx.sum()) utils.add_col(cr, 'NVERTEX', nvertex, desc='The number of vertexes in the closed hull') nmax = max(nvertex) pos_out = np.full((ncpts, 2, nmax), np.nan, dtype=np.float64) eqpos_out = np.full((ncpts, 2, nmax), np.nan, dtype=np.float64) for i, dvals in enumerate(zip(pos, eqpos)): npts = nvertex[i] phys, cel = dvals pos_out[i, :, :npts] = phys eqpos_out[i, :, :npts] = cel col = pycrates.create_vector_column('POS', ['X', 'Y']) col.desc = 'The master hull vertices' col.unit = 'pixel' col.values = pos_out cr.add_column(col) col = pycrates.create_vector_column('EQPOS', ['RA', 'DEC']) col.desc = 'The master hull vertices' col.unit = 'degree' col.values = eqpos_out cr.add_column(col) cr.write(outfile) print("Created: {}".format(outfile)) outfile = os.path.join(outdir, 'qa.{:03d}.v{:03d}.reg'.format(ctr, revision)) with open(outfile, 'w') as ofh: ds9_header(ofh, color=color) for i, cel in enumerate(eqpos): npts = nvertex[i] ostr = ds9_shape(cel[:, :npts]) ostr += ' # text={{Id={} {}}}\n'.format(ctr, i + 1) ofh.write(ostr) print("Created: {}".format(outfile))