def snapshot(self): thisStar = self.starData[self.idx] cen_x = thisStar["xcentroid"] cen_y = thisStar["ycentroid"] # get the subset of the data first # get the central pixel cen_x_pix = int(np.floor(cen_x)) cen_y_pix = int(np.floor(cen_y)) # we'll select a larger subset around that central pixel, then change the plot # limits to be just in the center, so that the object always appears at the # center buffer_half_width = int(np.ceil(self.plotWidth / 2) + 3) min_x_pix = cen_x_pix - buffer_half_width max_x_pix = cen_x_pix + buffer_half_width min_y_pix = cen_y_pix - buffer_half_width max_y_pix = cen_y_pix + buffer_half_width # then get this slice of the data snapshot_data = self.imageData[min_y_pix:max_y_pix, min_x_pix:max_x_pix] # When showing the plot I want the star to be in the very center. To do this I # need to get the values for the border in the new pixel coordinates cen_x_new = cen_x - min_x_pix cen_y_new = cen_y - min_y_pix # then make the plot limits min_x_plot = cen_x_new - 0.5 * self.plotWidth max_x_plot = cen_x_new + 0.5 * self.plotWidth min_y_plot = cen_y_new - 0.5 * self.plotWidth max_y_plot = cen_y_new + 0.5 * self.plotWidth fig, ax = bpl.subplots(figsize=[6, 5]) vmax = np.max(snapshot_data) vmin = -5 * noise linthresh = max(0.01 * vmax, 5 * noise) norm = colors.SymLogNorm(vmin=vmin, vmax=vmax * 2, linthresh=linthresh, base=10) im = ax.imshow(snapshot_data, norm=norm, cmap=bpl.cm.lapaz, origin="lower") ax.set_limits(min_x_plot, max_x_plot, min_y_plot, max_y_plot) ax.scatter([cen_x_new], [cen_y_new], marker="x", c=bpl.almost_black, s=20) ax.remove_labels("both") ax.remove_spines(["all"]) fig.colorbar(im, ax=ax) fig.savefig(temp_loc, dpi=100, bbox_inches="tight") plt.close(fig)
image_data, _, _ = utils.get_drc_image(home_dir) # ====================================================================================== # # Get the sky noise level and make debug plot # # ====================================================================================== # first throw out all data that's exactly zero idxs_nonzero = np.nonzero(image_data) nonzero_data = image_data[idxs_nonzero] # we do the simplest thing and do sigma clipping mean, median, sigma_sky = stats.sigma_clipped_stats(nonzero_data, sigma=2.0) # make a debug plot to assess how well this worked fig, ax = bpl.subplots() bins = np.arange(mean - 10 * sigma_sky, mean + 10.1 * sigma_sky, 0.1 * sigma_sky) ax.hist(nonzero_data, bins=bins, color=bpl.color_cycle[1]) ax.set_limits(min(bins), max(bins)) ax.axvline(mean, ls="--", label="Mean") ax.axvline(mean + sigma_sky, ls=":", label="Mean $\pm \sigma_{sky}$") ax.axvline(mean - sigma_sky, ls=":") ax.add_labels("Pixel Values [electrons]", "Number of Pixels") ax.legend() fig.savefig(size_dir / "plots" / "sky_noise_debug.png") # ====================================================================================== # # Then assign noise values for all pixels in the image #
def mask_plot(kind, savename): idx = np.argmin(get_data_wrap(data_original, "x", original_subset, kind)) center = [ get_data_wrap(data_original, "x", original_subset, kind)[idx], get_data_wrap(data_original, "y", original_subset, kind)[idx], get_data_wrap(data_original, "z", original_subset, kind)[idx] ] dx = 10.0 limits = [ np.floor(center[0] - dx), np.floor(center[0] + dx), np.floor(center[1] - dx), np.floor(center[1] + dx), np.floor(center[2]), np.ceil(center[2]) ] # ensure integer z range fig, ax = bpl.subplots() zorder_final = 5 zorder_original = 6 zorder_root = 7 if kind == "gas": marker = "s" size_final = 30 size_original = 10 size_root = 3 label = " Cells" else: marker = "o" size_final = 50 size_original = 20 size_root = 10 label = " Particles" utils.plot_one_sim(get_data_wrap(data_final, "x", "all", kind), get_data_wrap(data_final, "y", "all", kind), get_data_wrap(data_final, "z", "all", kind), *limits, ax, s=size_final, zorder=zorder_final, marker=marker, c=color_final, label="Final" + label) utils.plot_one_sim(get_data_wrap(data_original, "x", "all", kind), get_data_wrap(data_original, "y", "all", kind), get_data_wrap(data_original, "z", "all", kind), *limits, ax, s=size_original, zorder=zorder_original, marker=marker, c=color_original, label="Original" + label) utils.plot_one_sim(get_data_wrap(data_root, "x", "all", kind), get_data_wrap(data_root, "y", "all", kind), get_data_wrap(data_root, "z", "all", kind), *limits, ax, s=size_root, zorder=zorder_root, marker=marker, c=color_root, label="New Root" + label) for x in np.arange(limits[0], limits[1], 1): ax.axvline(x, lw=0.5) for y in np.arange(limits[2], limits[3], 1): ax.axhline(y, lw=0.5) if kind == "gas": mask = mask_gas else: mask = mask_part d_check = 0.1 eps = 1E-10 mask_color = "0.92" mask_labeled = False for x_min in tqdm(np.arange(limits[0], limits[1], 1)): x_max = x_min + 1 for y_min in np.arange(limits[2], limits[3], 1): y_max = y_min + 1 cs = [] for x in np.arange(x_min + eps, x_max, d_check): for y in np.arange(y_min + eps, y_max, d_check): for z in np.arange(limits[-2] + eps, limits[-1], d_check): cell_edges = utils.find_cell_edges(x, y, z, 0) idx_i = int(round(cell_edges[0], 0)) idx_j = int(round(cell_edges[2], 0)) idx_k = int(round(cell_edges[4], 0)) if idx_i < 0 or idx_j < 0 or idx_k < 0 or mask[idx_i][ idx_j][idx_k] < 0.5: cs.append("white") else: cs.append(mask_color) # we checked several points within one root cell. If we did the masking # right these should all be the same assert len(set(cs)) == 1 if not mask_labeled and cs[0] == mask_color: label = "Mask Region" mask_labeled = True else: label = None ax.fill_between(x=[x_min, x_max], y1=y_min, y2=y_max, color=cs[0], zorder=-1, label=label) ax.equal_scale() ax.add_labels("X [code units]", "Y [code units]", "{} < Z < {}".format(limits[4], limits[5])) ax.set_limits(limits[0], limits[1], limits[2], limits[3]) ax.legend(bbox_to_anchor=(0.97, 0.5), loc="center left") fig.savefig(savename)
for x in ["x", "y", "z"] ] median_replica = [ np.median(get_data_wrap(data_replica, x, "zoom_0", "particle")) for x in ["x", "y", "z"] ] print(" - Original zoom region median: {:.5f}, {:.5f}, {:.5f}". format(*median_original)) print(" - Replica zoom region median: {:.5f}, {:.5f}, {:.5f}". format(*median_replica)) diffs = [median_replica[i] - median_original[i] for i in range(3)] # start the plot before we correct the data fig, axs = bpl.subplots(ncols=2, figsize=[15, 8]) idx = np.argmin(get_data_wrap(data_replica, "x", "zoom_0", "particle")) plot_center = [ get_data_wrap(data_replica, x, "zoom_0", "particle")[idx] for x in ["x", "y", "z"] ] plot_offset(axs[0], plot_center, "Before", get_data_wrap(data_original, "x", "all", "particle"), get_data_wrap(data_original, "y", "all", "particle"), get_data_wrap(data_original, "z", "all", "particle"), get_data_wrap(data_replica, "x", "all", "particle"), get_data_wrap(data_replica, "y", "all", "particle"), get_data_wrap(data_replica, "z", "all", "particle")) # these diffs are in units of the new root grid, rather than the original root # grid. The ratio between those two is the ratio of the cell sizes
return ys def calculate_peak(r_eff_grid, pdf): max_pdf = -1 max_r = 0 for idx in range(len(r_eff_grid)): if pdf[idx] > max_pdf: max_r = r_eff_grid[idx] max_pdf = pdf[idx] return max_r nrows = 4 ncols = 8 fig, axs = bpl.subplots(nrows=nrows, ncols=ncols, figsize=[5 * ncols, 5 * nrows]) axs = axs.flatten() radii_plot = np.logspace(-1, 1.5, 300) stacked_pdf = kde( radii_plot, stacked_catalog["r_eff_log"], stacked_catalog["r_eff_log_smooth"], ) r_peak_stack = calculate_peak(radii_plot, stacked_pdf) print(f"Peak of stacked distribution: {r_peak_stack:.3f}pc") # Have a separate plot of the peak values fig_peak, ax_peak = bpl.subplots() # also track how many galaxies have a p-value above a given threshold n_min = 50
# ============================================================================== # # start comparing velocities # # ============================================================================== def bin_size(data_1, data_2, n_bins): overall_max = np.max([np.max(data_1), np.max(data_2)]) overall_min = np.max([np.min(data_1), np.min(data_2)]) return (overall_max - overall_min) / n_bins for kind in kinds: fig, axs = bpl.subplots(ncols=3, nrows=len(n_plot_levels), figsize=[25, 5 * len(n_plot_levels)]) for idx, ax_row in zip(n_plot_levels, axs): level = "zoom_{}".format(idx) orig_vx = get_data_wrap(data_original, "vx", level, kind) orig_vy = get_data_wrap(data_original, "vy", level, kind) orig_vz = get_data_wrap(data_original, "vz", level, kind) # see if we can just compare the same level try: # will raise ValueError if this level is not present this_vx = get_data_wrap(data_final, "vx", level, kind) this_vy = get_data_wrap(data_final, "vy", level, kind) this_vz = get_data_wrap(data_final, "vz", level, kind) # but if we're on the root grid, we want to do the masking
hf = h5py.File(ic_file_loc) values = np.array(hf['level_{:03d}_{}'.format(level, field)]) hf.close() print(" - Trimming cube from 2^{} to 2^{}".format(level, central_power)) # Trim it to the size requested plot_values = trim_box(values, cut_length) # normalize the positions and velocities. They are all in units where the box # size is one, so multiplying by the grid size will get it into code units if "DM_d" in field or "DM_v" in field: plot_values *= 2**level print(" - Making visualization") # Then make the visualization fig, axs = bpl.subplots(nrows=1, ncols=2, gridspec_kw={"width_ratios":[20, 1]}) ax = axs[0] cax = axs[1] ax.equal_scale() ax.add_labels("X [code units]", "Y [code units]") # vmax determined experimentally with several outputs, although I don't # understand what baryons are doing if "DM_d" in field: cmap = cmocean.cm.delta vmax = 0.2 * 2**(central_power - 5) elif "DM_v" in field: cmap = cmocean.cm.balance vmax = 125 * 2**(central_power - 5) elif "BA_v" in field: cmap = cmocean.cm.curl
norm = colors.Normalize(vmin=0, vmax=vmax) im_data = ax.imshow(psf_data, norm=norm, cmap=cmap, origin="lower") fig.colorbar(im_data, ax=ax, pad=0) ax.remove_labels("both") # ax.remove_spines(["all"]) for psf, star_source in zip([psf_legus, psf_me], ["legus", "my"]): fig, axs = bpl.subplots( ncols=2, figsize=[12, 5], tight_layout=False, gridspec_kw={ "top": 0.9, "left": 0.05, "right": 0.95, "wspace": 0.1 }, ) visualize_psf(fig, axs[0], psf, "linear") visualize_psf(fig, axs[1], psf, "log") # reformat the name if star_source == "my": plot_title = f"{str(home_dir.name).upper()} - Me" else: plot_title = f"{str(home_dir.name).upper()} - LEGUS" fig.suptitle(plot_title, fontsize=24)
return ys # set the colors to be used on the plots colors = { "ngc5194": bpl.color_cycle[0], "ngc628": bpl.color_cycle[1], "ngc1313": bpl.color_cycle[3], "ngc4449": bpl.color_cycle[4], "other_1": bpl.color_cycle[5], "ngc1566": bpl.color_cycle[7], "ngc7793": bpl.color_cycle[6], "other_2": bpl.almost_black, } fig, axs = bpl.subplots(ncols=2, figsize=[14, 7]) radii_plot = np.logspace(-1, 1.5, 300) for idx, galaxy in enumerate(galaxies_1 + galaxies_2): if galaxy in galaxies_1: ax = axs[0] else: ax = axs[1] cat = individual_cats[galaxy] # I want to add an extra space in the legend for NGC628 label = f"NGC {galaxy[3:]}, " if len(galaxy) == 6: # chose spaces fine tuned to align in the legend: # https://www.overleaf.com/learn/latex/Spacing_in_math_mode label += "$\ \ $"
output_name = Path(sys.argv[2]) fit_out_file = open(output_name, "w") big_catalog = mru.make_big_table(sys.argv[3]) # Filter out clusters older than 1 Gyr mask = big_catalog["age_yr"] < 1e9 mass, mass_err_lo, mass_err_hi = mru.get_my_masses(big_catalog, mask) r_eff, r_eff_err_lo, r_eff_err_hi = mru.get_my_radii(big_catalog, mask) age, _, _ = mru.get_my_ages(big_catalog, mask) # Then do several splits by age mask_young = age < 1e7 mask_med = np.logical_and(age >= 1e7, age < 1e8) mask_old = np.logical_and(age >= 1e8, age < 1e9) fig, ax = bpl.subplots(figsize=[8, 5.5]) for age_mask, name, color, zorder in zip( [mask_young, mask_med, mask_old], ["Age: 1--10 Myr", "Age: 10--100 Myr", "Age: 100 Myr -- 1 Gyr"], mru_p.age_colors, [1, 3, 2], ): fit, fit_history = mru_mle.fit_mass_size_relation( mass[age_mask], mass_err_lo[age_mask], mass_err_hi[age_mask], r_eff[age_mask], r_eff_err_lo[age_mask], r_eff_err_hi[age_mask], fit_mass_upper_limit=1e5, )
# music_D.extension, while if we do, they will be of the form # "music_H.extension" # see if the baryon file is in the directory ic_files = os.listdir(ic_dir) has_baryons = "music_H.md" in ic_files data = utils.ARTData(ic_dir, has_baryons) # ============================================================================== # # make the plot # # ============================================================================== for kind in ["particle"] + ["gas"] * has_baryons: fig, axs = bpl.subplots(ncols=3, figsize=[20, 7]) axs = axs.flatten() max_vel = np.max([np.max(data.get_data("v{}".format(dim), "all", kind)) for dim in ["x", "y", "z"]]) min_vel = np.min([np.min(data.get_data("v{}".format(dim), "all", kind)) for dim in ["x", "y", "z"]]) n_bins = 50 bin_size = (max_vel - min_vel) / n_bins for idx in range(10): try: level = "zoom_{}".format(idx) vx = data.get_data("vx", level, kind) vy = data.get_data("vy", level, kind) vz = data.get_data("vz", level, kind)
return bin_centers, ys_percentiles success_color = bpl.color_cycle[0] failure_color = bpl.color_cycle[3] # ====================================================================================== # # Simple plot of cumulative histograms # # ====================================================================================== # This will have several columns for different parameters, with the rows being the # different ways of assessing each parameter fig, axs = bpl.subplots( ncols=3, figsize=[16, 6], tight_layout=False, gridspec_kw={"top": 0.9, "bottom": 0.2, "left": 0.08, "right": 0.98}, ) for ax, param in zip(axs, plot_params): # Then the cumulative histogram ax.plot( *make_cumulative_histogram(big_catalog[param][success_mask]), color=success_color, lw=2, label=f"Success (N={n_good:,})", ) ax.plot( *make_cumulative_histogram(big_catalog[param][~success_mask]), color=failure_color, lw=2, label=f"Failure (N={len(big_catalog) - n_good:,})",
} param_limits = { "scale_radius_pixels": (0.05, 20), "axis_ratio": (-0.05, 1.05), "position_angle": (0, np.pi), "power_law_slope": (0, 3), } param_scale = { "scale_radius_pixels": "log", "axis_ratio": "linear", "position_angle": "linear", "power_law_slope": "linear", } # then plot fig, axs = bpl.subplots(ncols=2, nrows=2, figsize=[12, 12]) axs = axs.flatten() plot_colors = [ mappable.to_rgba(np.log10(v)) if take_cbar_log else mappable.to_rgba(v) for v in catalog[cbar_quantity] ] for p, ax in zip(params_to_compare, axs): ax.scatter( catalog[p + "_true"], catalog[p], alpha=1, c=plot_colors, ) ax.plot([0, 1e10], [0, 1e10], ls=":", c=bpl.almost_black, zorder=0)
cmap.set_bad(cmap(0)) # for negative values in log plot ncols = 5 nrows = int(np.ceil(len(star_cutouts) / 5)) top_inches = 1.5 inches_per_row = 3 inches_per_col = 3.4 fig, axs = bpl.subplots( nrows=nrows, ncols=ncols, figsize=[inches_per_col * ncols, top_inches + inches_per_row * nrows], tight_layout=False, gridspec_kw={ "top": (inches_per_row * nrows) / (top_inches + inches_per_row * nrows), "wspace": 0.18, "hspace": 0.35, "left": 0.01, "right": 0.98, "bottom": 0.01, }, ) axs = axs.flatten() for ax in axs: ax.set_axis_off() for ax, cutout, row, fitted_star in zip(axs, star_cutouts, star_table, fitted_stars): vmax = np.max(cutout) vmin = -5 * noise
"bound fraction M > 5000", np.sum(catalog["bound"][massive_mask]) / len(catalog[massive_mask]), ) old_mask = catalog["age_yr"] >= 1e7 print( "bound fraction age > 1e7", np.sum(catalog["bound"][old_mask]) / len(catalog[old_mask]), ) # ====================================================================================== # # make the simple plot # # ====================================================================================== figsize = [8, 5.5] fig, ax = bpl.subplots(figsize=figsize) # make the colormap for masses # cmap = cm.get_cmap("gist_earth_r") # cmap = cmocean.cm.thermal_r # cmap = cmocean.tools.crop_by_percent(cmap, 20, "min") # make a custom colormap madee manually by taking colors from # https://sashamaps.net/docs/resources/20-colors/ and fading them cmap_colors = ["#f58231", "#FFAC71", "#8BA4FD", "#4363d8"] cmap = colors.ListedColormap(colors=cmap_colors, name="") norm = colors.LogNorm(vmin=1e3, vmax=1e5) mappable = cm.ScalarMappable(cmap=cmap, norm=norm) mass_colors = mappable.to_rgba(catalog["mass_msun"]) # perturb the ages slightly for plotting purposes. Copy them to avoid messing up # later analysis plot_ages = catalog["age_yr"].copy() plot_ages *= np.random.normal(1, 0.15, len(plot_ages))