def test_dendrogramComputation(self): d = Dendrogram(self.data, minimum_npix=8, minimum_delta=0.3, minimum_flux=1.4, verbose=False) num_leaves = len(d.get_leaves()) self.assertEqual(num_leaves,55) # This data with these parameters should produce 55 leaves # Now check every pixel in the data cube (this takes a while). # The following loop construct may look crazy, but it is a more # efficient way of iterating through the array than using a regular # nditer with multi_index. for coord in np.array(np.unravel_index( np.arange(self.data.size), self.data.shape)).transpose(): coord = tuple(coord) f = self.data[coord] if (f < 1.4): self.assertEqual(d.item_at(coord), None) else: item = d.item_at(coord) if item: # The current pixel is associated with part of the dendrogram. self.assertIn(coord, item.coords, "Pixel at {0} is claimed to be part of {1}, but that item does not contain the coordinate {0}!".format(coord, item)) fmax_item, _, fmax = item.get_peak_recursive() if fmax_item is item: # The current pixel is the peak pixel in this item pass else: self.assertTrue(fmax >= f)
def test_4dim(self): " Test 4-dimensional data " data = np.zeros((5,5,5,5)) # Create a 5x5x5x5 array initialized to zero # N-dimensional data is hard to conceptualize so I've kept this simple. # Create a local maximum (value 5) at the centre data[2,2,2,2] = 5 # add some points around it of intensity 3. Note that '1:4:2' is equivalent to saying indices '1' and '3' data[2,1:4:2,2,2] = data[2,2,1:4:2,2] = data[2,2,2,1:4:2] = 3 # Add a trail of points of value 2 connecting one of those 3s to a 4 data[0:3,0,2,2] = 2 # Sets [0,0,2,2], [1,0,2,2], and [2,0,2,2] all equal to 2 -> will connect to the '3' at [2,1,2,2] data[0,0,2,1] = 4 # Now dendrogram it: d = Dendrogram(data, minimum_flux=1, verbose=False) # We expect two leaves: leaves = d.get_leaves() self.assertEqual(len(leaves), 2) # We expect one branch: branches = [i for i in d.all_items if type(i) is Branch] self.assertEqual(len(branches), 1) self.assertEqual(len(d.trunk), 1) self.assertEqual(d.trunk[0], branches[0]) # The maxima of each leaf should be at [2,2,2,2] and [0,3,2,1] for leaf in leaves: self.assertIn(leaf.peak, ( ((2,2,2,2), 5.), ((0,0,2,1),4.) ) ) self.assertNotEqual(leaves[0].peak, leaves[1].peak) # Check out a few more properties of the leaf around the global maximum: leaf = d.item_at((2,2,2,2)) self.assertEqual(leaf.fmax, 5) self.assertEqual(leaf.fmin, 2) self.assertEqual(leaf.npix, 1+6+2) # Contains 1x '5', 6x '3', and 2x '2'. The other '2' should be in the branch # Check that the only pixel in the branch is a '2' at [0,0,2,2] self.assertEqual((branches[0].coords, branches[0].f), ( [(0,0,2,2),],[2.,] ))
def get_dendrogram(self, max_pos): # if the dendrogram file doesn't exist if not os.path.isfile('dendrogram.fits'): dendro = Dendrogram.compute(self.vol_data, min_value=1.0, min_delta=1, min_npix=10, verbose=True) dendro.save_to('dendrogram.fits') dendro = Dendrogram.load_from('dendrogram.fits') substructure = dendro.structure_at(max_pos) # max_pos should be (z, y, x) dendro_mask = substructure.get_mask(shape=self.vol_data.shape) return dendro_mask
def main(): data = fits.getdata(os.path.join('benchmark_data', '2d.fits')) for outfile in '2d1.fits 2d2.fits 2d3.fits'.split(): d = Dendrogram.compute(data, verbose=True, **BENCHMARKS[outfile]) d.save_to(os.path.join('benchmark_data', outfile)) data = fits.getdata(os.path.join('benchmark_data', '3d.fits')) for outfile in '3d1.fits 3d2.fits 3d3.fits'.split(): d = Dendrogram.compute(data, verbose=True, **BENCHMARKS[outfile]) d.save_to(os.path.join('benchmark_data', outfile))
def get_dendrogram(self, max_pos): # if the dendrogram file doesn't exist if not os.path.isfile('dendrogram.fits'): dendro = Dendrogram.compute(self.vol_data, min_value=1.0, min_delta=1, min_npix=10, verbose=True) dendro.save_to('dendrogram.fits') dendro = Dendrogram.load_from('dendrogram.fits') substructure = dendro.structure_at( max_pos) # max_pos should be (z, y, x) dendro_mask = substructure.get_mask(shape=self.vol_data.shape) return dendro_mask
def load_dendro(filename): """ Load a dendrogram saved by the astrodendro package :param file: Path to a dendrogram file :returns: A list of 2 glue Data objects: the original dataset, and dendrogram. """ label = data_label(filename) dg = Dendrogram.load_from(filename) structs = np.arange(len(dg)) parent = np.array([ dg[i].parent.idx if dg[i].parent is not None else -1 for i in structs ]) height = np.array([dg[i].height for i in structs]) pk = np.array([dg[i].get_peak(True)[1] for i in structs]) dendro = Data(parent=parent, height=height, peak=pk, label="{} [dendrogram]".format(label)) im = Data(intensity=dg.data, structure=dg.index_map, label="{} [data]".format(label)) im.join_on_key(dendro, 'structure', dendro.pixel_component_ids[0]) return [dendro, im]
def calc_dendrogram(data,sigma,snr,delta,ppb, save=False,fout='temp'): # Survey designs # sigma - K, noise level # ppb - pixels/beam # delta - flux derivation between sources def custom_independent(structure, index=None, value=None): peak_index, peak_value = structure.get_peak() return peak_value > 1.5*sigma d = Dendrogram.compute(data, min_value=snr*sigma, \ min_delta=delta*sigma, min_npix=ppb*ppb, \ is_independent=custom_independent, \ verbose = 1) #v=d.viewer() #v.show() #%&%&%&%&%&%&%&%&%&%&%&%&%&% # Generate the catalog #%&%&%&%&%&%&%&%&%&%&%&%&%&% #print("Generate a catalog of dendrogram structures") #metadata = {} #metadata['data_unit'] = u.Jy #This should be Kelvin (not yet implemented)! #cat = ppv_catalog(d, metadata) #print(cat) if save: d.save_to(fout+'.hdf5') return d
def test_identify_edge_structures_4(): # Case 4: something more complex. data = np.zeros((4,5,6)) # a non-edge structure data[2,2,1] = 1 data[2,2,2] = 1 # an edge structure on zeros data[0,0,3] = 1 data[0,1,3] = 1 data[1,1,3] = 1 # an edge structure on the max side data[1,1,5] = 1 data[2,1,5] = 1 d = Dendrogram.compute(data, min_value=0) on_edge = identify_edge_structures(d) expected_onedge_len = 2 expected_offedge_len = 1 assert_equal(len(d), 3) assert_equal(np.sum(on_edge), expected_onedge_len) assert_equal(len(on_edge) - np.sum(on_edge), expected_offedge_len)
def __init__(self, CO12FITS, dendroFITS, regionName): self.CO12FITS = CO12FITS self.dendroFITS = dendroFITS #read fits imediately hdu = fits.open(self.CO12FITS)[0] self.CO12Data = hdu.data self.CO12Head = hdu.header self.regionName = regionName self.catWithLevelTB = regionName + self.catWithLevelTB self.dendroCat = self.regionName + "_DendroCat.fit" self.maskPath = self.regionName + "Mask/" os.system("mkdir " + self.maskPath) self.pvPath = "./pvPath/" + self.regionName + "PVFITS/" os.system("mkdir " + self.pvPath) print "Loading dendrodata..." self.dendroData = Dendrogram.load_from(self.dendroFITS)
def make_dend(cube, noise, view=True, write=True, min_npix=100, min_nsig_value=3, min_nsig_delta=2, outfn="DendroMask_H2CO303202.hdf5"): """ Given a cube and a 2D noise map, extract dendrograms. """ # Use a little sigma-rejection to get a decently robust noise estimate noise_std = noise[noise == noise].std() noise_mean = noise[noise == noise].mean() err_estimate = noise[(noise > (noise_mean - noise_std)) & (noise < (noise_mean + noise_std))].mean() bad_noise = np.isnan(noise) log.info("{1} Estimated error: {0}".format(err_estimate, outfn)) dend = Dendrogram.compute(cube.filled_data[:].value, min_value=min_nsig_value * err_estimate, min_delta=min_nsig_delta * err_estimate, min_npix=min_npix, verbose=True, wcs=cube.wcs) if view: dend.viewer() if write: dend.save_to(hpath(outfn)) return dend
def make_dend(cube, noise, view=True, write=True, min_npix=100, min_nsig_value=3, min_nsig_delta=2, outfn="DendroMask_H2CO303202.hdf5"): """ Given a cube and a 2D noise map, extract dendrograms. """ # Use a little sigma-rejection to get a decently robust noise estimate noise_std = noise[noise==noise].std() noise_mean = noise[noise==noise].mean() err_estimate = noise[(noise > (noise_mean-noise_std)) & (noise < (noise_mean+noise_std))].mean() bad_noise = np.isnan(noise) log.info("{1} Estimated error: {0}".format(err_estimate, outfn)) dend = Dendrogram.compute(cube.filled_data[:].value, min_value=min_nsig_value*err_estimate, min_delta=min_nsig_delta*err_estimate, min_npix=min_npix, verbose=True, wcs=cube.wcs) if view: dend.viewer() if write: dend.save_to(hpath(outfn)) return dend
def grad_dendro(self, min_value, min_npix, min_delta): """ Calculate the dendrogram Parameters ------ min_value: minimum value in density to consider. See astrodendro. min_npix: minimum number of voxels in a structure for it to be considered. See astrodendro. min_delta: minimum difference in density for a structure to be considered, i.e. from the saddle point where it joins with another structure to the peak. See astrodendro. """ dendro = Dendrogram.compute(self.N, min_value=min_value, min_npix=min_npix, min_delta=min_delta) self.dendro = dendro df_massflow = defaultdict(list) for i in range(len(dendro)): mask_i = dendro[i].get_mask() Sigma_i, dV_i, dR_i = quick2D(self.N, self.v, mask_i, ev=self.ev) df_massflow['size'].append(2. * dR_i) df_massflow['massflow'].append(Sigma_i * dV_i * (2. * dR_i)**2.) df_massflow = pd.DataFrame(df_massflow) self.df_massflow_dendro = df_massflow
def compute_dendro(self, verbose=False): ''' Compute the dendrogram and prune to the minimum deltas. ** min_deltas must be in ascending order! ** Parameters ---------- verbose : optional, bool ''' d = Dendrogram.compute(self.cube, verbose=verbose, min_delta=self.min_deltas[0], min_value=self.dendro_params["min_value"], min_npix=self.dendro_params["min_npix"]) self.numfeatures[0] = len(d) self.values.append( np.asarray([struct.vmax for struct in d.all_structures])) for i, delta in enumerate(self.min_deltas[1:]): if verbose: print "On %s of %s" % (i + 1, len(self.min_deltas[1:])) d.prune(min_delta=delta) self.numfeatures[i + 1] = len(d) self.values.append([struct.vmax for struct in d.all_structures]) return self
def test_save_dendrogram_catalog_output(): # 1. construct a silly dendrogram, catalog, header, and metadata data = np.zeros((3, 3, 3)) data[1, 1, 1] = 1 d = Dendrogram.compute(data, min_value=0) catalog = Table() catalog['test_column'] = np.zeros(10) header = Header.fromstring( "SIMPLE = T / conforms to FITS standard BITPIX = 64 / array data type NAXIS = 3 / number of array dimensions NAXIS1 = 6 NAXIS2 = 5 NAXIS3 = 4 CTYPE1 = 'VELO-LSR' CTYPE2 = 'GLON-CAR' CTYPE3 = 'GLAT-CAR' CRVAL1 = '' CRVAL2 = '' CRVAL3 = '' CDELT1 = '' CDELT2 = '' CDELT3 = '' CRPIX1 = '' CRPIX2 = '' CRPIX3 = '' END " ) metadata = {} metadata['data_unit'] = u.K # 2. run save_dendrogram_catalog_output on them - to some safe location kwargs = { 'data_filename': 'not_real_data_savetest.fits', 'min_value': 1, 'min_delta': 2, 'min_npix': 3, 'savepath': filepath } save_dendrogram_catalog_output(d, catalog, header, metadata, **kwargs) # 3. reload those things filename_base = filepath + "not_real_data_savetest.fits_1.000_2.000_3" d2 = Dendrogram.load_from(filename_base + "_d.hdf5") catalog2 = Table.read(filename_base + "_catalog.fits") header2 = getheader(filename_base + "_header.fits") metadata2 = pickle.load(open(filename_base + "_metadata.p", 'rb')) #4 and assert they equal the mock things. assert_equal(d2.index_map, d.index_map) assert_array_equal(catalog2, catalog) assert_equal(header2, header) assert_equal(metadata2, metadata) #5 then delete the saved objects. os.remove(filename_base + "_d.hdf5") os.remove(filename_base + "_catalog.fits") os.remove(filename_base + "_header.fits") os.remove(filename_base + "_metadata.p")
def explore_dendro(label='scimes', xaxis='radius', yaxis='v_rms'): d = Dendrogram.load_from(label + '_dendrogram.hdf5') cat = Table.read(label + '_full_catalog.txt', format='ascii.ecsv') dv = d.viewer() ds = Scatter(d, dv.hub, cat, xaxis, yaxis) ds.set_loglog() dv.show() return
def doDendro(self, data, minV=3, minDelta=3, minP=1000): print "Calculating dendrogram...." d = Dendrogram.compute(data, min_value=minV * self.sigma, min_delta=minDelta * self.sigma, min_npix=minP) print "Done" return d
def doScimes(self,dendroFITS,hd ): self.metadata["wcs"]= WCS(hd) d = Dendrogram.load_from( dendroFITS ) cat = ppv_catalog(d, self.metadata) res = SpectralCloudstering(d, cat, hd, criteria = ['volume' ], blind = True, rms = self.rms, s2nlim = 3, save_all = True, user_iter=1) res.clusters_asgn.writeto (self.regionName+'Cluster_asgn.fits', overwrite=True)
def compute_regions(min_val, min_del, npix, filename, reg_file, pdf=False): contfile = fits.open(filename) mywcs = wcs.WCS(contfile[0].header).celestial array = contfile[0].data.squeeze() beam = radio_beam.Beam.from_fits_header(contfile[0].header) d = Dendrogram.compute(array, min_value=min_val, min_delta=min_del, min_npix=npix, wcs=mywcs, verbose=False) metadata = {} metadata['data_unit'] = u.Jy / u.beam pixel_scale = np.abs( mywcs.pixel_scale_matrix.diagonal().prod())**0.5 * u.deg metadata['spatial_scale'] = pixel_scale metadata['beam_major'] = beam.major metadata['beam_minor'] = beam.minor #metadata['wavelength'] = contfile[0].header['CRVAL3']*u.GHz metadata['wcs'] = mywcs cat = pp_catalog(d, metadata) with open(reg_file, 'w') as fh: fh.write("fk5\n") for row in cat: fh.write( "ellipse({x_cen}, {y_cen}, {major_sigma}, " "{minor_sigma}, {position_angle}) # text={{{_idx}}}\n".format( **dict(zip(row.colnames, row)))) if pdf == True: ax = pl.gca() ax.cla() pl.imshow(array, cmap='gray_r', interpolation='none', origin='lower', vmax=0.01, vmin=-0.001) pltr = d.plotter() for struct in d.leaves: cntr = pltr.plot_contour(ax, structure=struct, colors=['r'], linewidths=[0.9], zorder=5) if struct.parent: while struct.parent: struct = struct.parent cntr_g = pltr.plot_contour(ax, structure=struct, colors=[(0, 1, 0, 1)], linewidths=[0.2]) pl.savefig(reg_file + '.pdf') return d, cat
def test_computing_level(self): d = Dendrogram(self.data, verbose=False) # Now pick an item near the middle of the dendrogram: mid_item = d.item_at((0, self.size//2)) # Compute its level: sys.setrecursionlimit(100000) _ = mid_item.level # Now check the .level property of all items, in random order: import random items = random.sample(list(d.all_items), len(d.items_dict)) for item in items: obj = item level = item.level while level > 0: obj = obj.parent level -= 1 self.assertEqual(obj.parent, None) self.assertEqual(obj.level, 0)
def test_identify_edge_structures_1(): # Case 1: no edge structures data = np.zeros((3,3,3)) data[1,1,1] = 1 d = Dendrogram.compute(data, min_value=0) on_edge = identify_edge_structures(d) expected = np.array([0]) assert_equal(on_edge, expected)
def test_read(): array = pyfits.getdata("data.fits.gz") d = Dendrogram(array) d.to_hdf5("test.hdf5") d2 = Dendrogram() d2.from_hdf5("test.hdf5") os.remove("test.hdf5")
def test_identify_edge_structures_3(): # Case 3: an edge structure towards the "max" side data = np.zeros((3,3,3)) data[1,1,1] = 1 data[1,1,2] = 1 d = Dendrogram.compute(data, min_value=0) on_edge = identify_edge_structures(d) expected = np.array([1]) assert_equal(on_edge, expected)
def test_reload_dendrogram_catalog_output(): # 1. construct a silly dendrogram, catalog, header, and metadata data = np.zeros((3, 3, 3)) data[1, 1, 1] = 1 d = Dendrogram.compute(data, min_value=0) catalog = Table() catalog['test_column'] = np.zeros(10) header = Header.fromstring( "SIMPLE = T / conforms to FITS standard BITPIX = 64 / array data type NAXIS = 3 / number of array dimensions NAXIS1 = 6 NAXIS2 = 5 NAXIS3 = 4 CTYPE1 = 'VELO-LSR' CTYPE2 = 'GLON-CAR' CTYPE3 = 'GLAT-CAR' CRVAL1 = '' CRVAL2 = '' CRVAL3 = '' CDELT1 = '' CDELT2 = '' CDELT3 = '' CRPIX1 = '' CRPIX2 = '' CRPIX3 = '' END " ) metadata = {} metadata['data_unit'] = u.K # 2. save it all "manually" filename_base = filepath + "not_real_data_reloadtest.fits_1.000_2.000_3" d.save_to(filename_base + "_d.hdf5") catalog.write(filename_base + "_catalog.fits", overwrite=True) header.tofile(filename_base + "_header.fits", clobber=True) pickle.dump(metadata, open(filename_base + "_metadata.p", 'wb')) # 3. reconstitute it using the magic function kwargs = { 'data_filename': 'not_real_data_reloadtest.fits', 'min_value': 1, 'min_delta': 2, 'min_npix': 3, 'savepath': filepath } d2, catalog2, header2, metadata2 = reload_dendrogram_catalog_output( **kwargs) #4 and assert they equal the mock things. assert_equal(d2.index_map, d.index_map) assert_array_equal(catalog2, catalog) assert_equal(header2, header) assert_equal(metadata2, metadata) # 4.5. stress test. for i in range(5): reload_dendrogram_catalog_output(**kwargs) #5 then delete the saved objects. os.remove(filename_base + "_d.hdf5") os.remove(filename_base + "_catalog.fits") os.remove(filename_base + "_header.fits") os.remove(filename_base + "_metadata.p")
def compute_dendro(cube, header, delta, save_name, verbose=False, save=True,\ save_path=None): ## Pass **kwargs into Dendrogram class?? ''' Computes a dendrogram and (optional) save it in HDF5 format. ''' dendrogram = Dendrogram.compute(cube, min_delta=delta, verbose=verbose, min_value=0.25, min_npix=10) if save: dendrogram.save_to(save_name+"_"+str(delta)+"_dendrogram.hdf5") return os.path.join(save_path, save_name+"_"+str(delta)+"_dendrogram.hdf5") return dendrogram
def dend_spec(xx=12, yy=17, min_nsig=3, min_delta=1, min_npix=3): b303 = cube303[brick_slice] n303 = noise[brick_slice[1:]] dend = Dendrogram.compute(b303[:,yy,xx].value, min_value=n303[yy,xx]*min_nsig, min_delta=n303[yy,xx]*min_delta, min_npix=min_npix, verbose=True,) dend_guesses = [b303.spectral_axis[leaf.indices()].mean() for leaf in dend] import pylab as pl pl.plot(b303[:,yy,xx].value, drawstyle='steps-mid', color='k', linewidth=0.5) for ii in range(len(dend)): pl.plot(dend[ii].indices()[0], b303[:,yy,xx].value[dend[ii].indices()], '.') return dend_guesses,dend
def get_catalog(cogal): from astrodendro import Dendrogram from astrodendro import ppv_catalog co = cogal[0] gal = cogal[1] # get data and info file = data[co][gal]['noise matched']['file'] cube = fits.open(file)[0] noise = data[co][gal]['noise matched']['rms'].to(u.K) bmin = cube.header['bmin'] * u.degree bmaj = cube.header['bmaj'] * u.degree beam_area = 1.13309 * bmin * bmaj pix1 = u.Quantity( str(np.abs(cube.header['cdelt1'])) + cube.header['cunit1']) pix2 = u.Quantity( str(np.abs(cube.header['cdelt2'])) + cube.header['cunit2']) pix3 = u.Quantity( str(np.abs(cube.header['cdelt3'])) + cube.header['cunit3']) pix_beam = (beam_area / pix1 / pix2) d = Dendrogram.load_from(join(compdir, gal + '.' + co + '.dendrogram.fits')) # time execution print("\nComputing catalog: " + co + " " + gal + "\n") start = time.time() # calculate catalog metadata = { 'data_unit': u.K, 'spatial_scale': parsec_to_angle(pix1, source=gal), 'velocity_scale': pix3, 'beam_major': bmaj, 'beam_minor': bmin, 'vaxis': 0, 'wavelength': lines[co]['restfreq'], 'wcs': WCS(cube.header) } catalog = ppv_catalog(d, metadata) fnpickle(catalog, join(compdir, gal + '.' + co + '.catalog.pickle')) # time execution stop = time.time() exec_time = np.round(stop - start, 1) print("\nFinished catalog: " + co + " " + gal + "\nExecution took " + str(datetime.timedelta(seconds=exec_time)) + "hours for " + str(len(catalog)) + " structures.\n")
def to_dendrogram(self, min_value=None, min_delta=None, min_npix=None, save=True): """ Calculates a dendrogram for the image. Parameters ---------- min_value : float, optional Minimum detection level to be considered in the dendrogram. min_delta : float, optional How significant a dendrogram structure has to be in order to be considered a separate entity. min_npix : float, optional Minimum number of pixel needed for a dendrogram structure to be considered a separate entity. save : bool, optional If enabled, the resulting dendrogram will be saved as an instance attribute. Default is True. Returns ---------- `~astrodendro.dendrogram.Dendrogram` object A dendrogram object calculated from the radio image. """ if not min_value: min_value = self.min_value if not min_delta: min_delta = self.min_delta if not min_npix: min_npix = self.min_npix dend = Dendrogram.compute(self.data, min_value=min_value, min_delta=min_delta, min_npix=min_npix, wcs=self.wcs, verbose=True) if save: self.dendrogram = dend return dend
def make_sn_dend(sncube, view=True, write=True, outfn="DendroMask_H2CO303202_signal_to_noise.hdf5"): """ Obsolete: not used """ raise DeprecationWarning("Obsolete") dend = Dendrogram.compute(sncube, min_value=3, min_delta=2, min_npix=50, verbose=True) if view: dend.viewer if write: dend.save_to(hpath(outfn)) return dend
def dend_guess_npeaks(cube, noise_2d, min_nsig=3, min_delta=1, min_npix=3): valid_indices = np.where(np.isfinite(noise_2d)) guesses = {} for yy,xx in ProgressBar(zip(*valid_indices)): dend = Dendrogram.compute(cube[:, yy, xx].value, min_value=min_nsig*noise_2d[yy,xx], min_delta=min_delta*noise_2d[yy,xx], min_npix=min_npix,) guesses[(yy,xx)] = [x for leaf in dend for x in (cube.spectral_axis[leaf.indices()].mean().value, cube.spectral_axis[leaf.indices()].std().value) ] return guesses
def colorcode(label='scimes', table='full_catalog', cubefile=None, mom0file=None, types=['v_cen', 'v_rms', 'tmax', 'imean'], outdir='plots', vmin=None, vmax=None, **kwargs): # Header info hdu3 = fits.open(cubefile)[0] hd3 = hdu3.header # Moment image hdu2 = fits.open(mom0file)[0] img = hdu2.data # Load the dendrogram d = Dendrogram.load_from(label + '_dendrogram.hdf5') print('\n') cat = Table.read(label + '_' + table + '.txt', format='ascii.ecsv') # Plot colored ellipses on maps for set in ['leaves', 'trunks', 'clusters']: idc = [] with open(label + '_' + set + '.txt', 'r') as f: reader = csv.reader(f, delimiter=' ') for row in reader: idc.append(int(row[0])) subcat = cat[idc] props_colmap(dendrogram=d, subcat=subcat, img=img, cubhd=hd3, props=types, prefix=outdir + '/' + label + '_' + set, vmin=vmin, vmax=vmax, **kwargs) # Plot colored dendrogram props_coltree(label=label, dendrogram=d, cat=cat, cubhd=hd3, props=types, prefix=outdir + '/' + label, vmin=vmin, vmax=vmax) return
def compute_dendro(self, verbose=False, save_dendro=False, dendro_name=None, dendro_obj=None): ''' Compute the dendrogram and prune to the minimum deltas. ** min_deltas must be in ascending order! ** Parameters ---------- verbose : optional, bool Enables the progress bar in astrodendro. save_dendro : optional, bool Saves the dendrogram in HDF5 format. **Requires pyHDF5** dendro_name : str, optional Save name when save_dendro is enabled. ".hdf5" appended automatically. dendro_obj : Dendrogram, optional Input a pre-computed dendrogram object. It is assumed that the dendrogram has already been computed! ''' if dendro_obj is None: d = \ Dendrogram.compute(self.data, verbose=verbose, min_delta=self.min_deltas[0], min_value=self.dendro_params["min_value"], min_npix=self.dendro_params["min_npix"]) else: d = dendro_obj self.numfeatures[0] = len(d) self.values.append( np.asarray([struct.vmax for struct in d.all_structures])) if len(self.min_deltas) > 1: for i, delta in enumerate(self.min_deltas[1:]): if verbose: print "On %s of %s" % (i + 1, len(self.min_deltas[1:])) d.prune(min_delta=delta) self.numfeatures[i + 1] = len(d) self.values.append( [struct.vmax for struct in d.all_structures]) return self
def main(args): #------------------------ # Load dendrogram #------------------------ print('Load Dendrogram') d = Dendrogram.load_from(args.file_d + '.hdf5') plot_image(args.file_map,args.file_out,file_reg=args.file_reg,file_contour=args.file_contour,\ plot=args.plot,oformat=args.format,resize=args.resize,\ contour=args.contour,contour_color=args.contour_color,\ levels=args.levels,skycoor=args.skycoor,beam=args.beam,beamcolor=args.beamcolor,\ vmin=args.vmin,vmax=args.vmax,pmin=args.pmin,pmax=args.pmax,smooth=args.smooth,\ stretch=args.stretch,cmap=args.cmap,colorbar=args.colorbar,\ dendro=d,file_catalog=args.file_catalog) return 0
def main(args): #------------------------ # Load dendrogram #------------------------ print('Load Dendrogram') d = Dendrogram.load_from(args.file_dend + '.hdf5') print('') plot_image(args.file_map,args.file_velo,file_out=args.file_out,file_reg=args.file_reg,file_contour=args.file_contour,\ plot=args.plot,save=args.save,oformat=args.format,resize=args.resize,\ contour=args.contour,contour_color=args.contour_color,\ levels=args.levels,skycoor=args.skycoor,beam=args.beam,\ vmin=args.vmin,vmax=args.vmax,pmin=args.pmin,pmax=args.pmax,\ stretch=args.stretch,\ dendro=d,file_sour=args.file_sour) return 0
def to_dendrogram(self, min_value=None, min_delta=None, min_npix=None, save=True): """ Calculates a dendrogram for the image. Documentation needed Parameters ---------- min_value : float, optional min_delta : float, optional min_npix : float, optional save : bool, optional If enabled, the resulting dendrogram will be saved as an instance attribute. Default is True. Returns ---------- ~astrodendro.dendrogram.Dendrogram object A dendrogram object calculated from the radio image. """ if not min_value: min_value = self.min_value if not min_delta: min_delta = self.min_delta if not min_npix: min_npix = self.min_npix dend = Dendrogram.compute(self.data, min_value=min_value, min_delta=min_delta, min_npix=min_npix, wcs=self.wcs, verbose=True) if save: self.dendrogram = dend return dend
def load_dendrogram(hdf5_file, min_deltas=None): ''' Load in a previously saved dendrogram. **Requires pyHDF5** Parameters ---------- hdf5_file : str Name of saved file. min_deltas : numpy.ndarray or list Minimum deltas of leaves in the dendrogram. ''' dendro = Dendrogram.load_from(hdf5_file) self = Dendrogram_Stats(dendro.data, min_deltas=min_deltas, dendro_params=dendro.params) return self
def dend_guess_npeaks(cube, noise_2d, min_nsig=3, min_delta=1, min_npix=3): valid_indices = np.where(np.isfinite(noise_2d)) guesses = {} for yy, xx in ProgressBar(zip(*valid_indices)): dend = Dendrogram.compute( cube[:, yy, xx].value, min_value=min_nsig * noise_2d[yy, xx], min_delta=min_delta * noise_2d[yy, xx], min_npix=min_npix, ) guesses[(yy, xx)] = [ x for leaf in dend for x in (cube.spectral_axis[leaf.indices()].mean().value, cube.spectral_axis[leaf.indices()].std().value) ] return guesses
def make_dendogram(self, field, axis, res): """Make a dendrogram of a field on a specified axis and dump the dendrogram object to disk. """ self.get_fits_name(field, axis) self.get_dendrogram_name(field, axis) if glob.glob(self.dendrogram_name) != []: print "Existing file at the following directory. I won't overwrite." print self.dendrogram_name return -1 print 'making dendrogram' data = self.get_fits_array(field, axis) d = Dendrogram.compute(data, min_value=2.0, min_delta=1.0, min_npix=5, verbose=True) d.save_to(self.dendrogram_name) return d
def get_dendrogram(cogal, min_snr=5., fac_delta=1., fac_npix=1.): import time, datetime from astrodendro import Dendrogram co = cogal[0] gal = cogal[1] # get data and info file = data[co][gal]['noise matched']['file'] cube = fits.open(file)[0] noise = data[co][gal]['noise matched']['rms'].to(u.K) bmin = angle_to_parsec(cube.header['bmin'] * u.degree, source=gal) bmaj = angle_to_parsec(cube.header['bmaj'] * u.degree, source=gal) beam_area = 1.13309 * bmin * bmaj pix1 = u.Quantity( str(np.abs(cube.header['cdelt1'])) + cube.header['cunit1']) pix2 = u.Quantity( str(np.abs(cube.header['cdelt2'])) + cube.header['cunit2']) pix3 = u.Quantity( str(np.abs(cube.header['cdelt3'])) + cube.header['cunit3']) pix_beam = (beam_area / pix1 / pix2) # time execution print("\nComputing dendrogram: " + co + " " + gal + "\n") start = time.time() # calculate dendrogram d = Dendrogram.compute( cube.data, #wcs = WCS(cube.header), # causes a buffer overflow b/o wcslib errors: https://github.com/astropy/astropy/issues/7412 min_value=(min_snr * noise).value, min_delta=(fac_delta * noise).value, min_npix=(fac_npix * pix_beam).value, verbose=True) savepath = join(compdir, gal + '.' + co + '.dendrogram.fits') mkdir(os.path.dirname(escape_filename(savepath))) d.save_to(savepath) # time execution stop = time.time() exec_time = np.round(stop - start, 1) print("\nFinished dendrogram: " + co + " " + gal + "\nExecution took " + str(datetime.timedelta(seconds=exec_time)) + "hours.\n")
def compute_dendro(cube, header, delta, save_name, verbose=False, save=True,\ save_path=None): ## Pass **kwargs into Dendrogram class?? ''' Computes a dendrogram and (optional) save it in HDF5 format. ''' dendrogram = Dendrogram.compute(cube, min_delta=delta, verbose=verbose, min_value=0.25, min_npix=10) if save: dendrogram.save_to(save_name + "_" + str(delta) + "_dendrogram.hdf5") return os.path.join(save_path, save_name + "_" + str(delta) + "_dendrogram.hdf5") return dendrogram
def get_dendrogram(self, axis, prefix='dendrogram_1', fpickle_args=None): """Unsure how to save these to disk""" self.get_fits_name('density', axis) dendro_filename = self.fits_dir + "/%s.fits" % prefix if len(glob.glob(dendro_filename)) > 0: pyfits.open(dendro_filename)[0].data #return fPickle.load(dendro_filename) else: density = self.get_fits_array('density', axis) if fpickle_args is None: fpickle_args = { 'min_value': 2.0, 'min_delta': 1.0, 'min_npix': 10.0, 'verbose': True } d = dg.compute(density, **fpickle_args) #fPickle.dump(d,dendro_filename) return d
def dend_spec(xx=12, yy=17, min_nsig=3, min_delta=1, min_npix=3): b303 = cube303[brick_slice] n303 = noise[brick_slice[1:]] dend = Dendrogram.compute( b303[:, yy, xx].value, min_value=n303[yy, xx] * min_nsig, min_delta=n303[yy, xx] * min_delta, min_npix=min_npix, verbose=True, ) dend_guesses = [b303.spectral_axis[leaf.indices()].mean() for leaf in dend] import pylab as pl pl.plot(b303[:, yy, xx].value, drawstyle='steps-mid', color='k', linewidth=0.5) for ii in range(len(dend)): pl.plot(dend[ii].indices()[0], b303[:, yy, xx].value[dend[ii].indices()], '.') return dend_guesses, dend
def load_dendro(file): """ Load a dendrogram saved by the astrodendro package :param file: Path to a dendrogram file :returns: A list of 2 glue Data objects: the original dataset, and dendrogram. """ dg = Dendrogram.load_from(file) structs = np.arange(len(dg)) parent = np.array([dg[i].parent.idx if dg[i].parent is not None else -1 for i in structs]) height = np.array([dg[i].height for i in structs]) pk = np.array([dg[i].get_peak(True)[1] for i in structs]) dendro = Data(parent=parent, height=height, peak=pk, label='Dendrogram') im = Data(intensity=dg.data, structure=dg.index_map) im.join_on_key(dendro, 'structure', dendro.pixel_component_ids[0]) return [dendro, im]
def test_read(self): d = Dendrogram(self.data, verbose=False) d.to_hdf5(self.test_filename) d2 = Dendrogram() d2.from_hdf5(self.test_filename) self.assertEqual(len(d.items_dict), len(d2.items_dict)) np.testing.assert_array_equal(d.data, d2.data) # Do we recover the data exactly? for idx in d2.items_dict: item1, item2 = d.items_dict[idx], d2.items_dict[idx] self.assertItemsEqual(item1.coords, item2.coords) self.assertItemsEqual(item1.f, item2.f) self.assertEqual(type(item1), type(item2)) # Compare the coordinates and flux values of all reported peak pixels: self.assertEqual(item1.get_peak_recursive()[1:], item2.get_peak_recursive()[1:]) if type(item2) == Branch: self.assertEqual(item1.merge_level, item2.merge_level)
import pyfits from astrodendro import Dendrogram # Read in the data image = pyfits.getdata('data.fits.gz') # Compute the dendrogram d = Dendrogram(image) # Output to HDF5 file d.to_hdf5('simple_2d_dendrogram.hdf5')
def compute_dendro(self, show_progress=False, save_dendro=False, dendro_name=None, dendro_obj=None, periodic_bounds=False): ''' Compute the dendrogram and prune to the minimum deltas. ** min_deltas must be in ascending order! ** Parameters ---------- show_progress : optional, bool Enables the progress bar in astrodendro. save_dendro : optional, bool Saves the dendrogram in HDF5 format. **Requires pyHDF5** dendro_name : str, optional Save name when save_dendro is enabled. ".hdf5" appended automatically. dendro_obj : Dendrogram, optional Input a pre-computed dendrogram object. It is assumed that the dendrogram has already been computed! periodic_bounds : bool, optional Enable when the data is periodic in the spatial dimensions. ''' self._numfeatures = np.empty(self.min_deltas.shape, dtype=int) self._values = [] if dendro_obj is None: if periodic_bounds: # Find the spatial dimensions num_axes = self.data.ndim spat_axes = [] for i, axis_type in enumerate(self._wcs.get_axis_types()): if axis_type["coordinate_type"] == u"celestial": spat_axes.append(num_axes - i - 1) neighbours = periodic_neighbours(spat_axes) else: neighbours = None d = Dendrogram.compute(self.data, verbose=show_progress, min_delta=self.min_deltas[0], min_value=self.dendro_params["min_value"], min_npix=self.dendro_params["min_npix"], neighbours=neighbours) else: d = dendro_obj self._numfeatures[0] = len(d) self._values.append(np.array([struct.vmax for struct in d.all_structures])) if len(self.min_deltas) > 1: # Another progress bar for pruning steps if show_progress: print("Pruning steps.") bar = ProgressBar(len(self.min_deltas[1:])) for i, delta in enumerate(self.min_deltas[1:]): d.prune(min_delta=delta) self._numfeatures[i + 1] = len(d) self._values.append(np.array([struct.vmax for struct in d.all_structures])) if show_progress: bar.update(i + 1)
save_name=osjoin(fig_path, "delvar_design4_break.png")) # Look at difference w/ non-periodic boundary handling # This needs to be revisited with the astropy convolution updates # delvar.run(verbose=True, xunit=u.pix, xlow=4 * u.pix, xhigh=30 * u.pix, # boundary='fill', # save_name=osjoin(fig_path, "delvar_design4_boundaryfill.png")) # Dendrograms if run_dendro: from turbustat.statistics import Dendrogram_Stats from astrodendro import Dendrogram cube = fits.open(osjoin(data_path, "Design4_flatrho_0021_00_radmc.fits"))[0] d = Dendrogram.compute(cube.data, min_value=0.005, min_delta=0.1, min_npix=50, verbose=True) ax = plt.subplot(111) d.plotter().plot_tree(ax) plt.ylabel("Intensity (K)") plt.savefig(osjoin(fig_path, "design4_dendrogram.png")) plt.close() dend_stat = Dendrogram_Stats(cube, min_deltas=np.logspace(-2, 0, 50), dendro_params={"min_value": 0.005, "min_npix": 50}) dend_stat.run(verbose=True, save_name=osjoin(fig_path, "design4_dendrogram_stats.png")) # Periodic boundaries dend_stat.run(verbose=True, periodic_bounds=True,
do_topview = True # Make the dendrogram of the full cube/image if do_make: print 'Make dendrogram from the full cube' data = fits.getdata(data_file) if size(shape(data))==4: data = data[0,:,:,:] rms = 0.4 pix_beam = 14 d = Dendrogram.compute(data, min_value=2*rms, min_delta=2*rms, min_npix=10, verbose = 1) d.save_to(dendro_file+'.fits') d.viewer() # Load a premade dendrogram if do_load: data = fits.getdata(data_file) if size(shape(data))==4: data = data[0,:,:,:] print 'Load dendrogram file: '+load_file d = Dendrogram.load_from(load_file)
for file in glob.glob('*.fits'): count += 1 # Read in using astropy and then append the data to a list for use later contents = fits.open(str(file))[1] ''' # Append the name of the file to the position (count+len(data)) followed by # the file contents data.insert(count+len(data), file) data.append(contents) filenames.append(file) ''' # Define a dendrogram instance d = Dendrogram.compute(contents.data, verbose=True) # Let the dendrogram become an interactive plot p = d.plotter() # Add the data to a figure fig = figure() # Define subplots to plot with ax1 = subplot2grid((6,6), (0,0), colspan=4,rowspan=4) ax2 = subplot2grid((6,6), (5,0), colspan=4,rowspan=1) #ax13 = subplot2grid((3, 3), (1, 0), colspan=2, rowspan=2) #ax14 = subplot2grid((3, 3), (1, 2), rowspan=2) leaves = []
""" import numpy as np import time import warnings from astropy import log from astrodendro import Dendrogram,ppv_catalog from astropy.table import Table, Column from paths import hpath,tpath from masked_cubes import cube303,cube303sm,cube321,cube321sm import flag_other_lines from astropy.utils.console import ProgressBar if 'dend' not in locals(): t0 = time.time() log.info("Loading dendrogram from file.") dend = Dendrogram.load_from(hpath("DendroMask_H2CO303202.hdf5")) log.info("Loaded dendrogram from file in {0:0.1f} seconds.".format(time.time()-t0)) dend.wcs = cube303.wcs if 'dendsm' not in locals(): t0 = time.time() log.info("Loading dendrogram from file.") dendsm = Dendrogram.load_from(hpath("DendroMask_H2CO303202_smooth.hdf5")) log.info("Loaded dendrogram from file in {0:0.1f} seconds.".format(time.time()-t0)) dendsm.wcs = cube303sm.wcs # Removed: the 321 signal extraction approach never worked nicely # if 'dend321' not in locals(): # t0 = time.time() # log.info("Loading dendrogram from file.") # dend321 = Dendrogram.load_from(hpath("DendroMask_H2CO321220.hdf5"))
def test_compute(self): d = Dendrogram(self.data, verbose=False) leaves = d.get_leaves() self.assertEqual(len(leaves), self.size, msg="We expect {n} leaves, not {a}.".format(n=self.size, a=len(leaves)))
def test_write(self): d = Dendrogram(self.data, verbose=False) d.to_hdf5(self.test_filename)
def dendrogram(): ''' ''' ############################# Read in the data ################################ count, data, filenames = 0, [], [] # Loop through all fits files for file in glob.glob('*.fits'): count += 1 # Read in using astropy and then append the data to a list for use later contents = fits.open(str(file))[1] ''' # Append the name of the file to the position (count+len(data)) followed by # the file contents data.insert(count+len(data), file) data.append(contents) filenames.append(file) ''' # Define a dendrogram instance d = Dendrogram.compute(contents.data, verbose=True) # Let the dendrogram become an interactive plot p = d.plotter() # Add the data to a figure fig = figure() # Define subplots to plot with ax1 = subplot2grid((6,6), (0,0), colspan=4,rowspan=4) ax2 = subplot2grid((6,6), (5,0), colspan=4,rowspan=1) #ax13 = subplot2grid((3, 3), (1, 0), colspan=2, rowspan=2) #ax14 = subplot2grid((3, 3), (1, 2), rowspan=2) leaves = [] # Find the structure within the data for i in range(0,len(d)): struct = d[i] # Get the mask of the region highlighted mask = struct.get_mask() # Create FITS HDU objects mask_hdu = fits.PrimaryHDU(mask.astype('short'), contents.header) ax1.imshow(contents.data, origin='lower', interpolation='nearest') # Show contour for ``min_value`` p.plot_contour(ax1, color='black') #p.colorbar() # Determine the type of structure if struct.is_leaf: leaves.append(struct) # Extract the indices of the core and its value indices = struct.indices(subtree=True) vals = struct.values(subtree=True) #print indices #print vals # Highlight two branches p.plot_contour(ax1, structure=struct, lw=3, colors="#%06x" % random.randint(0, 0xFFFFFF)) # Plot the entire tree in black p.plot_tree(ax2, color='black') # Add labels to the plot if 'T_chi' in file: ax1.set_xlabel('X') ax1.set_ylabel('Y') ax1.set_title('A Map Showing the Structure\n of $T$ for the $\chi^{2}$ Recovered Values') ax2.set_xlabel('Structure') ax2.set_ylabel('$T\/(K)$') ax2.set_title('A Dendrogram Showing the Structure\n of $T$ for the $\chi^{2}$ Recovered Values') elif 'N_chi' in file: ax1.set_xlabel('X') ax1.set_ylabel('Y') ax1.set_title('A Map Showing the Structure\n of $N$ for the $\chi^{2}$ Recovered Values') ax2.set_xlabel('Structure') ax2.set_ylabel('$N\/(g\/cm^{-3})$') ax2.set_title('A Dendrogram Showing the Structure\n of $N$ for the $\chi^{2}$ Recovered Values') elif 'T_data' in file: ax1.set_xlabel('X') ax1.set_ylabel('Y') ax1.set_title('A Map Showing the Structure\n of $T$ for the Data Input Values') ax2.set_xlabel('Structure') ax2.set_ylabel('$T\/(K)$') ax2.set_title('A Dendrogram Showing the Structure\n of $T$ for the Data Input Values') elif 'N_data' in file: ax1.set_xlabel('X') ax1.set_ylabel('Y') ax1.set_title('A Map Showing the Structure\n of $N$ for the Data Input Values') ax2.set_xlabel('Structure') ax2.set_ylabel('$N\/(g\/cm^{-3})$') ax2.set_title('A Dendrogram Showing the Structure\n of $N$ for the Data Input Values') #ax1.imshow(contents, origin='lower', interpolation='nearest', cmap=cm.Blues, vmax1=4.0) # Plot black contours on to the data # Show contour for ``min_value`` #p.plot_contour(ax1, color='black') # Save the image and then close to save memory and allow the next image to take its place fig.savefig(str(file)+str('.jpg'), dpi=300) close()
def test_write(): array = pyfits.getdata("data.fits.gz") d = Dendrogram(array) d.to_hdf5("test.hdf5") os.remove("test.hdf5")
f = np.power(10, f) NH2 = f # plt.show() outpath1 = r'./W43_main_N_erosion.fits' if os.path.exists(outpath1): os.remove(outpath1) if os.path.exists(outpath1): os.remove(outpath1) print 'Writing', outpath1 fits.writeto(outpath1, np.log10(f), header=hdulist1[0].header) params = {'mathtext.default': 'regular'} plt.rcParams.update(params) d = Dendrogram.compute(f, min_value=7.0e21, min_delta=8e20 / 2.35 * 5., min_npix=7.0) metadata = {} metadata['data_unit'] = u.Jy metadata['spatial_scale'] = 1.5 * u.arcsec metadata['beam_major'] = 10.0 * u.arcsec metadata['beam_minor'] = 10.0 * u.arcsec threshold = 10 * 8e20 / 2.35 * 5. d.save_to('W43_main_my_dendrogram_erosion.fits') NH2_mean = [] for i, leaf in enumerate(d.leaves): NH2_mean = np.append(NH2_mean, np.nanmean(NH2[leaf.indices()[0], leaf.indices()[1]])) fig = plt.figure(figsize=(17, 7)) p3 = d.plotter() ax1 = fig.add_subplot(1, 3, 1) ax2 = fig.add_subplot(1, 3, 2)
filename = 'orion_12CO' #%&%&%&%&%&%&%&%&%&%&%&% # Make dendrogram #%&%&%&%&%&%&%&%&%&%&%&% print 'Make dendrogram from the full cube' hdu = fits.open(filename+'.fits')[0] data = hdu.data hd = hdu.header # Survey designs sigma = 0.3 #K, noise level ppb = 1.3 #pixels/beam d = Dendrogram.compute(data, min_value=sigma, \ min_delta=2*sigma, min_npix=3*ppb, verbose = 1) # Plot the tree fig = plt.figure(figsize=(14, 8)) ax = fig.add_subplot(111) ax.set_yscale('log') ax.set_xlabel('Structure') ax.set_ylabel('Flux') p = d.plotter() p.plot_tree(ax, color='black') #%&%&%&%&%&%&%&%&%&%&%&%&%&% # Generate the catalog