From 72a6938437618790c68e5e3efaba321c8104d876 Mon Sep 17 00:00:00 2001 From: Thibault Barnouin Date: Thu, 11 Jul 2024 15:11:57 +0200 Subject: [PATCH 01/18] some plot fix --- package/FOC_reduction.py | 8 ++++---- package/lib/plots.py | 27 +++++++++++++++------------ 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/package/FOC_reduction.py b/package/FOC_reduction.py index d93e453..17cf3d1 100755 --- a/package/FOC_reduction.py +++ b/package/FOC_reduction.py @@ -36,7 +36,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= # Background estimation error_sub_type = "freedman-diaconis" # sqrt, sturges, rice, scott, freedman-diaconis (default) or shape (example (51, 51)) - subtract_error = 1.0 + subtract_error = 2.0 display_bkg = False # Data binning @@ -54,8 +54,8 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= # Smoothing smoothing_function = "combine" # gaussian_after, weighted_gaussian_after, gaussian, weighted_gaussian or combine - smoothing_FWHM = 2.0 # If None, no smoothing is done - smoothing_scale = "px" # pixel or arcsec + smoothing_FWHM = 1.50 # If None, no smoothing is done + smoothing_scale = "px" # pixel or arcsec # Rotation rotate_North = True @@ -401,7 +401,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= deepcopy(Stokes_hdul), data_mask, SNRp_cut=SNRp_cut, SNRi_cut=SNRi_cut, savename=figname, plots_folder=plots_folder, display="integrate" ) elif pxscale.lower() not in ["full", "integrate"]: - proj_plots.pol_map(Stokes_hdul, SNRp_cut=SNRp_cut, SNRi_cut=SNRi_cut, flux_lim=flux_lim) + proj_plots.pol_map(Stokes_hdul, SNRp_cut=SNRp_cut, SNRi_cut=SNRi_cut, step_vec=step_vec, scale_vec=scale_vec, flux_lim=flux_lim) return outfiles diff --git a/package/lib/plots.py b/package/lib/plots.py index 9cba169..4906941 100755 --- a/package/lib/plots.py +++ b/package/lib/plots.py @@ -326,7 +326,7 @@ def polarization_map( plt.rcdefaults() ratiox = max(int(stkI.shape[1]/(stkI.shape[0])),1) ratioy = max(int((stkI.shape[0])/stkI.shape[1]),1) - fig, ax = plt.subplots(figsize=(6*ratiox, 6*ratioy), layout="compressed", subplot_kw=dict(projection=wcs)) + fig, ax = plt.subplots(figsize=(7*ratiox, 7*ratioy), layout="compressed", subplot_kw=dict(projection=wcs)) ax.set(aspect="equal", fc="k", ylim=[-stkI.shape[0]*0.10,stkI.shape[0]*1.15]) # fig.subplots_adjust(hspace=0, wspace=0, left=0.102, right=1.02) @@ -449,8 +449,8 @@ def polarization_map( ax.transAxes, "E", "N", - length=-0.05, - fontsize=0.02, + length=-0.07, + fontsize=0.03, loc=1, aspect_ratio=-(stkI.shape[1]/(stkI.shape[0]*1.25)), sep_y=0.01, @@ -670,7 +670,7 @@ class align_maps(object): length=-0.08, fontsize=0.03, loc=1, - aspect_ratio=-(self.map_data.shape[1]/self.map_data.shape[0]), + aspect_ratio=-(self.map_ax.get_xbound()[1]-self.map_ax.get_xbound()[0])/(self.map_ax.get_ybound()[1]-self.map_ax.get_ybound()[0]), sep_y=0.01, sep_x=0.01, angle=-self.map_header["orientat"], @@ -722,13 +722,13 @@ class align_maps(object): ) if "ORIENTAT" in list(self.other_header.keys()): north_dir2 = AnchoredDirectionArrows( - self.map_ax.transAxes, + self.other_ax.transAxes, "E", "N", length=-0.08, fontsize=0.03, loc=1, - aspect_ratio=-(self.other_data.shape[1]/self.other_data.shape[0]), + aspect_ratio=-(self.other_ax.get_xbound()[1]-self.other_ax.get_xbound()[0])/(self.other_ax.get_ybound()[1]-self.other_ax.get_ybound()[0]), sep_y=0.01, sep_x=0.01, angle=-self.other_header["orientat"], @@ -1272,7 +1272,9 @@ class overplot_pol(align_maps): pol[SNRi < SNRi_cut] = np.nan plt.rcParams.update({"font.size": 16}) - self.fig_overplot, self.ax_overplot = plt.subplots(figsize=(11, 10), subplot_kw=dict(projection=self.other_wcs)) + ratiox = max(int(stkI.shape[1]/stkI.shape[0]),1) + ratioy = max(int(stkI.shape[0]/stkI.shape[1]),1) + self.fig_overplot, self.ax_overplot = plt.subplots(figsize=(10*ratiox, 10*ratioy), subplot_kw=dict(projection=self.other_wcs)) self.fig_overplot.subplots_adjust(hspace=0, wspace=0, bottom=0.1, left=0.1, top=0.80, right=1.02) self.ax_overplot.set_xlabel(label="Right Ascension (J2000)") @@ -1327,11 +1329,12 @@ class overplot_pol(align_maps): ) # Display full size polarization vectors + px_scale = self.wcs_UV.wcs.get_cdelt()[0]/self.other_wcs.wcs.get_cdelt()[0] if scale_vec is None: - self.scale_vec = 2.0 + self.scale_vec = 2.0*px_scale pol[np.isfinite(pol)] = 1.0 / 2.0 else: - self.scale_vec = scale_vec + self.scale_vec = scale_vec*px_scale step_vec = 1 self.X, self.Y = np.meshgrid(np.arange(stkI.shape[1]), np.arange(stkI.shape[0])) self.U, self.V = pol * np.cos(np.pi / 2.0 + pang * np.pi / 180.0), pol * np.sin(np.pi / 2.0 + pang * np.pi / 180.0) @@ -1348,8 +1351,8 @@ class overplot_pol(align_maps): headwidth=0.0, headlength=0.0, headaxislength=0.0, - width=0.5, - linewidth=0.75, + width=0.5*px_scale, + linewidth=0.3*px_scale, color="white", edgecolor="black", transform=self.ax_overplot.get_transform(self.wcs_UV), @@ -1388,7 +1391,7 @@ class overplot_pol(align_maps): length=-0.08, fontsize=0.03, loc=1, - aspect_ratio=-(stkI.shape[1]/stkI.shape[0]), + aspect_ratio=-(self.ax_overplot.get_xbound()[1]-self.ax_overplot.get_xbound()[0])/(self.ax_overplot.get_ybound()[1]-self.ax_overplot.get_ybound()[0]), sep_y=0.01, sep_x=0.01, angle=-self.Stokes_UV[0].header["orientat"], From 1c60e875e8a2f03c6bc0ae60e5ffec377f49d4ef Mon Sep 17 00:00:00 2001 From: Thibault Barnouin Date: Tue, 16 Jul 2024 11:40:40 +0200 Subject: [PATCH 02/18] np.mat to np.asmatrix for Numpy 2.0 --- package/lib/reduction.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/lib/reduction.py b/package/lib/reduction.py index 2b6f736..a9ce0f1 100755 --- a/package/lib/reduction.py +++ b/package/lib/reduction.py @@ -217,9 +217,9 @@ def bin_ndarray(ndarray, new_shape, operation="sum"): elif operation.lower() in ["mean", "average", "avg"]: ndarray = ndarray.mean(-1 * (i + 1)) else: - row_comp = np.mat(get_row_compressor(ndarray.shape[0], new_shape[0], operation)) - col_comp = np.mat(get_column_compressor(ndarray.shape[1], new_shape[1], operation)) - ndarray = np.array(row_comp * np.mat(ndarray) * col_comp) + row_comp = np.asmatrix(get_row_compressor(ndarray.shape[0], new_shape[0], operation)) + col_comp = np.asmatrix(get_column_compressor(ndarray.shape[1], new_shape[1], operation)) + ndarray = np.array(row_comp * np.asmatrix(ndarray) * col_comp) return ndarray From 904d29839883a47ef9520d00e1706f8dcbc3fe6b Mon Sep 17 00:00:00 2001 From: Thibault Barnouin Date: Mon, 2 Sep 2024 16:23:32 +0200 Subject: [PATCH 03/18] add confidence level computation and better display --- package/FOC_reduction.py | 12 ++--- package/lib/plots.py | 108 ++++++++++++++++++++++++--------------- package/lib/utils.py | 13 +++++ 3 files changed, 85 insertions(+), 48 deletions(-) diff --git a/package/FOC_reduction.py b/package/FOC_reduction.py index 17cf3d1..04345f3 100755 --- a/package/FOC_reduction.py +++ b/package/FOC_reduction.py @@ -36,12 +36,12 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= # Background estimation error_sub_type = "freedman-diaconis" # sqrt, sturges, rice, scott, freedman-diaconis (default) or shape (example (51, 51)) - subtract_error = 2.0 + subtract_error = 0.5 display_bkg = False # Data binning - pxsize = 2 - pxscale = "px" # pixel, arcsec or full + pxsize = 0.05 + pxscale = "arcsec" # pixel, arcsec or full rebin_operation = "sum" # sum or average # Alignement @@ -54,8 +54,8 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= # Smoothing smoothing_function = "combine" # gaussian_after, weighted_gaussian_after, gaussian, weighted_gaussian or combine - smoothing_FWHM = 1.50 # If None, no smoothing is done - smoothing_scale = "px" # pixel or arcsec + smoothing_FWHM = 0.075 # If None, no smoothing is done + smoothing_scale = "arcsec" # pixel or arcsec # Rotation rotate_North = True @@ -64,7 +64,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= SNRp_cut = 3.0 # P measurments with SNR>3 SNRi_cut = 1.0 # I measurments with SNR>30, which implies an uncertainty in P of 4.7%. flux_lim = None # lowest and highest flux displayed on plot, defaults to bkg and maximum in cut if None - scale_vec = 5 + scale_vec = 3 step_vec = 1 # plot all vectors in the array. if step_vec = 2, then every other vector will be plotted if step_vec = 0 then all vectors are displayed at full length # Pipeline start diff --git a/package/lib/plots.py b/package/lib/plots.py index 4906941..3a694c6 100755 --- a/package/lib/plots.py +++ b/package/lib/plots.py @@ -61,9 +61,9 @@ from mpl_toolkits.axes_grid1.anchored_artists import ( from scipy.ndimage import zoom as sc_zoom try: - from .utils import princ_angle, rot2D, sci_not + from .utils import PCconf, princ_angle, rot2D, sci_not except ImportError: - from utils import princ_angle, rot2D, sci_not + from utils import PCconf, princ_angle, rot2D, sci_not def plot_obs(data_array, headers, rectangle=None, savename=None, plots_folder="", **kwargs): @@ -99,7 +99,7 @@ def plot_obs(data_array, headers, rectangle=None, savename=None, plots_folder="" plt.rcParams.update({"font.size": 10}) nb_obs = np.max([np.sum([head["filtnam1"] == curr_pol for head in headers]) for curr_pol in ["POL0", "POL60", "POL120"]]) shape = np.array((3, nb_obs)) - fig, ax = plt.subplots(shape[0], shape[1], figsize=(3 * shape[1], 3 * shape[0]), dpi=200, layout="constrained", sharex=True, sharey=True) + fig, ax = plt.subplots(shape[0], shape[1], figsize=(3 * shape[1], 3 * shape[0]), layout="constrained", sharex=True, sharey=True) r_pol = dict(pol0=0, pol60=1, pol120=2) c_pol = dict(pol0=0, pol60=0, pol120=0) for i, (data, head) in enumerate(zip(data_array, headers)): @@ -148,7 +148,7 @@ def plot_obs(data_array, headers, rectangle=None, savename=None, plots_folder="" # fig.suptitle(savename) if savename[-4:] not in [".png", ".jpg", ".pdf"]: savename += ".pdf" - fig.savefig(path_join(plots_folder, savename), bbox_inches="tight") + fig.savefig(path_join(plots_folder, savename), bbox_inches="tight", dpi=150, facecolor="None") plt.show() return 0 @@ -183,9 +183,9 @@ def plot_Stokes(Stokes, savename=None, plots_folder=""): # Plot figure plt.rcParams.update({"font.size": 14}) - ratiox = max(int(stkI.shape[1]/stkI.shape[0]),1) - ratioy = max(int(stkI.shape[0]/stkI.shape[1]),1) - fig, (axI, axQ, axU) = plt.subplots(ncols=3, figsize=(15*ratiox, 6*ratioy), subplot_kw=dict(projection=wcs)) + ratiox = max(int(stkI.shape[1] / stkI.shape[0]), 1) + ratioy = max(int(stkI.shape[0] / stkI.shape[1]), 1) + fig, (axI, axQ, axU) = plt.subplots(ncols=3, figsize=(15 * ratiox, 6 * ratioy), subplot_kw=dict(projection=wcs)) fig.subplots_adjust(hspace=0, wspace=0.50, bottom=0.01, top=0.99, left=0.07, right=0.97) fig.suptitle("I, Q, U Stokes parameters") @@ -207,7 +207,7 @@ def plot_Stokes(Stokes, savename=None, plots_folder=""): savename += "_IQU.pdf" else: savename = savename[:-4] + "_IQU" + savename[-4:] - fig.savefig(path_join(plots_folder, savename), bbox_inches="tight") + fig.savefig(path_join(plots_folder, savename), bbox_inches="tight", dpi=150, facecolor="None") plt.show() return 0 @@ -324,10 +324,10 @@ def polarization_map( # Plot the map plt.rcParams.update({"font.size": 14}) plt.rcdefaults() - ratiox = max(int(stkI.shape[1]/(stkI.shape[0])),1) - ratioy = max(int((stkI.shape[0])/stkI.shape[1]),1) - fig, ax = plt.subplots(figsize=(7*ratiox, 7*ratioy), layout="compressed", subplot_kw=dict(projection=wcs)) - ax.set(aspect="equal", fc="k", ylim=[-stkI.shape[0]*0.10,stkI.shape[0]*1.15]) + ratiox = max(int(stkI.shape[1] / (stkI.shape[0])), 1) + ratioy = max(int((stkI.shape[0]) / stkI.shape[1]), 1) + fig, ax = plt.subplots(figsize=(7 * ratiox, 7 * ratioy), layout="compressed", subplot_kw=dict(projection=wcs)) + ax.set(aspect="equal", fc="k", ylim=[-stkI.shape[0] * 0.10, stkI.shape[0] * 1.15]) # fig.subplots_adjust(hspace=0, wspace=0, left=0.102, right=1.02) # ax.coords.grid(True, color='white', ls='dotted', alpha=0.5) @@ -452,7 +452,7 @@ def polarization_map( length=-0.07, fontsize=0.03, loc=1, - aspect_ratio=-(stkI.shape[1]/(stkI.shape[0]*1.25)), + aspect_ratio=-(stkI.shape[1] / (stkI.shape[0] * 1.25)), sep_y=0.01, sep_x=0.01, back_length=0.0, @@ -534,7 +534,7 @@ def polarization_map( if savename is not None: if savename[-4:] not in [".png", ".jpg", ".pdf"]: savename += ".pdf" - fig.savefig(path_join(plots_folder, savename), bbox_inches="tight", dpi=200) + fig.savefig(path_join(plots_folder, savename), bbox_inches="tight", dpi=150, facecolor="None") plt.show() return fig, ax @@ -670,7 +670,7 @@ class align_maps(object): length=-0.08, fontsize=0.03, loc=1, - aspect_ratio=-(self.map_ax.get_xbound()[1]-self.map_ax.get_xbound()[0])/(self.map_ax.get_ybound()[1]-self.map_ax.get_ybound()[0]), + aspect_ratio=-(self.map_ax.get_xbound()[1] - self.map_ax.get_xbound()[0]) / (self.map_ax.get_ybound()[1] - self.map_ax.get_ybound()[0]), sep_y=0.01, sep_x=0.01, angle=-self.map_header["orientat"], @@ -728,7 +728,7 @@ class align_maps(object): length=-0.08, fontsize=0.03, loc=1, - aspect_ratio=-(self.other_ax.get_xbound()[1]-self.other_ax.get_xbound()[0])/(self.other_ax.get_ybound()[1]-self.other_ax.get_ybound()[0]), + aspect_ratio=-(self.other_ax.get_xbound()[1] - self.other_ax.get_xbound()[0]) / (self.other_ax.get_ybound()[1] - self.other_ax.get_ybound()[0]), sep_y=0.01, sep_x=0.01, angle=-self.other_header["orientat"], @@ -992,7 +992,7 @@ class overplot_radio(align_maps): length=-0.08, fontsize=0.03, loc=1, - aspect_ratio=-(stkI.shape[1]/stkI.shape[0]), + aspect_ratio=-(stkI.shape[1] / stkI.shape[0]), sep_y=0.01, sep_x=0.01, angle=-self.Stokes_UV[0].header["orientat"], @@ -1033,7 +1033,7 @@ class overplot_radio(align_maps): if savename is not None: if savename[-4:] not in [".png", ".jpg", ".pdf"]: savename += ".pdf" - self.fig_overplot.savefig(savename, bbox_inches="tight", dpi=200) + self.fig_overplot.savefig(savename, bbox_inches="tight", dpi=150, facecolor="None") self.fig_overplot.canvas.draw() @@ -1194,7 +1194,7 @@ class overplot_chandra(align_maps): length=-0.08, fontsize=0.03, loc=1, - aspect_ratio=-(stkI.shape[1]/stkI.shape[0]), + aspect_ratio=-(stkI.shape[1] / stkI.shape[0]), sep_y=0.01, sep_x=0.01, angle=-self.Stokes_UV[0].header["orientat"], @@ -1232,7 +1232,7 @@ class overplot_chandra(align_maps): if savename is not None: if savename[-4:] not in [".png", ".jpg", ".pdf"]: savename += ".pdf" - self.fig_overplot.savefig(savename, bbox_inches="tight", dpi=200) + self.fig_overplot.savefig(savename, bbox_inches="tight", dpi=150, facecolor="None") self.fig_overplot.canvas.draw() @@ -1272,9 +1272,10 @@ class overplot_pol(align_maps): pol[SNRi < SNRi_cut] = np.nan plt.rcParams.update({"font.size": 16}) - ratiox = max(int(stkI.shape[1]/stkI.shape[0]),1) - ratioy = max(int(stkI.shape[0]/stkI.shape[1]),1) - self.fig_overplot, self.ax_overplot = plt.subplots(figsize=(10*ratiox, 10*ratioy), subplot_kw=dict(projection=self.other_wcs)) + ratiox = max(int(stkI.shape[1] / stkI.shape[0]), 1) + ratioy = max(int(stkI.shape[0] / stkI.shape[1]), 1) + px_scale = self.wcs_UV.wcs.get_cdelt()[0] / self.other_wcs.wcs.get_cdelt()[0] + self.fig_overplot, self.ax_overplot = plt.subplots(figsize=(10 * ratiox, 10 * ratioy), subplot_kw=dict(projection=self.other_wcs)) self.fig_overplot.subplots_adjust(hspace=0, wspace=0, bottom=0.1, left=0.1, top=0.80, right=1.02) self.ax_overplot.set_xlabel(label="Right Ascension (J2000)") @@ -1288,7 +1289,12 @@ class overplot_pol(align_maps): # Display "other" intensity map vmin, vmax = other_data[other_data > 0.0].max() / 1e3 * self.other_convert, other_data[other_data > 0.0].max() * self.other_convert - for key, value in [["cmap", [["cmap", "inferno"]]], ["norm", [["vmin", vmin], ["vmax", vmax]]]]: + for key, value in [ + ["cmap", [["cmap", "inferno"]]], + ["norm", [["vmin", vmin], ["vmax", vmax]]], + ["width", [["width", 0.5 * px_scale]]], + ["linewidth", [["linewidth", 0.3 * px_scale]]], + ]: try: _ = kwargs[key] except KeyError: @@ -1323,18 +1329,19 @@ class overplot_pol(align_maps): else: self.ax_overplot.set_facecolor("white") font_color = "black" - self.im = self.ax_overplot.imshow(other_data * self.other_convert, alpha=1.0, label="{0:s} observation".format(self.other_observer), **kwargs) + self.im = self.ax_overplot.imshow( + other_data * self.other_convert, alpha=1.0, label="{0:s} observation".format(self.other_observer), cmap=kwargs["cmap"], norm=kwargs["norm"] + ) self.cbar = self.fig_overplot.colorbar( self.im, ax=self.ax_overplot, aspect=80, shrink=0.75, pad=0.025, label=r"$F_{{\lambda}}$ [{0:s}]".format(self.other_unit) ) # Display full size polarization vectors - px_scale = self.wcs_UV.wcs.get_cdelt()[0]/self.other_wcs.wcs.get_cdelt()[0] if scale_vec is None: - self.scale_vec = 2.0*px_scale + self.scale_vec = 2.0 * px_scale pol[np.isfinite(pol)] = 1.0 / 2.0 else: - self.scale_vec = scale_vec*px_scale + self.scale_vec = scale_vec * px_scale step_vec = 1 self.X, self.Y = np.meshgrid(np.arange(stkI.shape[1]), np.arange(stkI.shape[0])) self.U, self.V = pol * np.cos(np.pi / 2.0 + pang * np.pi / 180.0), pol * np.sin(np.pi / 2.0 + pang * np.pi / 180.0) @@ -1345,14 +1352,14 @@ class overplot_pol(align_maps): self.V[::step_vec, ::step_vec], units="xy", angles="uv", - scale=1. / self.scale_vec, + scale=1.0 / self.scale_vec, scale_units="xy", pivot="mid", headwidth=0.0, headlength=0.0, headaxislength=0.0, - width=0.5*px_scale, - linewidth=0.3*px_scale, + width=kwargs["width"], + linewidth=kwargs["linewidth"], color="white", edgecolor="black", transform=self.ax_overplot.get_transform(self.wcs_UV), @@ -1391,7 +1398,8 @@ class overplot_pol(align_maps): length=-0.08, fontsize=0.03, loc=1, - aspect_ratio=-(self.ax_overplot.get_xbound()[1]-self.ax_overplot.get_xbound()[0])/(self.ax_overplot.get_ybound()[1]-self.ax_overplot.get_ybound()[0]), + aspect_ratio=-(self.ax_overplot.get_xbound()[1] - self.ax_overplot.get_xbound()[0]) + / (self.ax_overplot.get_ybound()[1] - self.ax_overplot.get_ybound()[0]), sep_y=0.01, sep_x=0.01, angle=-self.Stokes_UV[0].header["orientat"], @@ -1437,7 +1445,7 @@ class overplot_pol(align_maps): if savename is not None: if savename[-4:] not in [".png", ".jpg", ".pdf"]: savename += ".pdf" - self.fig_overplot.savefig(savename, bbox_inches="tight", dpi=200) + self.fig_overplot.savefig(savename, bbox_inches="tight", dpi=150, facecolor="None") self.fig_overplot.canvas.draw() @@ -1454,18 +1462,21 @@ class overplot_pol(align_maps): position = self.other_wcs.world_to_pixel(position) u, v = pol_deg * np.cos(np.radians(pol_ang) + np.pi / 2.0), pol_deg * np.sin(np.radians(pol_ang) + np.pi / 2.0) - for key, value in [["scale", [["scale", self.scale_vec]]], ["width", [["width", 0.1]]], ["color", [["color", "k"]]]]: + for key, value in [["scale", [["scale", self.scale_vec]]], ["width", [["width", 0.1]]], ["color", [["color", "k"]]], ["edgecolor", [["edgecolor", "w"]]]]: try: _ = kwargs[key] except KeyError: for key_i, val_i in value: kwargs[key_i] = val_i + handles, labels = self.legend.legend_handles, [l.get_text() for l in self.legend.texts] new_vec = self.ax_overplot.quiver( *position, u, v, units="xy", angles="uv", scale_units="xy", pivot="mid", headwidth=0.0, headlength=0.0, headaxislength=0.0, **kwargs ) + handles.append(FancyArrowPatch((0, 0), (0, 1), arrowstyle="-", fc=new_vec.get_fc(), ec=new_vec.get_ec())) + labels.append(new_vec.get_label()) self.legend.remove() self.legend = self.ax_overplot.legend( - title=self.legend_title, bbox_to_anchor=(0.0, 1.02, 1.0, 0.102), loc="lower left", mode="expand", borderaxespad=0.0 + title=self.legend_title, handles=handles, labels=labels, bbox_to_anchor=(0.0, 1.02, 1.0, 0.102), loc="lower left", mode="expand", borderaxespad=0.0 ) self.fig_overplot.canvas.draw() return new_vec @@ -1556,7 +1567,7 @@ class align_pol(object): length=-0.08, fontsize=0.025, loc=1, - aspect_ratio=-(stkI.shape[1]/stkI.shape[0]), + aspect_ratio=-(stkI.shape[1] / stkI.shape[0]), sep_y=0.01, sep_x=0.01, back_length=0.0, @@ -1605,7 +1616,7 @@ class align_pol(object): if savename is not None: if savename[-4:] not in [".png", ".jpg", ".pdf"]: savename += ".pdf" - fig.savefig(savename, bbox_inches="tight", dpi=300) + fig.savefig(savename, bbox_inches="tight", dpi=150, facecolor="None") plt.show(block=True) return fig, ax @@ -2592,7 +2603,7 @@ class pol_map(object): save_fig.suptitle(r"{0:s} with $SNR_{{p}} \geq$ {1:d} and $SNR_{{I}} \geq$ {2:d}".format(self.targ, int(self.SNRp), int(self.SNRi))) if expression[-4:] not in [".png", ".jpg", ".pdf"]: expression += ".pdf" - save_fig.savefig(expression, bbox_inches="tight", dpi=200) + save_fig.savefig(expression, bbox_inches="tight", dpi=150, facecolor="None") plt.close(save_fig) text_save.set_val("") ax_snr_reset.set(visible=True) @@ -2810,7 +2821,7 @@ class pol_map(object): length=-0.05, fontsize=0.02, loc=1, - aspect_ratio=-(self.I.shape[1]/self.I.shape[0]), + aspect_ratio=-(self.I.shape[1] / self.I.shape[0]), sep_y=0.01, sep_x=0.01, back_length=0.0, @@ -3048,6 +3059,7 @@ class pol_map(object): fig.canvas.draw_idle() def pol_int(self, fig=None, ax=None): + str_conf = "" if self.region is None: s_I = np.sqrt(self.IQU_cov[0, 0]) I_reg = self.I.sum() @@ -3109,6 +3121,10 @@ class pol_map(object): IU_reg_err = np.sqrt(np.sum(s_IU[self.region] ** 2)) QU_reg_err = np.sqrt(np.sum(s_QU[self.region] ** 2)) + conf = PCconf(QN=Q_reg / I_reg, QN_ERR=Q_reg_err / I_reg, UN=U_reg / I_reg, UN_ERR=U_reg_err / I_reg) + if 1.0 - conf > 1e-3: + str_conf = "\n" + r"Confidence: {0:.2f} %".format(conf * 100.0) + with np.errstate(divide="ignore", invalid="ignore"): P_reg = np.sqrt(Q_reg**2 + U_reg**2) / I_reg P_reg_err = ( @@ -3175,6 +3191,7 @@ class pol_map(object): + r"$P^{{int}}$ = {0:.1f} $\pm$ {1:.1f} %".format(P_reg * 100.0, np.ceil(P_reg_err * 1000.0) / 10.0) + "\n" + r"$\theta_{{P}}^{{int}}$ = {0:.1f} $\pm$ {1:.1f} °".format(PA_reg, np.ceil(PA_reg_err * 10.0) / 10.0) + + str_conf ) self.str_cut = "" # self.str_cut = "\n"+r"$F_{{\lambda}}^{{cut}}$({0:.0f} $\AA$) = {1} $ergs \cdot cm^{{-2}} \cdot s^{{-1}} \cdot \AA^{{-1}}$".format(self.pivot_wav, sci_not(I_cut*self.map_convert, I_cut_err*self.map_convert, 2))+"\n"+r"$P^{{cut}}$ = {0:.1f} $\pm$ {1:.1f} %".format(P_cut*100., np.ceil(P_cut_err*1000.)/10.)+"\n"+r"$\theta_{{P}}^{{cut}}$ = {0:.1f} $\pm$ {1:.1f} °".format(PA_cut, np.ceil(PA_cut_err*10.)/10.) @@ -3201,6 +3218,7 @@ class pol_map(object): + r"$P^{{int}}$ = {0:.1f} $\pm$ {1:.1f} %".format(P_reg * 100.0, np.ceil(P_reg_err * 1000.0) / 10.0) + "\n" + r"$\theta_{{P}}^{{int}}$ = {0:.1f} $\pm$ {1:.1f} °".format(PA_reg, np.ceil(PA_reg_err * 10.0) / 10.0) + + str_conf ) str_cut = "" # str_cut = "\n"+r"$F_{{\lambda}}^{{cut}}$({0:.0f} $\AA$) = {1} $ergs \cdot cm^{{-2}} \cdot s^{{-1}} \cdot \AA^{{-1}}$".format(self.pivot_wav, sci_not(I_cut*self.map_convert, I_cut_err*self.map_convert, 2))+"\n"+r"$P^{{cut}}$ = {0:.1f} $\pm$ {1:.1f} %".format(P_cut*100., np.ceil(P_cut_err*1000.)/10.)+"\n"+r"$\theta_{{P}}^{{cut}}$ = {0:.1f} $\pm$ {1:.1f} °".format(PA_cut, np.ceil(PA_cut_err*10.)/10.) @@ -3236,7 +3254,9 @@ if __name__ == "__main__": ) parser.add_argument("-pa", "--pang-err", action="store_true", required=False, help="Whether the polarization angle uncertainties should be displayed") parser.add_argument("-l", "--lim", metavar="flux_lim", nargs=2, required=False, help="Limits for the intensity map", type=float, default=None) - parser.add_argument("-pdf", "--static-pdf", metavar="static_pdf", required=False, help="Whether the analysis tool or the static pdfs should be outputed", default=None) + parser.add_argument( + "-pdf", "--static-pdf", metavar="static_pdf", required=False, help="Whether the analysis tool or the static pdfs should be outputed", default=None + ) args = parser.parse_args() if args.file is not None: @@ -3350,7 +3370,11 @@ if __name__ == "__main__": display="SNRp", ) else: - pol_map(Stokes_UV, SNRp_cut=args.snrp, SNRi_cut=args.snri, step_vec=args.step_vec, scale_vec=args.scale_vec, flux_lim=args.lim, pa_err=args.pang_err) + pol_map( + Stokes_UV, SNRp_cut=args.snrp, SNRi_cut=args.snri, step_vec=args.step_vec, scale_vec=args.scale_vec, flux_lim=args.lim, pa_err=args.pang_err + ) else: - print("python3 plots.py -f -p -i -st -sc -l -pa --pdf ") + print( + "python3 plots.py -f -p -i -st -sc -l -pa --pdf " + ) diff --git a/package/lib/utils.py b/package/lib/utils.py index bf4128c..858b8aa 100755 --- a/package/lib/utils.py +++ b/package/lib/utils.py @@ -28,6 +28,18 @@ def princ_angle(ang): return A[0] +def PCconf(QN, UN, QN_ERR, UN_ERR): + """ + Compute the confidence level for 2 parameters polarisation degree and + polarisation angle from the PCUBE analysis. + """ + mask = np.logical_and(QN_ERR > 0.0, UN_ERR > 0.0) + conf = np.full(QN.shape, -1.0) + chi2 = QN**2 / QN_ERR**2 + UN**2 / UN_ERR**2 + conf[mask] = 1.0 - np.exp(-0.5 * chi2[mask]) + return conf + + def sci_not(v, err, rnd=1, out=str): """ Return the scientifque error notation as a string. @@ -46,6 +58,7 @@ def sci_not(v, err, rnd=1, out=str): else: return *output[1:], -power + def wcs_PA(PC21, PC22): """ Return the position angle in degrees to the North direction of a wcs From bf5373d4e03c29b4122b427256ce49da0927dc5e Mon Sep 17 00:00:00 2001 From: Thibault Barnouin Date: Fri, 6 Sep 2024 17:28:01 +0200 Subject: [PATCH 04/18] add fonction to compute confidence map of center of emission location --- package/lib/utils.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/package/lib/utils.py b/package/lib/utils.py index 858b8aa..204352a 100755 --- a/package/lib/utils.py +++ b/package/lib/utils.py @@ -39,6 +39,23 @@ def PCconf(QN, UN, QN_ERR, UN_ERR): conf[mask] = 1.0 - np.exp(-0.5 * chi2[mask]) return conf +def Centerconf(mask, PA, sPA): + """ + Compute the confidence map for the position of the center of emission. + """ + chi2 = np.full(PA.shape, np.nan) + conf = np.full(PA.shape, -1.0) + yy, xx = np.indices(PA.shape) + def ideal(c): + itheta = np.degrees(np.arctan((yy+0.5-c[1])/(xx+0.5-c[0]))) + itheta[np.isnan(itheta)] = PA[np.isnan(itheta)] + return princ_angle(itheta) + def chisq(c): + return np.sum((princ_angle(PA[mask])-ideal((x,y))[mask])**2/sPA[mask]**2)/np.sum(mask) + for x,y in zip(xx[np.isfinite(PA)],yy[np.isfinite(PA)]): + chi2[y,x] = chisq((x,y)) + conf[mask] = 1.0 - np.exp(-0.5*chi2[mask]) + return conf def sci_not(v, err, rnd=1, out=str): """ From 08cb65200a89961b86fa9b61798d58aa03d2be3e Mon Sep 17 00:00:00 2001 From: Thibault Barnouin Date: Mon, 9 Sep 2024 14:50:04 +0200 Subject: [PATCH 05/18] correction for center confidence and test script --- package/lib/utils.py | 31 +++++++++---- package/test_center.py | 99 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 8 deletions(-) create mode 100644 package/test_center.py diff --git a/package/lib/utils.py b/package/lib/utils.py index 204352a..e28bbff 100755 --- a/package/lib/utils.py +++ b/package/lib/utils.py @@ -39,23 +39,38 @@ def PCconf(QN, UN, QN_ERR, UN_ERR): conf[mask] = 1.0 - np.exp(-0.5 * chi2[mask]) return conf -def Centerconf(mask, PA, sPA): + +def CenterConf(mask, PA, sPA): """ Compute the confidence map for the position of the center of emission. """ chi2 = np.full(PA.shape, np.nan) conf = np.full(PA.shape, -1.0) yy, xx = np.indices(PA.shape) + def ideal(c): - itheta = np.degrees(np.arctan((yy+0.5-c[1])/(xx+0.5-c[0]))) - itheta[np.isnan(itheta)] = PA[np.isnan(itheta)] + itheta = np.full(PA.shape, np.nan) + itheta[(xx + 0.5) != c[0]] = np.degrees(np.arctan((yy[(xx + 0.5) != c[0]] + 0.5 - c[1]) / (xx[(xx + 0.5) != c[0]] + 0.5 - c[0]))) + itheta[(xx + 0.5) == c[0]] = PA[(xx + 0.5) == c[0]] return princ_angle(itheta) + def chisq(c): - return np.sum((princ_angle(PA[mask])-ideal((x,y))[mask])**2/sPA[mask]**2)/np.sum(mask) - for x,y in zip(xx[np.isfinite(PA)],yy[np.isfinite(PA)]): - chi2[y,x] = chisq((x,y)) - conf[mask] = 1.0 - np.exp(-0.5*chi2[mask]) - return conf + return np.sum((princ_angle(PA[mask]) - ideal((c[0], c[1]))[mask]) ** 2 / sPA[mask] ** 2) / np.sum(mask) + + for x, y in zip(xx[np.isfinite(PA)], yy[np.isfinite(PA)]): + chi2[y, x] = chisq((x, y)) + + from scipy.optimize import minimize + from scipy.special import gammainc + + conf[np.isfinite(PA)] = 1.0 - gammainc(0.5, 0.5 * chi2[np.isfinite(PA)]) + result = minimize(chisq, np.array(PA.shape) / 2.0, bounds=[(0, PA.shape[1]), (0.0, PA.shape[0])]) + if result.success: + print("Center of emission found") + else: + print("Center of emission not found") + return conf, result.x + def sci_not(v, err, rnd=1, out=str): """ diff --git a/package/test_center.py b/package/test_center.py new file mode 100644 index 0000000..54c21d4 --- /dev/null +++ b/package/test_center.py @@ -0,0 +1,99 @@ +import matplotlib.pyplot as plt +import numpy as np +from astropy.io.fits import open as fits_open +from astropy.wcs import WCS +from lib.utils import CenterConf, PCconf +from matplotlib.colors import LogNorm +from matplotlib.patches import Rectangle + +levelssnr = np.array([3.0, 4.0]) +levelsconf = np.array([0.99]) + +NGC1068 = fits_open("./data/NGC1068/5144/NGC1068_FOC_b0.05arcsec_c0.07arcsec.fits") +NGC1068conf = PCconf( + NGC1068["Q_STOKES"].data / NGC1068["I_STOKES"].data, + NGC1068["U_STOKES"].data / NGC1068["I_STOKES"].data, + np.sqrt(NGC1068["IQU_COV_MATRIX"].data[1, 1]) / NGC1068["I_STOKES"].data, + np.sqrt(NGC1068["IQU_COV_MATRIX"].data[2, 2]) / NGC1068["I_STOKES"].data, +) +NGC1068mask = NGC1068["DATA_MASK"].data.astype(bool) +NGC1068snr = np.full(NGC1068mask.shape, np.nan) +NGC1068snr[NGC1068["POL_DEG_ERR"].data > 0.0] = ( + NGC1068["POL_DEG_DEBIASED"].data[NGC1068["POL_DEG_ERR"].data > 0.0] / NGC1068["POL_DEG_ERR"].data[NGC1068["POL_DEG_ERR"].data > 0.0] +) + +NGC1068centconf, NGC1068center = CenterConf(NGC1068conf > 0.99, NGC1068["POL_ANG"].data, NGC1068["POL_ANG_ERR"].data) + +figngc, axngc = plt.subplots(1, 2, layout="tight", figsize=(18,9), subplot_kw=dict(projection=WCS(NGC1068[0].header))) + +axngc[0].set(xlabel="RA", ylabel="DEC", title="NGC1069 intensity map with SNR and confidence contours") +imngc = axngc[0].imshow(NGC1068["I_STOKES"].data * NGC1068["I_STOKES"].header["PHOTFLAM"], norm=LogNorm(), cmap="inferno") +ngcsnrcont = axngc[0].contour(NGC1068snr, levelssnr, colors="b") +ngcconfcont = axngc[0].contour(NGC1068conf, levelsconf, colors="r") +ngcconfcenter = axngc[0].plot(*np.unravel_index(np.argmax(NGC1068centconf), NGC1068centconf.shape)[::-1], "k+", label="Best confidence for center") +ngcconfcentcont = axngc[0].contour(NGC1068centconf, 1.-levelsconf, colors="k") +handles, labels = axngc[0].get_legend_handles_labels() +labels.append("SNR contours") +handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=ngcsnrcont.collections[0].get_edgecolor()[0])) +labels.append("CONF99 contour") +handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=ngcconfcont.collections[0].get_edgecolor()[0])) +labels.append("Center CONF99 contour") +handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=ngcconfcentcont.collections[0].get_edgecolor()[0])) +axngc[0].legend(handles=handles, labels=labels) + +axngc[1].set(xlabel="RA", ylabel="DEC", title="Location of the nucleus confidence map") +ngccent = axngc[1].imshow(NGC1068centconf, vmin=0.0, cmap="inferno") +ngccentcont = axngc[1].contour(NGC1068centconf, 1.-levelsconf, colors="grey") +ngccentcenter = axngc[1].plot(*np.unravel_index(np.argmax(NGC1068centconf), NGC1068centconf.shape)[::-1], "k+", label="Best confidence for center") +handles, labels = axngc[1].get_legend_handles_labels() +labels.append("CONF99 contour") +handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=ngccentcont.collections[0].get_edgecolor()[0])) +axngc[1].legend(handles=handles, labels=labels) + +figngc.savefig("NGC1068_center.pdf",dpi=150,facecolor="None") + +################################################################################################### + +MRK463E = fits_open("./data/MRK463E/5960/MRK463E_FOC_b0.05arcsec_c0.07arcsec.fits") +MRK463Econf = PCconf( + MRK463E["Q_STOKES"].data / MRK463E["I_STOKES"].data, + MRK463E["U_STOKES"].data / MRK463E["I_STOKES"].data, + np.sqrt(MRK463E["IQU_COV_MATRIX"].data[1, 1]) / MRK463E["I_STOKES"].data, + np.sqrt(MRK463E["IQU_COV_MATRIX"].data[2, 2]) / MRK463E["I_STOKES"].data, +) +MRK463Emask = MRK463E["DATA_MASK"].data.astype(bool) +MRK463Esnr = np.full(MRK463Emask.shape, np.nan) +MRK463Esnr[MRK463E["POL_DEG_ERR"].data > 0.0] = ( + MRK463E["POL_DEG_DEBIASED"].data[MRK463E["POL_DEG_ERR"].data > 0.0] / MRK463E["POL_DEG_ERR"].data[MRK463E["POL_DEG_ERR"].data > 0.0] +) + +MRK463Ecentconf, MRK463Ecenter = CenterConf(MRK463Econf > 0.99, MRK463E["POL_ANG"].data, MRK463E["POL_ANG_ERR"].data) + +figmrk, axmrk = plt.subplots(1, 2, layout="tight", figsize=(18,9), subplot_kw=dict(projection=WCS(MRK463E[0].header))) + +axmrk[0].set(xlabel="RA", ylabel="DEC", title="NGC1069 intensity map with SNR and confidence contours") +immrk = axmrk[0].imshow(MRK463E["I_STOKES"].data * MRK463E["I_STOKES"].header["PHOTFLAM"], norm=LogNorm(), cmap="inferno") +mrksnrcont = axmrk[0].contour(MRK463Esnr, levelssnr, colors="b") +mrkconfcont = axmrk[0].contour(MRK463Econf, levelsconf, colors="r") +mrkconfcenter = axmrk[0].plot(*np.unravel_index(np.argmax(MRK463Ecentconf), MRK463Ecentconf.shape)[::-1], "k+", label="Best confidence for center") +mrkconfcentcont = axmrk[0].contour(MRK463Ecentconf, 1.-levelsconf, colors="k") +handles, labels = axmrk[1].get_legend_handles_labels() +labels.append("SNR contours") +handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=mrksnrcont.collections[0].get_edgecolor()[0])) +labels.append("CONF99 contour") +handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=mrkconfcont.collections[0].get_edgecolor()[0])) +labels.append("Center CONF99 contour") +handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=mrkconfcentcont.collections[0].get_edgecolor()[0])) +axmrk[0].legend(handles=handles, labels=labels) + +axmrk[1].set(xlabel="RA", ylabel="DEC", title="Location of the nucleus confidence map") +mrkcent = axmrk[1].imshow(MRK463Ecentconf, vmin=0.0, cmap="inferno") +mrkcentcont = axmrk[1].contour(MRK463Ecentconf, 1.-levelsconf, colors="grey") +mrkcentcenter = axmrk[1].plot(*np.unravel_index(np.argmax(MRK463Ecentconf), MRK463Ecentconf.shape)[::-1], "k+", label="Best confidence for center") +handles, labels = axmrk[1].get_legend_handles_labels() +labels.append("CONF99 contour") +handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=mrkcentcont.collections[0].get_edgecolor()[0])) +axmrk[1].legend(handles=handles, labels=labels) + +figmrk.savefig("MRK463E_center.pdf",dpi=150,facecolor="None") +plt.show() From 10577352d4a47a1de7eaee304da0c6f6203bf071 Mon Sep 17 00:00:00 2001 From: Thibault Barnouin Date: Fri, 13 Sep 2024 16:42:06 +0200 Subject: [PATCH 06/18] bit of doctring and fix on test_center --- package/lib/utils.py | 79 ++++++++++++++++++++++++++++++++++++++++-- package/test_center.py | 40 +++++++++++++-------- 2 files changed, 101 insertions(+), 18 deletions(-) diff --git a/package/lib/utils.py b/package/lib/utils.py index e28bbff..7d38335 100755 --- a/package/lib/utils.py +++ b/package/lib/utils.py @@ -4,6 +4,14 @@ import numpy as np def rot2D(ang): """ Return the 2D rotation matrix of given angle in degrees + ---------- + Inputs: + ang : float + Angle in degrees + ---------- + Returns: + rot_mat : numpy.ndarray + 2D matrix of shape (2,2) to perform vector rotation at angle "ang". """ alpha = np.pi * ang / 180 return np.array([[np.cos(alpha), np.sin(alpha)], [-np.sin(alpha), np.cos(alpha)]]) @@ -13,6 +21,14 @@ def princ_angle(ang): """ Return the principal angle in the 0° to 180° quadrant as PA is always defined at p/m 180°. + ---------- + Inputs: + ang : float, numpy.ndarray + Angle in degrees. Can be an array of angles. + ---------- + Returns: + princ_ang : float, numpy.ndarray + Principal angle in the 0°-180° quadrant in the same shape as input. """ if not isinstance(ang, np.ndarray): A = np.array([ang]) @@ -32,6 +48,21 @@ def PCconf(QN, UN, QN_ERR, UN_ERR): """ Compute the confidence level for 2 parameters polarisation degree and polarisation angle from the PCUBE analysis. + ---------- + Inputs: + QN : float, numpy.ndarray + Normalized Q Stokes flux. + UN : float, numpy.ndarray + Normalized U Stokes flux. + QN_ERR : float, numpy.ndarray + Normalized error on Q Stokes flux. + UN_ERR : float, numpy.ndarray + Normalized error on U Stokes flux. + ---------- + Returns: + conf : numpy.ndarray + 2D matrix of same shape as input containing the confidence on the polarization + computation between 0 and 1 for 2 parameters of interest (Q and U Stokes fluxes). """ mask = np.logical_and(QN_ERR > 0.0, UN_ERR > 0.0) conf = np.full(QN.shape, -1.0) @@ -43,6 +74,19 @@ def PCconf(QN, UN, QN_ERR, UN_ERR): def CenterConf(mask, PA, sPA): """ Compute the confidence map for the position of the center of emission. + ---------- + Inputs: + mask : bool, numpy.ndarray + Mask of the polarization vectors from which the center of emission should be drawn. + PA : float, numpy.ndarray + 2D matrix containing the computed polarization angle. + sPA : float, numpy.ndarray + 2D matrix containing the total uncertainties on the polarization angle. + ---------- + Returns: + conf : numpy.ndarray + 2D matrix of same shape as input containing the confidence on the polarization + computation between 0 and 1 for 2 parameters of interest (Q and U Stokes fluxes). """ chi2 = np.full(PA.shape, np.nan) conf = np.full(PA.shape, -1.0) @@ -64,17 +108,36 @@ def CenterConf(mask, PA, sPA): from scipy.special import gammainc conf[np.isfinite(PA)] = 1.0 - gammainc(0.5, 0.5 * chi2[np.isfinite(PA)]) - result = minimize(chisq, np.array(PA.shape) / 2.0, bounds=[(0, PA.shape[1]), (0.0, PA.shape[0])]) + c0 = np.unravel_index(np.argmax(conf), conf.shape)[::-1] + result = minimize(chisq, c0, bounds=[(0, PA.shape[1]), (0.0, PA.shape[0])]) if result.success: print("Center of emission found") else: - print("Center of emission not found") + print("Center of emission not found", result) return conf, result.x def sci_not(v, err, rnd=1, out=str): """ - Return the scientifque error notation as a string. + Return the scientific error notation as a string. + ---------- + Inputs: + v : float + Value to be transformed into scientific notation. + err : float + Error on the value to be transformed into scientific notation. + rnd : int + Number of significant numbers for the scientific notation. + Default to 1. + out : str or other + Format in which the notation should be returned. "str" means the notation + is returned as a single string, "other" means it is returned as a list of "str". + Default to str. + ---------- + Returns: + conf : numpy.ndarray + 2D matrix of same shape as input containing the confidence on the polarization + computation between 0 and 1 for 2 parameters of interest (Q and U Stokes fluxes). """ power = -int(("%E" % v)[-3:]) + 1 output = [r"({0}".format(round(v * 10**power, rnd)), round(v * 10**power, rnd)] @@ -95,6 +158,16 @@ def wcs_PA(PC21, PC22): """ Return the position angle in degrees to the North direction of a wcs from the values of coefficient of its transformation matrix. + ---------- + Inputs: + PC21 : float + Value of the WCS matric PC[1,0] + PC22 : float + Value of the WCS matric PC[1,1] + ---------- + Returns: + orient : float + Angle in degrees between the North direction and the Up direction of the WCS. """ if (abs(PC21) > abs(PC22)) and (PC21 >= 0): orient = -np.arccos(PC22) * 180.0 / np.pi diff --git a/package/test_center.py b/package/test_center.py index 54c21d4..bedfda8 100644 --- a/package/test_center.py +++ b/package/test_center.py @@ -23,15 +23,20 @@ NGC1068snr[NGC1068["POL_DEG_ERR"].data > 0.0] = ( ) NGC1068centconf, NGC1068center = CenterConf(NGC1068conf > 0.99, NGC1068["POL_ANG"].data, NGC1068["POL_ANG_ERR"].data) +NGC1068pos = WCS(NGC1068[0].header).pixel_to_world(*NGC1068center) -figngc, axngc = plt.subplots(1, 2, layout="tight", figsize=(18,9), subplot_kw=dict(projection=WCS(NGC1068[0].header))) +figngc, axngc = plt.subplots(1, 2, layout="tight", figsize=(18, 9), subplot_kw=dict(projection=WCS(NGC1068[0].header)), sharex=True, sharey=True) axngc[0].set(xlabel="RA", ylabel="DEC", title="NGC1069 intensity map with SNR and confidence contours") -imngc = axngc[0].imshow(NGC1068["I_STOKES"].data * NGC1068["I_STOKES"].header["PHOTFLAM"], norm=LogNorm(), cmap="inferno") +vmin, vmax = ( + 0.5 * np.median(NGC1068["I_STOKES"].data[NGC1068mask]) * NGC1068[0].header["PHOTFLAM"], + np.max(NGC1068["I_STOKES"].data[NGC1068mask]) * NGC1068[0].header["PHOTFLAM"], +) +imngc = axngc[0].imshow(NGC1068["I_STOKES"].data * NGC1068["I_STOKES"].header["PHOTFLAM"], norm=LogNorm(vmin, vmax), cmap="inferno") ngcsnrcont = axngc[0].contour(NGC1068snr, levelssnr, colors="b") ngcconfcont = axngc[0].contour(NGC1068conf, levelsconf, colors="r") -ngcconfcenter = axngc[0].plot(*np.unravel_index(np.argmax(NGC1068centconf), NGC1068centconf.shape)[::-1], "k+", label="Best confidence for center") -ngcconfcentcont = axngc[0].contour(NGC1068centconf, 1.-levelsconf, colors="k") +ngcconfcenter = axngc[0].plot(*NGC1068center, marker="+",color="gray", label="Best confidence for center: {0}".format(NGC1068pos.to_string('hmsdms'))) +ngcconfcentcont = axngc[0].contour(NGC1068centconf, [0.01], colors="gray") handles, labels = axngc[0].get_legend_handles_labels() labels.append("SNR contours") handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=ngcsnrcont.collections[0].get_edgecolor()[0])) @@ -43,14 +48,14 @@ axngc[0].legend(handles=handles, labels=labels) axngc[1].set(xlabel="RA", ylabel="DEC", title="Location of the nucleus confidence map") ngccent = axngc[1].imshow(NGC1068centconf, vmin=0.0, cmap="inferno") -ngccentcont = axngc[1].contour(NGC1068centconf, 1.-levelsconf, colors="grey") -ngccentcenter = axngc[1].plot(*np.unravel_index(np.argmax(NGC1068centconf), NGC1068centconf.shape)[::-1], "k+", label="Best confidence for center") +ngccentcont = axngc[1].contour(NGC1068centconf, [0.01], colors="gray") +ngccentcenter = axngc[1].plot(*NGC1068center, marker="+",color="gray", label="Best confidence for center: {0}".format(NGC1068pos.to_string('hmsdms'))) handles, labels = axngc[1].get_legend_handles_labels() labels.append("CONF99 contour") handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=ngccentcont.collections[0].get_edgecolor()[0])) axngc[1].legend(handles=handles, labels=labels) -figngc.savefig("NGC1068_center.pdf",dpi=150,facecolor="None") +figngc.savefig("NGC1068_center.pdf", dpi=150, facecolor="None") ################################################################################################### @@ -68,16 +73,21 @@ MRK463Esnr[MRK463E["POL_DEG_ERR"].data > 0.0] = ( ) MRK463Ecentconf, MRK463Ecenter = CenterConf(MRK463Econf > 0.99, MRK463E["POL_ANG"].data, MRK463E["POL_ANG_ERR"].data) +MRK463Epos = WCS(MRK463E[0].header).pixel_to_world(*MRK463Ecenter) -figmrk, axmrk = plt.subplots(1, 2, layout="tight", figsize=(18,9), subplot_kw=dict(projection=WCS(MRK463E[0].header))) +figmrk, axmrk = plt.subplots(1, 2, layout="tight", figsize=(18, 9), subplot_kw=dict(projection=WCS(MRK463E[0].header)), sharex=True, sharey=True) axmrk[0].set(xlabel="RA", ylabel="DEC", title="NGC1069 intensity map with SNR and confidence contours") -immrk = axmrk[0].imshow(MRK463E["I_STOKES"].data * MRK463E["I_STOKES"].header["PHOTFLAM"], norm=LogNorm(), cmap="inferno") +vmin, vmax = ( + 0.5 * np.median(MRK463E["I_STOKES"].data[MRK463Emask]) * MRK463E[0].header["PHOTFLAM"], + np.max(MRK463E["I_STOKES"].data[MRK463Emask]) * MRK463E[0].header["PHOTFLAM"], +) +immrk = axmrk[0].imshow(MRK463E["I_STOKES"].data * MRK463E["I_STOKES"].header["PHOTFLAM"], norm=LogNorm(vmin, vmax), cmap="inferno") mrksnrcont = axmrk[0].contour(MRK463Esnr, levelssnr, colors="b") mrkconfcont = axmrk[0].contour(MRK463Econf, levelsconf, colors="r") -mrkconfcenter = axmrk[0].plot(*np.unravel_index(np.argmax(MRK463Ecentconf), MRK463Ecentconf.shape)[::-1], "k+", label="Best confidence for center") -mrkconfcentcont = axmrk[0].contour(MRK463Ecentconf, 1.-levelsconf, colors="k") -handles, labels = axmrk[1].get_legend_handles_labels() +mrkconfcenter = axmrk[0].plot(*MRK463Ecenter, marker="+",color="gray", label="Best confidence for center: {0}".format(MRK463Epos.to_string('hmsdms'))) +mrkconfcentcont = axmrk[0].contour(MRK463Ecentconf, [0.01], colors="gray") +handles, labels = axmrk[0].get_legend_handles_labels() labels.append("SNR contours") handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=mrksnrcont.collections[0].get_edgecolor()[0])) labels.append("CONF99 contour") @@ -88,12 +98,12 @@ axmrk[0].legend(handles=handles, labels=labels) axmrk[1].set(xlabel="RA", ylabel="DEC", title="Location of the nucleus confidence map") mrkcent = axmrk[1].imshow(MRK463Ecentconf, vmin=0.0, cmap="inferno") -mrkcentcont = axmrk[1].contour(MRK463Ecentconf, 1.-levelsconf, colors="grey") -mrkcentcenter = axmrk[1].plot(*np.unravel_index(np.argmax(MRK463Ecentconf), MRK463Ecentconf.shape)[::-1], "k+", label="Best confidence for center") +mrkcentcont = axmrk[1].contour(MRK463Ecentconf, [0.01], colors="gray") +mrkcentcenter = axmrk[1].plot(*MRK463Ecenter, marker="+",color="gray", label="Best confidence for center: {0}".format(MRK463Epos.to_string('hmsdms'))) handles, labels = axmrk[1].get_legend_handles_labels() labels.append("CONF99 contour") handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=mrkcentcont.collections[0].get_edgecolor()[0])) axmrk[1].legend(handles=handles, labels=labels) -figmrk.savefig("MRK463E_center.pdf",dpi=150,facecolor="None") +figmrk.savefig("MRK463E_center.pdf", dpi=150, facecolor="None") plt.show() From db3deac6c268ef2974e2ae8ad45531f380cee328 Mon Sep 17 00:00:00 2001 From: Thibault Barnouin Date: Tue, 17 Sep 2024 21:07:26 +0200 Subject: [PATCH 07/18] fix package calling and clean scripts --- package/FOC_reduction.py | 40 +++- package/__init__.py | 3 +- package/lib/plots.py | 314 +++++++++++++++++--------- package/{ => src}/Combine.py | 5 +- package/src/__init__.py | 0 package/src/analysis.py | 40 ---- package/src/comparison_Kishimoto.py | 214 ------------------ package/src/emission_center.py | 77 +++++++ package/src/get_cdelt.py | 5 + package/{ => src}/overplot_IC5063.py | 22 +- package/{ => src}/overplot_MRK463E.py | 12 +- package/test_center.py | 109 --------- 12 files changed, 345 insertions(+), 496 deletions(-) rename package/{ => src}/Combine.py (98%) delete mode 100644 package/src/__init__.py delete mode 100755 package/src/analysis.py delete mode 100755 package/src/comparison_Kishimoto.py create mode 100755 package/src/emission_center.py rename package/{ => src}/overplot_IC5063.py (66%) rename package/{ => src}/overplot_MRK463E.py (66%) delete mode 100644 package/test_center.py diff --git a/package/FOC_reduction.py b/package/FOC_reduction.py index 04345f3..58d73c2 100755 --- a/package/FOC_reduction.py +++ b/package/FOC_reduction.py @@ -3,6 +3,10 @@ """ Main script where are progressively added the steps for the FOC pipeline reduction. """ +from pathlib import Path +from sys import path as syspath + +syspath.append(str(Path(__file__).parent.parent)) # Project libraries from copy import deepcopy @@ -61,7 +65,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= rotate_North = True # Polarization map output - SNRp_cut = 3.0 # P measurments with SNR>3 + P_cut = 0.99 # if >=1.0 cut on the signal-to-noise else cut on the confidence level in Q, U SNRi_cut = 1.0 # I measurments with SNR>30, which implies an uncertainty in P of 4.7%. flux_lim = None # lowest and highest flux displayed on plot, defaults to bkg and maximum in cut if None scale_vec = 3 @@ -292,7 +296,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= proj_plots.polarization_map( deepcopy(Stokes_hdul), data_mask, - SNRp_cut=SNRp_cut, + P_cut=P_cut, SNRi_cut=SNRi_cut, flux_lim=flux_lim, step_vec=step_vec, @@ -303,7 +307,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= proj_plots.polarization_map( deepcopy(Stokes_hdul), data_mask, - SNRp_cut=SNRp_cut, + P_cut=P_cut, SNRi_cut=SNRi_cut, flux_lim=flux_lim, step_vec=step_vec, @@ -315,7 +319,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= proj_plots.polarization_map( deepcopy(Stokes_hdul), data_mask, - SNRp_cut=SNRp_cut, + P_cut=P_cut, SNRi_cut=SNRi_cut, flux_lim=flux_lim, step_vec=step_vec, @@ -327,7 +331,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= proj_plots.polarization_map( deepcopy(Stokes_hdul), data_mask, - SNRp_cut=SNRp_cut, + P_cut=P_cut, SNRi_cut=SNRi_cut, flux_lim=flux_lim, step_vec=step_vec, @@ -339,7 +343,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= proj_plots.polarization_map( deepcopy(Stokes_hdul), data_mask, - SNRp_cut=SNRp_cut, + P_cut=P_cut, SNRi_cut=SNRi_cut, flux_lim=flux_lim, step_vec=step_vec, @@ -351,7 +355,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= proj_plots.polarization_map( deepcopy(Stokes_hdul), data_mask, - SNRp_cut=SNRp_cut, + P_cut=P_cut, SNRi_cut=SNRi_cut, flux_lim=flux_lim, step_vec=step_vec, @@ -363,7 +367,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= proj_plots.polarization_map( deepcopy(Stokes_hdul), data_mask, - SNRp_cut=SNRp_cut, + P_cut=P_cut, SNRi_cut=SNRi_cut, flux_lim=flux_lim, step_vec=step_vec, @@ -375,7 +379,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= proj_plots.polarization_map( deepcopy(Stokes_hdul), data_mask, - SNRp_cut=SNRp_cut, + P_cut=P_cut, SNRi_cut=SNRi_cut, flux_lim=flux_lim, step_vec=step_vec, @@ -387,7 +391,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= proj_plots.polarization_map( deepcopy(Stokes_hdul), data_mask, - SNRp_cut=SNRp_cut, + P_cut=P_cut if P_cut >= 1. else 3., SNRi_cut=SNRi_cut, flux_lim=flux_lim, step_vec=step_vec, @@ -396,12 +400,24 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= plots_folder=plots_folder, display="SNRp", ) + proj_plots.polarization_map( + deepcopy(Stokes_hdul), + data_mask, + P_cut=P_cut if P_cut < 1. else 0.99, + SNRi_cut=SNRi_cut, + flux_lim=flux_lim, + step_vec=step_vec, + scale_vec=scale_vec, + savename="_".join([figname, "confP"]), + plots_folder=plots_folder, + display="confp", + ) elif not interactive: proj_plots.polarization_map( - deepcopy(Stokes_hdul), data_mask, SNRp_cut=SNRp_cut, SNRi_cut=SNRi_cut, savename=figname, plots_folder=plots_folder, display="integrate" + deepcopy(Stokes_hdul), data_mask, P_cut=P_cut, SNRi_cut=SNRi_cut, savename=figname, plots_folder=plots_folder, display="integrate" ) elif pxscale.lower() not in ["full", "integrate"]: - proj_plots.pol_map(Stokes_hdul, SNRp_cut=SNRp_cut, SNRi_cut=SNRi_cut, step_vec=step_vec, scale_vec=scale_vec, flux_lim=flux_lim) + proj_plots.pol_map(Stokes_hdul, P_cut=P_cut, SNRi_cut=SNRi_cut, step_vec=step_vec, scale_vec=scale_vec, flux_lim=flux_lim) return outfiles diff --git a/package/__init__.py b/package/__init__.py index 094aa13..a8ca1bd 100644 --- a/package/__init__.py +++ b/package/__init__.py @@ -1,3 +1,2 @@ -from . import lib -from . import src +from .lib import * from . import FOC_reduction diff --git a/package/lib/plots.py b/package/lib/plots.py index 3a694c6..df6354f 100755 --- a/package/lib/plots.py +++ b/package/lib/plots.py @@ -9,7 +9,7 @@ prototypes : - plot_Stokes(Stokes, savename, plots_folder) Plot the I/Q/U maps from the Stokes HDUList. - - polarization_map(Stokes, data_mask, rectangle, SNRp_cut, SNRi_cut, step_vec, savename, plots_folder, display) -> fig, ax + - polarization_map(Stokes, data_mask, rectangle, P_cut, SNRi_cut, step_vec, savename, plots_folder, display) -> fig, ax Plots polarization map of polarimetric parameters saved in an HDUList. class align_maps(map, other_map, **kwargs) @@ -36,7 +36,7 @@ prototypes : class aperture(img, cdelt, radius, fig, ax) Class to interactively simulate aperture integration. - class pol_map(Stokes, SNRp_cut, SNRi_cut, selection) + class pol_map(Stokes, P_cut, SNRi_cut, selection) Class to interactively study polarization maps making use of the cropping and selecting tools. """ @@ -60,10 +60,7 @@ from mpl_toolkits.axes_grid1.anchored_artists import ( ) from scipy.ndimage import zoom as sc_zoom -try: - from .utils import PCconf, princ_angle, rot2D, sci_not -except ImportError: - from utils import PCconf, princ_angle, rot2D, sci_not +from .utils import PCconf, princ_angle, rot2D, sci_not def plot_obs(data_array, headers, rectangle=None, savename=None, plots_folder="", **kwargs): @@ -216,11 +213,11 @@ def polarization_map( Stokes, data_mask=None, rectangle=None, - SNRp_cut=3.0, - SNRi_cut=3.0, + P_cut=0.99, + SNRi_cut=1.0, flux_lim=None, step_vec=1, - scale_vec=2.0, + scale_vec=3.0, savename=None, plots_folder="", display="default", @@ -236,9 +233,9 @@ def polarization_map( Array of parameters for matplotlib.patches.Rectangle objects that will be displayed on each output image. If None, no rectangle displayed. Defaults to None. - SNRp_cut : float, optional + P_cut : float, optional Cut that should be applied to the signal-to-noise ratio on P. - Any SNR < SNRp_cut won't be displayed. + Any SNR < P_cut won't be displayed. Defaults to 3. SNRi_cut : float, optional Cut that should be applied to the signal-to-noise ratio on I. @@ -276,15 +273,24 @@ def polarization_map( """ # Get data stkI = Stokes["I_stokes"].data.copy() + stkQ = Stokes["Q_stokes"].data.copy() + stkU = Stokes["U_stokes"].data.copy() stk_cov = Stokes["IQU_cov_matrix"].data.copy() pol = Stokes["Pol_deg_debiased"].data.copy() pol_err = Stokes["Pol_deg_err"].data.copy() pang = Stokes["Pol_ang"].data.copy() - try: - if data_mask is None: + if data_mask is None: + try: data_mask = Stokes["Data_mask"].data.astype(bool).copy() - except KeyError: - data_mask = np.ones(stkI.shape).astype(bool) + except KeyError: + data_mask = np.zeros(stkI.shape).astype(bool) + data_mask[stkI > 0.0] = True + + # Compute confidence level map + QN, UN, QN_ERR, UN_ERR = np.full((4, stkI.shape[0], stkI.shape[1]), np.nan) + for nflux, sflux in zip([QN, UN, QN_ERR, UN_ERR], [stkQ, stkU, np.sqrt(stk_cov[1, 1]), np.sqrt(stk_cov[2, 2])]): + nflux[stkI > 0.0] = sflux[stkI > 0.0] / stkI[stkI > 0.0] + confP = PCconf(QN, UN, QN_ERR, UN_ERR) for dataset in [stkI, pol, pol_err, pang]: dataset[np.logical_not(data_mask)] = np.nan @@ -302,15 +308,23 @@ def polarization_map( # Compute SNR and apply cuts poldata, pangdata = pol.copy(), pang.copy() - maskP = pol_err > 0 - SNRp = np.ones(pol.shape) * np.nan - SNRp[maskP] = pol[maskP] / pol_err[maskP] + SNRi = np.full(stkI.shape, np.nan) + SNRi[stk_cov[0, 0] > 0.0] = stkI[stk_cov[0, 0] > 0.0] / np.sqrt(stk_cov[0, 0][stk_cov[0, 0] > 0.0]) + maskI = np.zeros(stkI.shape, dtype=bool) + maskI[stk_cov[0, 0] > 0.0] = SNRi[stk_cov[0, 0] > 0.0] > SNRi_cut - maskI = stk_cov[0, 0] > 0 - SNRi = np.ones(stkI.shape) * np.nan - SNRi[maskI] = stkI[maskI] / np.sqrt(stk_cov[0, 0][maskI]) + SNRp = np.full(pol.shape, np.nan) + SNRp[pol_err > 0.0] = pol[pol_err > 0.0] / pol_err[pol_err > 0.0] + maskP = np.zeros(pol.shape, dtype=bool) - mask = (SNRp > SNRp_cut) * (SNRi > SNRi_cut) + if P_cut >= 1.0: + # MaskP on the signal-to-noise value + maskP[pol_err > 0.0] = SNRp[pol_err > 0.0] > P_cut + else: + # MaskP on the confidence value + maskP = confP > P_cut + + mask = np.logical_and(maskI, maskP) poldata[np.logical_not(mask)] = np.nan pangdata[np.logical_not(mask)] = np.nan @@ -381,8 +395,8 @@ def polarization_map( elif display.lower() in ["s_p", "pol_err", "pol_deg_err"]: # Display polarization degree error map display = "s_p" - if (SNRp > SNRp_cut).any(): - vmin, vmax = 0.0, np.max([pol_err[SNRp > SNRp_cut].max(), 1.0]) * 100.0 + if (SNRp > P_cut).any(): + vmin, vmax = 0.0, np.max([pol_err[SNRp > P_cut].max(), 1.0]) * 100.0 im = ax.imshow(pol_err * 100.0, vmin=vmin, vmax=vmax, aspect="equal", cmap="inferno_r", alpha=1.0) else: vmin, vmax = 0.0, 100.0 @@ -400,30 +414,39 @@ def polarization_map( else: im = ax.imshow(np.sqrt(stk_cov[0, 0]) * convert_flux, aspect="equal", cmap="inferno", alpha=1.0) fig.colorbar(im, ax=ax, aspect=50, shrink=0.75, pad=0.025, label=r"$\sigma_I$ [$ergs \cdot cm^{-2} \cdot s^{-1} \cdot \AA^{-1}$]") - elif display.lower() in ["snr", "snri"]: + elif display.lower() in ["snri"]: # Display I_stokes signal-to-noise map display = "snri" vmin, vmax = 0.0, np.max(SNRi[np.isfinite(SNRi)]) if vmax * 0.99 > SNRi_cut: im = ax.imshow(SNRi, vmin=vmin, vmax=vmax, aspect="equal", cmap="inferno", alpha=1.0) - levelsSNRi = np.linspace(SNRi_cut, vmax * 0.99, 5) + levelsSNRi = np.linspace(SNRi_cut, vmax * 0.99, 5).astype(int) print("SNRi contour levels : ", levelsSNRi) ax.contour(SNRi, levels=levelsSNRi, colors="grey", linewidths=0.5) else: im = ax.imshow(SNRi, aspect="equal", cmap="inferno", alpha=1.0) fig.colorbar(im, ax=ax, aspect=50, shrink=0.75, pad=0.025, label=r"$I_{Stokes}/\sigma_{I}$") - elif display.lower() in ["snrp"]: + elif display.lower() in ["snr", "snrp"]: # Display polarization degree signal-to-noise map display = "snrp" vmin, vmax = 0.0, np.max(SNRp[np.isfinite(SNRp)]) - if vmax * 0.99 > SNRp_cut: + if vmax * 0.99 > P_cut: im = ax.imshow(SNRp, vmin=vmin, vmax=vmax, aspect="equal", cmap="inferno", alpha=1.0) - levelsSNRp = np.linspace(SNRp_cut, vmax * 0.99, 5) + levelsSNRp = np.linspace(P_cut, vmax * 0.99, 5).astype(int) print("SNRp contour levels : ", levelsSNRp) ax.contour(SNRp, levels=levelsSNRp, colors="grey", linewidths=0.5) else: im = ax.imshow(SNRp, aspect="equal", cmap="inferno", alpha=1.0) fig.colorbar(im, ax=ax, aspect=50, shrink=0.75, pad=0.025, label=r"$P/\sigma_{P}$") + elif display.lower() in ["conf", "confp"]: + # Display polarization degree signal-to-noise map + display = "confp" + vmin, vmax = 0.0, 1.0 + im = ax.imshow(confP, vmin=vmin, vmax=vmax, aspect="equal", cmap="inferno", alpha=1.0) + levelsconfp = np.array([0.500, 0.900, 0.990, 0.999]) + print("confp contour levels : ", levelsconfp) + ax.contour(confP, levels=levelsconfp, colors="grey", linewidths=0.5) + fig.colorbar(im, ax=ax, aspect=50, shrink=0.75, pad=0.025, label=r"$Conf_{P}$") else: # Defaults to intensity map if mask.sum() > 0.0: @@ -463,7 +486,7 @@ def polarization_map( arrow_props={"ec": "k", "fc": "w", "alpha": 1, "lw": 1}, ) - if display.lower() in ["i", "s_i", "snri", "pf", "p", "pa", "s_p", "snrp"]: + if display.lower() in ["i", "s_i", "snri", "pf", "p", "pa", "s_p", "snrp", "confp"]: if step_vec == 0: poldata[np.isfinite(poldata)] = 1.0 / 2.0 step_vec = 1 @@ -536,7 +559,6 @@ def polarization_map( savename += ".pdf" fig.savefig(path_join(plots_folder, savename), bbox_inches="tight", dpi=150, facecolor="None") - plt.show() return fig, ax @@ -765,14 +787,14 @@ class align_maps(object): x = event.xdata y = event.ydata - self.cr_map.set(data=[x, y]) + self.cr_map.set(data=[[x], [y]]) self.fig_align.canvas.draw_idle() if (event.inaxes is not None) and (event.inaxes == self.other_ax): x = event.xdata y = event.ydata - self.cr_other.set(data=[x, y]) + self.cr_other.set(data=[[x], [y]]) self.fig_align.canvas.draw_idle() def reset_align(self, event): @@ -843,16 +865,23 @@ class overplot_radio(align_maps): Inherit from class align_maps in order to get the same WCS on both maps. """ - def overplot(self, levels=None, SNRp_cut=3.0, SNRi_cut=3.0, scale_vec=2, savename=None, **kwargs): + def overplot(self, levels=None, P_cut=0.99, SNRi_cut=1.0, scale_vec=2, savename=None, **kwargs): self.Stokes_UV = self.map self.wcs_UV = self.map_wcs # Get Data obj = self.Stokes_UV[0].header["targname"] stkI = self.Stokes_UV["I_STOKES"].data + stkQ = self.Stokes_UV["Q_STOKES"].data + stkU = self.Stokes_UV["U_STOKES"].data stk_cov = self.Stokes_UV["IQU_COV_MATRIX"].data pol = deepcopy(self.Stokes_UV["POL_DEG_DEBIASED"].data) pol_err = self.Stokes_UV["POL_DEG_ERR"].data pang = self.Stokes_UV["POL_ANG"].data + # Compute confidence level map + QN, UN, QN_ERR, UN_ERR = np.full((4, stkI.shape[0], stkI.shape[1]), np.nan) + for nflux, sflux in zip([QN, UN, QN_ERR, UN_ERR], [stkQ, stkU, np.sqrt(stk_cov[1, 1]), np.sqrt(stk_cov[2, 2])]): + nflux[stkI > 0.0] = sflux[stkI > 0.0] / stkI[stkI > 0.0] + confP = PCconf(QN, UN, QN_ERR, UN_ERR) other_data = self.other_data self.other_convert = 1.0 @@ -864,12 +893,17 @@ class overplot_radio(align_maps): self.map_convert = self.Stokes_UV[0].header["photflam"] # Compute SNR and apply cuts - pol[pol == 0.0] = np.nan - SNRp = pol / pol_err - SNRp[np.isnan(SNRp)] = 0.0 - pol[SNRp < SNRp_cut] = np.nan - SNRi = stkI / np.sqrt(stk_cov[0, 0]) - SNRi[np.isnan(SNRi)] = 0.0 + maskP = np.zeros(pol.shape, dtype=bool) + if P_cut >= 1.0: + SNRp = np.zeros(pol.shape) + SNRp[pol_err > 0.0] = pol[pol_err > 0.0] / pol_err[pol_err > 0.0] + maskP = SNRp > P_cut + else: + maskP = confP > P_cut + pol[np.logical_not(maskP)] = np.nan + + SNRi = np.zeros(stkI.shape) + SNRi[stk_cov[0, 0] > 0.0] = stkI[stk_cov[0, 0] > 0.0] / np.sqrt(stk_cov[0, 0][stk_cov[0, 0] > 0.0]) pol[SNRi < SNRi_cut] = np.nan plt.rcParams.update({"font.size": 16}) @@ -1025,7 +1059,7 @@ class overplot_radio(align_maps): (0, 0), (0, 1), arrowstyle="-", fc="w", ec="k", lw=2 ) labels.append("{0:s} contour".format(self.other_observer)) - handles.append(Rectangle((0, 0), 1, 1, fill=False, lw=2, ec=other_cont.collections[0].get_edgecolor()[0])) + handles.append(Rectangle((0, 0), 1, 1, fill=False, lw=2, ec=other_cont.get_edgecolor()[0])) self.legend = self.ax_overplot.legend( handles=handles, labels=labels, bbox_to_anchor=(0.0, 1.02, 1.0, 0.102), loc="lower left", mode="expand", borderaxespad=0.0 ) @@ -1037,10 +1071,10 @@ class overplot_radio(align_maps): self.fig_overplot.canvas.draw() - def plot(self, levels=None, SNRp_cut=3.0, SNRi_cut=3.0, savename=None, **kwargs) -> None: + def plot(self, levels=None, P_cut=0.99, SNRi_cut=1.0, savename=None, **kwargs) -> None: while not self.aligned: self.align() - self.overplot(levels=levels, SNRp_cut=SNRp_cut, SNRi_cut=SNRi_cut, savename=savename, **kwargs) + self.overplot(levels=levels, P_cut=P_cut, SNRi_cut=SNRi_cut, savename=savename, **kwargs) plt.show(block=True) @@ -1050,16 +1084,23 @@ class overplot_chandra(align_maps): Inherit from class align_maps in order to get the same WCS on both maps. """ - def overplot(self, levels=None, SNRp_cut=3.0, SNRi_cut=3.0, scale_vec=2, zoom=1, savename=None, **kwargs): + def overplot(self, levels=None, P_cut=0.99, SNRi_cut=1.0, scale_vec=2, zoom=1, savename=None, **kwargs): self.Stokes_UV = self.map self.wcs_UV = self.map_wcs # Get Data obj = self.Stokes_UV[0].header["targname"] stkI = self.Stokes_UV["I_STOKES"].data + stkQ = self.Stokes_UV["Q_STOKES"].data + stkU = self.Stokes_UV["U_STOKES"].data stk_cov = self.Stokes_UV["IQU_COV_MATRIX"].data pol = deepcopy(self.Stokes_UV["POL_DEG_DEBIASED"].data) pol_err = self.Stokes_UV["POL_DEG_ERR"].data pang = self.Stokes_UV["POL_ANG"].data + # Compute confidence level map + QN, UN, QN_ERR, UN_ERR = np.full((4, stkI.shape[0], stkI.shape[1]), np.nan) + for nflux, sflux in zip([QN, UN, QN_ERR, UN_ERR], [stkQ, stkU, np.sqrt(stk_cov[1, 1]), np.sqrt(stk_cov[2, 2])]): + nflux[stkI > 0.0] = sflux[stkI > 0.0] / stkI[stkI > 0.0] + confP = PCconf(QN, UN, QN_ERR, UN_ERR) other_data = deepcopy(self.other_data) other_wcs = self.other_wcs.deepcopy() @@ -1070,12 +1111,17 @@ class overplot_chandra(align_maps): self.other_unit = "counts" # Compute SNR and apply cuts - pol[pol == 0.0] = np.nan - SNRp = pol / pol_err - SNRp[np.isnan(SNRp)] = 0.0 - pol[SNRp < SNRp_cut] = np.nan - SNRi = stkI / np.sqrt(stk_cov[0, 0]) - SNRi[np.isnan(SNRi)] = 0.0 + maskP = np.zeros(pol.shape, dtype=bool) + if P_cut >= 1.0: + SNRp = np.zeros(pol.shape) + SNRp[pol_err > 0.0] = pol[pol_err > 0.0] / pol_err[pol_err > 0.0] + maskP = SNRp > P_cut + else: + maskP = confP > P_cut + pol[np.logical_not(maskP)] = np.nan + + SNRi = np.zeros(stkI.shape) + SNRi[stk_cov[0, 0] > 0.0] = stkI[stk_cov[0, 0] > 0.0] / np.sqrt(stk_cov[0, 0][stk_cov[0, 0] > 0.0]) pol[SNRi < SNRi_cut] = np.nan plt.rcParams.update({"font.size": 16}) @@ -1224,7 +1270,7 @@ class overplot_chandra(align_maps): (0, 0), (0, 1), arrowstyle="-", fc="w", ec="k", lw=2 ) labels.append("{0:s} contour in counts".format(self.other_observer)) - handles.append(Rectangle((0, 0), 1, 1, fill=False, lw=2, ec=other_cont.collections[0].get_edgecolor()[0])) + handles.append(Rectangle((0, 0), 1, 1, fill=False, lw=2, ec=other_cont.get_edgecolor()[0])) self.legend = self.ax_overplot.legend( handles=handles, labels=labels, bbox_to_anchor=(0.0, 1.02, 1.0, 0.102), loc="lower left", mode="expand", borderaxespad=0.0 ) @@ -1236,10 +1282,10 @@ class overplot_chandra(align_maps): self.fig_overplot.canvas.draw() - def plot(self, levels=None, SNRp_cut=3.0, SNRi_cut=3.0, zoom=1, savename=None, **kwargs) -> None: + def plot(self, levels=None, P_cut=0.99, SNRi_cut=1.0, zoom=1, savename=None, **kwargs) -> None: while not self.aligned: self.align() - self.overplot(levels=levels, SNRp_cut=SNRp_cut, SNRi_cut=SNRi_cut, zoom=zoom, savename=savename, **kwargs) + self.overplot(levels=levels, P_cut=P_cut, SNRi_cut=SNRi_cut, zoom=zoom, savename=savename, **kwargs) plt.show(block=True) @@ -1249,26 +1295,38 @@ class overplot_pol(align_maps): Inherit from class align_maps in order to get the same WCS on both maps. """ - def overplot(self, levels=None, SNRp_cut=3.0, SNRi_cut=3.0, scale_vec=2.0, savename=None, **kwargs): + def overplot(self, levels=None, P_cut=0.99, SNRi_cut=1.0, scale_vec=2.0, savename=None, **kwargs): self.Stokes_UV = self.map self.wcs_UV = self.map_wcs # Get Data obj = self.Stokes_UV[0].header["targname"] stkI = self.Stokes_UV["I_STOKES"].data + stkQ = self.Stokes_UV["Q_STOKES"].data + stkU = self.Stokes_UV["U_STOKES"].data stk_cov = self.Stokes_UV["IQU_COV_MATRIX"].data pol = deepcopy(self.Stokes_UV["POL_DEG_DEBIASED"].data) pol_err = self.Stokes_UV["POL_DEG_ERR"].data pang = self.Stokes_UV["POL_ANG"].data + # Compute confidence level map + QN, UN, QN_ERR, UN_ERR = np.full((4, stkI.shape[0], stkI.shape[1]), np.nan) + for nflux, sflux in zip([QN, UN, QN_ERR, UN_ERR], [stkQ, stkU, np.sqrt(stk_cov[1, 1]), np.sqrt(stk_cov[2, 2])]): + nflux[stkI > 0.0] = sflux[stkI > 0.0] / stkI[stkI > 0.0] + confP = PCconf(QN, UN, QN_ERR, UN_ERR) other_data = self.other_data # Compute SNR and apply cuts - pol[pol == 0.0] = np.nan - SNRp = pol / pol_err - SNRp[np.isnan(SNRp)] = 0.0 - pol[SNRp < SNRp_cut] = np.nan - SNRi = stkI / np.sqrt(stk_cov[0, 0]) - SNRi[np.isnan(SNRi)] = 0.0 + maskP = np.zeros(pol.shape, dtype=bool) + if P_cut >= 1.0: + SNRp = np.zeros(pol.shape) + SNRp[pol_err > 0.0] = pol[pol_err > 0.0] / pol_err[pol_err > 0.0] + maskP = SNRp > P_cut + else: + maskP = confP > P_cut + pol[np.logical_not(maskP)] = np.nan + + SNRi = np.zeros(stkI.shape) + SNRi[stk_cov[0, 0] > 0.0] = stkI[stk_cov[0, 0] > 0.0] / np.sqrt(stk_cov[0, 0][stk_cov[0, 0] > 0.0]) pol[SNRi < SNRi_cut] = np.nan plt.rcParams.update({"font.size": 16}) @@ -1437,7 +1495,7 @@ class overplot_pol(align_maps): (0, 0), (0, 1), arrowstyle="-", fc="w", ec="k", lw=2 ) labels.append("{0:s} Stokes I contour".format(self.map_observer)) - handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=cont_stkI.collections[0].get_edgecolor()[0])) + handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=cont_stkI.get_edgecolor()[0])) self.legend = self.ax_overplot.legend( handles=handles, labels=labels, bbox_to_anchor=(0.0, 1.02, 1.0, 0.102), loc="lower left", mode="expand", borderaxespad=0.0 ) @@ -1449,10 +1507,10 @@ class overplot_pol(align_maps): self.fig_overplot.canvas.draw() - def plot(self, levels=None, SNRp_cut=3.0, SNRi_cut=3.0, scale_vec=2.0, savename=None, **kwargs) -> None: + def plot(self, levels=None, P_cut=0.99, SNRi_cut=1.0, scale_vec=2.0, savename=None, **kwargs) -> None: while not self.aligned: self.align() - self.overplot(levels=levels, SNRp_cut=SNRp_cut, SNRi_cut=SNRi_cut, scale_vec=scale_vec, savename=savename, **kwargs) + self.overplot(levels=levels, P_cut=P_cut, SNRi_cut=SNRi_cut, scale_vec=scale_vec, savename=savename, **kwargs) plt.show(block=True) def add_vector(self, position="center", pol_deg=1.0, pol_ang=0.0, **kwargs): @@ -1462,7 +1520,12 @@ class overplot_pol(align_maps): position = self.other_wcs.world_to_pixel(position) u, v = pol_deg * np.cos(np.radians(pol_ang) + np.pi / 2.0), pol_deg * np.sin(np.radians(pol_ang) + np.pi / 2.0) - for key, value in [["scale", [["scale", self.scale_vec]]], ["width", [["width", 0.1]]], ["color", [["color", "k"]]], ["edgecolor", [["edgecolor", "w"]]]]: + for key, value in [ + ["scale", [["scale", self.scale_vec]]], + ["width", [["width", 0.1]]], + ["color", [["color", "k"]]], + ["edgecolor", [["edgecolor", "w"]]], + ]: try: _ = kwargs[key] except KeyError: @@ -1495,7 +1558,7 @@ class align_pol(object): self.kwargs = kwargs - def single_plot(self, curr_map, wcs, v_lim=None, ax_lim=None, SNRp_cut=3.0, SNRi_cut=3.0, savename=None, **kwargs): + def single_plot(self, curr_map, wcs, v_lim=None, ax_lim=None, P_cut=3.0, SNRi_cut=3.0, savename=None, **kwargs): # Get data stkI = curr_map["I_STOKES"].data stk_cov = curr_map["IQU_COV_MATRIX"].data @@ -1518,7 +1581,7 @@ class align_pol(object): SNRi = np.zeros(stkI.shape) SNRi[maskI] = stkI[maskI] / np.sqrt(stk_cov[0, 0][maskI]) - mask = (SNRp > SNRp_cut) * (SNRi > SNRi_cut) * (pol >= 0.0) + mask = (SNRp > P_cut) * (SNRi > SNRi_cut) * (pol >= 0.0) pol[mask] = np.nan # Plot the map @@ -1627,7 +1690,7 @@ class align_pol(object): self.wcs, self.wcs_other[i] = curr_align.align() self.aligned[i] = curr_align.aligned - def plot(self, SNRp_cut=3.0, SNRi_cut=3.0, savename=None, **kwargs): + def plot(self, P_cut=3.0, SNRi_cut=3.0, savename=None, **kwargs): while not self.aligned.all(): self.align() eps = 1e-35 @@ -1673,13 +1736,13 @@ class align_pol(object): ) v_lim = np.array([vmin, vmax]) - fig, ax = self.single_plot(self.ref_map, self.wcs, v_lim=v_lim, SNRp_cut=SNRp_cut, SNRi_cut=SNRi_cut, savename=savename + "_0", **kwargs) + fig, ax = self.single_plot(self.ref_map, self.wcs, v_lim=v_lim, P_cut=P_cut, SNRi_cut=SNRi_cut, savename=savename + "_0", **kwargs) x_lim, y_lim = ax.get_xlim(), ax.get_ylim() ax_lim = np.array([self.wcs.pixel_to_world(x_lim[i], y_lim[i]) for i in range(len(x_lim))]) for i, curr_map in enumerate(self.other_maps): self.single_plot( - curr_map, self.wcs_other[i], v_lim=v_lim, ax_lim=ax_lim, SNRp_cut=SNRp_cut, SNRi_cut=SNRi_cut, savename=savename + "_" + str(i + 1), **kwargs + curr_map, self.wcs_other[i], v_lim=v_lim, ax_lim=ax_lim, P_cut=P_cut, SNRi_cut=SNRi_cut, savename=savename + "_" + str(i + 1), **kwargs ) @@ -1726,6 +1789,7 @@ class crop_map(object): self.mask_alpha = 0.75 self.rect_selector = RectangleSelector(self.ax, self.onselect_crop, button=[1]) self.embedded = True + self.ax.set(xlabel="Right Ascension (J2000)", ylabel="Declination (J2000)") self.display(self.data, self.wcs, self.map_convert, **self.kwargs) self.extent = np.array([0.0, self.data.shape[0], 0.0, self.data.shape[1]]) @@ -2024,7 +2088,7 @@ class image_lasso_selector(object): self.mask = np.zeros(self.img.shape[:2], dtype=bool) self.mask[self.indices] = True if hasattr(self, "cont"): - for coll in self.cont.collections: + for coll in self.cont: coll.remove() self.cont = self.ax.contour(self.mask.astype(float), levels=[0.5], colors="white", linewidths=1) if not self.embedded: @@ -2137,7 +2201,7 @@ class slit(object): for p in self.pix: self.mask[tuple(p)] = (np.abs(np.dot(rot2D(-self.angle), p - self.rect.get_center()[::-1])) < (self.height / 2.0, self.width / 2.0)).all() if hasattr(self, "cont"): - for coll in self.cont.collections: + for coll in self.cont: try: coll.remove() except AttributeError: @@ -2240,7 +2304,7 @@ class aperture(object): x0, y0 = self.circ.center self.mask = np.sqrt((xx - x0) ** 2 + (yy - y0) ** 2) < self.radius if hasattr(self, "cont"): - for coll in self.cont.collections: + for coll in self.cont: try: coll.remove() except AttributeError: @@ -2258,21 +2322,22 @@ class pol_map(object): Class to interactively study polarization maps. """ - def __init__(self, Stokes, SNRp_cut=3.0, SNRi_cut=3.0, step_vec=1, scale_vec=3.0, flux_lim=None, selection=None, pa_err=False): + def __init__(self, Stokes, P_cut=0.99, SNRi_cut=1.0, step_vec=1, scale_vec=3.0, flux_lim=None, selection=None, pa_err=False): if isinstance(Stokes, str): Stokes = fits.open(Stokes) self.Stokes = deepcopy(Stokes) - self.SNRp_cut = SNRp_cut + self.P_cut = P_cut self.SNRi_cut = SNRi_cut self.flux_lim = flux_lim self.SNRi = deepcopy(self.SNRi_cut) - self.SNRp = deepcopy(self.SNRp_cut) + self.SNRp = deepcopy(self.P_cut) self.region = None self.data = None self.display_selection = selection self.step_vec = step_vec self.scale_vec = scale_vec self.pa_err = pa_err + self.conf = PCconf(self.Q / self.I, self.U / self.I, np.sqrt(self.IQU_cov[1, 1]) / self.I, np.sqrt(self.IQU_cov[2, 2]) / self.I) # Get data self.targ = self.Stokes[0].header["targname"] @@ -2292,18 +2357,22 @@ class pol_map(object): # Display integrated values in ROI self.pol_int() - # Set axes for sliders (SNRp_cut, SNRi_cut) - ax_I_cut = self.fig.add_axes([0.120, 0.080, 0.230, 0.01]) - ax_P_cut = self.fig.add_axes([0.120, 0.055, 0.230, 0.01]) - ax_vec_sc = self.fig.add_axes([0.240, 0.030, 0.110, 0.01]) - ax_snr_reset = self.fig.add_axes([0.080, 0.020, 0.05, 0.02]) + # Set axes for sliders (P_cut, SNRi_cut) + ax_I_cut = self.fig.add_axes([0.120, 0.080, 0.220, 0.01]) + self.ax_P_cut = self.fig.add_axes([0.120, 0.055, 0.220, 0.01]) + ax_vec_sc = self.fig.add_axes([0.260, 0.030, 0.090, 0.01]) + ax_snr_reset = self.fig.add_axes([0.060, 0.020, 0.05, 0.02]) + ax_snr_conf = self.fig.add_axes([0.115, 0.020, 0.05, 0.02]) SNRi_max = np.max(self.I[self.IQU_cov[0, 0] > 0.0] / np.sqrt(self.IQU_cov[0, 0][self.IQU_cov[0, 0] > 0.0])) SNRp_max = np.max(self.P[self.s_P > 0.0] / self.s_P[self.s_P > 0.0]) s_I_cut = Slider(ax_I_cut, r"$SNR^{I}_{cut}$", 1.0, int(SNRi_max * 0.95), valstep=1, valinit=self.SNRi_cut) - s_P_cut = Slider(ax_P_cut, r"$SNR^{P}_{cut}$", 1.0, int(SNRp_max * 0.95), valstep=1, valinit=self.SNRp_cut) - s_vec_sc = Slider(ax_vec_sc, r"Vectors scale", 0.0, 10.0, valstep=1, valinit=self.scale_vec) + self.s_P_cut = Slider(self.ax_P_cut, r"$Conf^{P}_{cut}$", 0.50, 1.0, valstep=[0.500, 0.900, 0.990, 0.999], valinit=self.P_cut if P_cut <= 1.0 else 0.99) + s_vec_sc = Slider(ax_vec_sc, r"Vec scale", 0.0, 10.0, valstep=1, valinit=self.scale_vec) b_snr_reset = Button(ax_snr_reset, "Reset") b_snr_reset.label.set_fontsize(8) + self.snr_conf = 1 + b_snr_conf = Button(ax_snr_conf, "Conf") + b_snr_conf.label.set_fontsize(8) def update_snri(val): self.SNRi = val @@ -2325,13 +2394,34 @@ class pol_map(object): def reset_snr(event): s_I_cut.reset() - s_P_cut.reset() + self.s_P_cut.reset() s_vec_sc.reset() + def toggle_snr_conf(event=None): + self.ax_P_cut.remove() + self.ax_P_cut = self.fig.add_axes([0.120, 0.055, 0.220, 0.01]) + if self.snr_conf: + self.snr_conf = 0 + b_snr_conf.label.set_text("Conf") + self.s_P_cut = Slider(self.ax_P_cut, r"$SNR^{P}_{cut}$", 1.0, int(SNRp_max * 0.95), valstep=1, valinit=self.P_cut if P_cut >= 1.0 else 3) + else: + self.snr_conf = 1 + b_snr_conf.label.set_text("SNR") + self.s_P_cut = Slider( + self.ax_P_cut, r"$Conf^{P}_{cut}$", 0.50, 1.0, valstep=[0.500, 0.900, 0.990, 0.999], valinit=self.P_cut if P_cut <= 1.0 else 0.99 + ) + self.s_P_cut.on_changed(update_snrp) + update_snrp(self.s_P_cut.val) + self.fig.canvas.draw_idle() + s_I_cut.on_changed(update_snri) - s_P_cut.on_changed(update_snrp) + self.s_P_cut.on_changed(update_snrp) s_vec_sc.on_changed(update_vecsc) b_snr_reset.on_clicked(reset_snr) + b_snr_conf.on_clicked(toggle_snr_conf) + + if self.P_cut >= 1.0: + toggle_snr_conf() # Set axe for ROI selection ax_select = self.fig.add_axes([0.375, 0.070, 0.05, 0.02]) @@ -2349,7 +2439,7 @@ class pol_map(object): self.selected = False self.region = deepcopy(self.select_instance.mask.astype(bool)) self.select_instance.displayed.remove() - for coll in self.select_instance.cont.collections: + for coll in self.select_instance.cont: coll.remove() self.select_instance.lasso.set_active(False) self.set_data_mask(deepcopy(self.region)) @@ -2393,7 +2483,7 @@ class pol_map(object): self.select_instance.update_mask() self.region = deepcopy(self.select_instance.mask.astype(bool)) self.select_instance.displayed.remove() - for coll in self.select_instance.cont.collections[:]: + for coll in self.select_instance.cont: coll.remove() self.select_instance.circ.set_visible(False) self.set_data_mask(deepcopy(self.region)) @@ -2451,7 +2541,7 @@ class pol_map(object): self.select_instance.update_mask() self.region = deepcopy(self.select_instance.mask.astype(bool)) self.select_instance.displayed.remove() - for coll in self.select_instance.cont.collections[:]: + for coll in self.select_instance.cont: coll.remove() self.select_instance.rect.set_visible(False) self.set_data_mask(deepcopy(self.region)) @@ -2768,8 +2858,11 @@ class pol_map(object): def cut(self): s_I = np.sqrt(self.IQU_cov[0, 0]) SNRp_mask, SNRi_mask = np.zeros(self.P.shape).astype(bool), np.zeros(self.I.shape).astype(bool) - SNRp_mask[self.s_P > 0.0] = self.P[self.s_P > 0.0] / self.s_P[self.s_P > 0.0] > self.SNRp SNRi_mask[s_I > 0.0] = self.I[s_I > 0.0] / s_I[s_I > 0.0] > self.SNRi + if self.SNRp >= 1.0: + SNRp_mask[self.s_P > 0.0] = self.P[self.s_P > 0.0] / self.s_P[self.s_P > 0.0] > self.SNRp + else: + SNRp_mask = self.conf > self.SNRp return np.logical_and(SNRi_mask, SNRp_mask) def ax_cosmetics(self, ax=None): @@ -3171,7 +3264,7 @@ class pol_map(object): ) if hasattr(self, "cont"): - for coll in self.cont.collections: + for coll in self.cont: try: coll.remove() except AttributeError: @@ -3242,15 +3335,13 @@ if __name__ == "__main__": parser = argparse.ArgumentParser(description="Interactively plot the pipeline products") parser.add_argument("-f", "--file", metavar="path", required=False, help="The full or relative path to the data product", type=str, default=None) - parser.add_argument( - "-p", "--snrp", metavar="snrp_cut", required=False, help="The cut in signal-to-noise for the polarization degree", type=float, default=3.0 - ) + parser.add_argument("-p", "--pcut", metavar="p_cut", required=False, help="The cut in signal-to-noise for the polarization degree", type=float, default=3.0) parser.add_argument("-i", "--snri", metavar="snri_cut", required=False, help="The cut in signal-to-noise for the intensity", type=float, default=3.0) parser.add_argument( "-st", "--step-vec", metavar="step_vec", required=False, help="Quantity of vectors to be shown, 1 is all, 2 is every other, etc.", type=int, default=1 ) parser.add_argument( - "-sc", "--scale-vec", metavar="scale_vec", required=False, help="Size of the 100% polarization vector in pixel units", type=float, default=3.0 + "-sc", "--scale-vec", metavar="scale_vec", required=False, help="Size of the 100%% polarization vector in pixel units", type=float, default=3.0 ) parser.add_argument("-pa", "--pang-err", action="store_true", required=False, help="Whether the polarization angle uncertainties should be displayed") parser.add_argument("-l", "--lim", metavar="flux_lim", nargs=2, required=False, help="Limits for the intensity map", type=float, default=None) @@ -3265,7 +3356,7 @@ if __name__ == "__main__": polarization_map( Stokes_UV, Stokes_UV["DATA_MASK"].data.astype(bool), - SNRp_cut=args.snrp, + P_cut=args.p_cut, SNRi_cut=args.snri, flux_lim=args.lim, step_vec=args.step_vec, @@ -3276,7 +3367,7 @@ if __name__ == "__main__": polarization_map( Stokes_UV, Stokes_UV["DATA_MASK"].data.astype(bool), - SNRp_cut=args.snrp, + P_cut=args.p_cut, SNRi_cut=args.snri, flux_lim=args.lim, step_vec=args.step_vec, @@ -3288,7 +3379,7 @@ if __name__ == "__main__": polarization_map( Stokes_UV, Stokes_UV["DATA_MASK"].data.astype(bool), - SNRp_cut=args.snrp, + P_cut=args.p_cut, SNRi_cut=args.snri, flux_lim=args.lim, step_vec=args.step_vec, @@ -3300,7 +3391,7 @@ if __name__ == "__main__": polarization_map( Stokes_UV, Stokes_UV["DATA_MASK"].data.astype(bool), - SNRp_cut=args.snrp, + P_cut=args.p_cut, SNRi_cut=args.snri, flux_lim=args.lim, step_vec=args.step_vec, @@ -3312,7 +3403,7 @@ if __name__ == "__main__": polarization_map( Stokes_UV, Stokes_UV["DATA_MASK"].data.astype(bool), - SNRp_cut=args.snrp, + P_cut=args.p_cut, SNRi_cut=args.snri, flux_lim=args.lim, step_vec=args.step_vec, @@ -3324,7 +3415,7 @@ if __name__ == "__main__": polarization_map( Stokes_UV, Stokes_UV["DATA_MASK"].data.astype(bool), - SNRp_cut=args.snrp, + P_cut=args.p_cut, SNRi_cut=args.snri, flux_lim=args.lim, step_vec=args.step_vec, @@ -3336,7 +3427,7 @@ if __name__ == "__main__": polarization_map( Stokes_UV, Stokes_UV["DATA_MASK"].data.astype(bool), - SNRp_cut=args.snrp, + P_cut=args.p_cut, SNRi_cut=args.snri, flux_lim=args.lim, step_vec=args.step_vec, @@ -3348,7 +3439,7 @@ if __name__ == "__main__": polarization_map( Stokes_UV, Stokes_UV["DATA_MASK"].data.astype(bool), - SNRp_cut=args.snrp, + P_cut=args.p_cut, SNRi_cut=args.snri, flux_lim=args.lim, step_vec=args.step_vec, @@ -3360,7 +3451,7 @@ if __name__ == "__main__": polarization_map( Stokes_UV, Stokes_UV["DATA_MASK"].data.astype(bool), - SNRp_cut=args.snrp, + P_cut=args.p_cut if args.p_cut >= 1.0 else 3.0, SNRi_cut=args.snri, flux_lim=args.lim, step_vec=args.step_vec, @@ -3369,12 +3460,21 @@ if __name__ == "__main__": plots_folder=args.static_pdf, display="SNRp", ) - else: - pol_map( - Stokes_UV, SNRp_cut=args.snrp, SNRi_cut=args.snri, step_vec=args.step_vec, scale_vec=args.scale_vec, flux_lim=args.lim, pa_err=args.pang_err + polarization_map( + Stokes_UV, + Stokes_UV["DATA_MASK"].data.astype(bool), + P_cut=args.p_cut if args.p_cut < 1.0 else 0.99, + SNRi_cut=args.snri, + flux_lim=args.lim, + step_vec=args.step_vec, + scale_vec=args.scale_vec, + savename="_".join([Stokes_UV[0].header["FILENAME"], "confP"]), + plots_folder=args.static_pdf, + display="confp", ) - + else: + pol_map(Stokes_UV, P_cut=args.p_cut, SNRi_cut=args.snri, step_vec=args.step_vec, scale_vec=args.scale_vec, flux_lim=args.lim, pa_err=args.pang_err) else: print( - "python3 plots.py -f -p -i -st -sc -l -pa --pdf " + "python3 plots.py -f -p -i -st -sc -l -pa --pdf " ) diff --git a/package/Combine.py b/package/src/Combine.py similarity index 98% rename from package/Combine.py rename to package/src/Combine.py index b3871f1..87b9632 100755 --- a/package/Combine.py +++ b/package/src/Combine.py @@ -1,6 +1,9 @@ #!/usr/bin/python # -*- coding:utf-8 -*- -# Project libraries +from pathlib import Path +from sys import path as syspath + +syspath.append(str(Path(__file__).parent.parent)) import numpy as np diff --git a/package/src/__init__.py b/package/src/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/package/src/analysis.py b/package/src/analysis.py deleted file mode 100755 index 815eaa3..0000000 --- a/package/src/analysis.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/python -from getopt import error as get_error -from getopt import getopt -from sys import argv - -arglist = argv[1:] -options = "hf:p:i:l:" -long_options = ["help", "fits=", "snrp=", "snri=", "lim="] - -fits_path = None -SNRp_cut, SNRi_cut = 3, 3 -flux_lim = None -out_txt = None - -try: - arg, val = getopt(arglist, options, long_options) - - for curr_arg, curr_val in arg: - if curr_arg in ("-h", "--help"): - print("python3 analysis.py -f -p -i -l ") - elif curr_arg in ("-f", "--fits"): - fits_path = str(curr_val) - elif curr_arg in ("-p", "--snrp"): - SNRp_cut = int(curr_val) - elif curr_arg in ("-i", "--snri"): - SNRi_cut = int(curr_val) - elif curr_arg in ("-l", "--lim"): - flux_lim = list("".join(curr_val).split(",")) -except get_error as err: - print(str(err)) - -if fits_path is not None: - from astropy.io import fits - from lib.plots import pol_map - - Stokes_UV = fits.open(fits_path) - p = pol_map(Stokes_UV, SNRp_cut=SNRp_cut, SNRi_cut=SNRi_cut, flux_lim=flux_lim) - -else: - print("python3 analysis.py -f -p -i -l ") diff --git a/package/src/comparison_Kishimoto.py b/package/src/comparison_Kishimoto.py deleted file mode 100755 index 75b7073..0000000 --- a/package/src/comparison_Kishimoto.py +++ /dev/null @@ -1,214 +0,0 @@ -#!/usr/bin/python -from src.lib.background import gauss, bin_centers -from src.lib.deconvolve import zeropad -from src.lib.reduction import align_data -from src.lib.plots import princ_angle -from matplotlib.colors import LogNorm -from os.path import join as path_join -from astropy.io import fits -from astropy.wcs import WCS -from scipy.ndimage import shift -from scipy.optimize import curve_fit -import numpy as np -import matplotlib.pyplot as plt - -root_dir = path_join('/home/t.barnouin/Documents/Thesis/HST') -root_dir_K = path_join(root_dir, 'Kishimoto', 'output') -root_dir_S = path_join(root_dir, 'FOC_Reduction', 'output') -root_dir_data_S = path_join(root_dir, 'FOC_Reduction', 'data', 'NGC1068', '5144') -root_dir_plot_S = path_join(root_dir, 'FOC_Reduction', 'plots', 'NGC1068', '5144', 'notaligned') -filename_S = "NGC1068_FOC_b10.00pixel_not_aligned.fits" -plt.rcParams.update({'font.size': 15}) - -SNRi_cut = 30. -SNRp_cut = 3. - -data_K = {} -data_S = {} -for d, i in zip(['I', 'Q', 'U', 'P', 'PA', 'sI', 'sQ', 'sU', 'sP', 'sPA'], [0, 1, 2, 5, 8, (3, 0, 0), (3, 1, 1), (3, 2, 2), 6, 9]): - data_K[d] = np.loadtxt(path_join(root_dir_K, d+'.txt')) - with fits.open(path_join(root_dir_data_S, filename_S)) as f: - if not type(i) is int: - data_S[d] = np.sqrt(f[i[0]].data[i[1], i[2]]) - else: - data_S[d] = f[i].data - if i == 0: - header = f[i].header -wcs = WCS(header) -convert_flux = header['photflam'] - -bkg_S = np.median(data_S['I'])/3 -bkg_K = np.median(data_K['I'])/3 - -# zeropad data to get same size of array -shape = data_S['I'].shape -for d in data_K: - data_K[d] = zeropad(data_K[d], shape) - -# shift array to get same information in same pixel -data_arr, error_ar, heads, data_msk, shifts, shifts_err = align_data(np.array([data_S['I'], data_K['I']]), [header, header], error_array=np.array( - [data_S['sI'], data_K['sI']]), background=np.array([bkg_S, bkg_K]), upsample_factor=10., ref_center='center', return_shifts=True) -for d in data_K: - data_K[d] = shift(data_K[d], shifts[1], order=1, cval=0.) - -# compute pol components from shifted array -for d in [data_S, data_K]: - for i in d: - d[i][np.isnan(d[i])] = 0. - d['P'] = np.where(np.logical_and(np.isfinite(d['I']), d['I'] > 0.), np.sqrt(d['Q']**2+d['U']**2)/d['I'], 0.) - d['sP'] = np.where(np.logical_and(np.isfinite(d['I']), d['I'] > 0.), np.sqrt((d['Q']**2*d['sQ']**2+d['U']**2*d['sU']**2) / - (d['Q']**2+d['U']**2)+((d['Q']/d['I'])**2+(d['U']/d['I'])**2)*d['sI']**2)/d['I'], 0.) - d['d_P'] = np.where(np.logical_and(np.isfinite(d['P']), np.isfinite(d['sP'])), np.sqrt(d['P']**2-d['sP']**2), 0.) - d['PA'] = 0.5*np.arctan2(d['U'], d['Q'])+np.pi - d['SNRp'] = np.zeros(d['d_P'].shape) - d['SNRp'][d['sP'] > 0.] = d['d_P'][d['sP'] > 0.]/d['sP'][d['sP'] > 0.] - d['SNRi'] = np.zeros(d['I'].shape) - d['SNRi'][d['sI'] > 0.] = d['I'][d['sI'] > 0.]/d['sI'][d['sI'] > 0.] - d['mask'] = np.logical_and(d['SNRi'] > SNRi_cut, d['SNRp'] > SNRp_cut) -data_S['mask'], data_K['mask'] = np.logical_and(data_S['mask'], data_K['mask']), np.logical_and(data_S['mask'], data_K['mask']) - - -# -# Compute histogram of measured polarization in cut -# -bins = int(data_S['mask'].sum()/5) -bin_size = 1./bins -mod_p = np.linspace(0., 1., 300) -for d in [data_S, data_K]: - d['hist'], d['bin_edges'] = np.histogram(d['d_P'][d['mask']], bins=bins, range=(0., 1.)) - d['binning'] = bin_centers(d['bin_edges']) - peak, bins_fwhm = d['binning'][np.argmax(d['hist'])], d['binning'][d['hist'] > d['hist'].max()/2.] - fwhm = bins_fwhm[1]-bins_fwhm[0] - p0 = [d['hist'].max(), peak, fwhm] - try: - popt, pcov = curve_fit(gauss, d['binning'], d['hist'], p0=p0) - except RuntimeError: - popt = p0 - d['hist_chi2'] = np.sum((d['hist']-gauss(d['binning'], *popt))**2)/d['hist'].size - d['hist_popt'] = popt - -fig_p, ax_p = plt.subplots(num="Polarization degree histogram", figsize=(10, 6), constrained_layout=True) -ax_p.errorbar(data_S['binning'], data_S['hist'], xerr=bin_size/2., fmt='b.', ecolor='b', label='P through this pipeline') -ax_p.plot(mod_p, gauss(mod_p, *data_S['hist_popt']), 'b--', label='mean = {1:.2f}, stdev = {2:.2f}'.format(*data_S['hist_popt'])) -ax_p.errorbar(data_K['binning'], data_K['hist'], xerr=bin_size/2., fmt='r.', ecolor='r', label="P through Kishimoto's pipeline") -ax_p.plot(mod_p, gauss(mod_p, *data_K['hist_popt']), 'r--', label='mean = {1:.2f}, stdev = {2:.2f}'.format(*data_K['hist_popt'])) -ax_p.set(xlabel="Polarization degree", ylabel="Counts", title="Histogram of polarization degree computed in the cut for both pipelines.") -ax_p.legend() -fig_p.savefig(path_join(root_dir_plot_S, "NGC1068_K_pol_deg.png"), bbox_inches="tight", dpi=300) - -# -# Compute angular difference between the maps in cut -# -dtheta = np.where(data_S['mask'], 0.5*np.arctan((np.sin(2*data_S['PA'])*np.cos(2*data_K['PA'])-np.cos(2*data_S['PA']) * - np.cos(2*data_K['PA']))/(np.cos(2*data_S['PA'])*np.cos(2*data_K['PA'])+np.cos(2*data_S['PA'])*np.sin(2*data_K['PA']))), np.nan) -fig_pa = plt.figure(num="Polarization degree alignement") -ax_pa = fig_pa.add_subplot(111, projection=wcs) -cbar_ax_pa = fig_pa.add_axes([0.88, 0.12, 0.01, 0.75]) -ax_pa.set_title(r"Degree of alignement $\zeta$ of the polarization angles from the 2 pipelines in the cut") -im_pa = ax_pa.imshow(np.cos(2*dtheta), vmin=-1., vmax=1., origin='lower', cmap='bwr', label=r"$\zeta$ between this pipeline and Kishimoto's") -cbar_pa = plt.colorbar(im_pa, cax=cbar_ax_pa, label=r"$\zeta = \cos\left( 2 \cdot \delta\theta_P \right)$") -ax_pa.coords[0].set_axislabel('Right Ascension (J2000)') -ax_pa.coords[1].set_axislabel('Declination (J2000)') -fig_pa.savefig(path_join(root_dir_plot_S, "NGC1068_K_pol_ang.png"), bbox_inches="tight", dpi=300) - -# -# Compute power uncertainty difference between the maps in cut -# -eta = np.where(data_S['mask'], np.abs(data_K['d_P']-data_S['d_P'])/np.sqrt(data_S['sP']**2+data_K['sP']**2)/2., np.nan) -fig_dif_p = plt.figure(num="Polarization power difference ratio") -ax_dif_p = fig_dif_p.add_subplot(111, projection=wcs) -cbar_ax_dif_p = fig_dif_p.add_axes([0.88, 0.12, 0.01, 0.75]) -ax_dif_p.set_title(r"Degree of difference $\eta$ of the polarization from the 2 pipelines in the cut") -im_dif_p = ax_dif_p.imshow(eta, vmin=0., vmax=2., origin='lower', cmap='bwr_r', label=r"$\eta$ between this pipeline and Kishimoto's") -cbar_dif_p = plt.colorbar(im_dif_p, cax=cbar_ax_dif_p, label=r"$\eta = \frac{2 \left|P^K-P^S\right|}{\sqrt{{\sigma^K_P}^2+{\sigma^S_P}^2}}$") -ax_dif_p.coords[0].set_axislabel('Right Ascension (J2000)') -ax_dif_p.coords[1].set_axislabel('Declination (J2000)') -fig_dif_p.savefig(path_join(root_dir_plot_S, "NGC1068_K_pol_diff.png"), bbox_inches="tight", dpi=300) - -# -# Compute angle uncertainty difference between the maps in cut -# -eta = np.where(data_S['mask'], np.abs(data_K['PA']-data_S['PA'])/np.sqrt(data_S['sPA']**2+data_K['sPA']**2)/2., np.nan) -fig_dif_pa = plt.figure(num="Polarization angle difference ratio") -ax_dif_pa = fig_dif_pa.add_subplot(111, projection=wcs) -cbar_ax_dif_pa = fig_dif_pa.add_axes([0.88, 0.12, 0.01, 0.75]) -ax_dif_pa.set_title(r"Degree of difference $\eta$ of the polarization from the 2 pipelines in the cut") -im_dif_pa = ax_dif_pa.imshow(eta, vmin=0., vmax=2., origin='lower', cmap='bwr_r', label=r"$\eta$ between this pipeline and Kishimoto's") -cbar_dif_pa = plt.colorbar(im_dif_pa, cax=cbar_ax_dif_pa, - label=r"$\eta = \frac{2 \left|\theta_P^K-\theta_P^S\right|}{\sqrt{{\sigma^K_{\theta_P}}^2+{\sigma^S_{\theta_P}}^2}}$") -ax_dif_pa.coords[0].set_axislabel('Right Ascension (J2000)') -ax_dif_pa.coords[1].set_axislabel('Declination (J2000)') -fig_dif_pa.savefig(path_join(root_dir_plot_S, "NGC1068_K_polang_diff.png"), bbox_inches="tight", dpi=300) - -# display both polarization maps to check consistency -# plt.rcParams.update({'font.size': 15}) -fig = plt.figure(num="Polarization maps comparison", figsize=(10, 10)) -ax = fig.add_subplot(111, projection=wcs) -fig.subplots_adjust(right=0.85) -cbar_ax = fig.add_axes([0.88, 0.12, 0.01, 0.75]) - -for d in [data_S, data_K]: - d['X'], d['Y'] = np.meshgrid(np.arange(d['I'].shape[1]), np.arange(d['I'].shape[0])) - d['xy_U'], d['xy_V'] = np.where(d['mask'], d['d_P']*np.cos(np.pi/2.+d['PA']), np.nan), np.where(d['mask'], d['d_P']*np.sin(np.pi/2.+d['PA']), np.nan) - -im0 = ax.imshow(data_S['I']*convert_flux, norm=LogNorm(data_S['I'][data_S['I'] > 0].min()*convert_flux, data_S['I'] - [data_S['I'] > 0].max()*convert_flux), origin='lower', cmap='gray', label=r"$I_{STOKES}$ through this pipeline") -quiv0 = ax.quiver(data_S['X'], data_S['Y'], data_S['xy_U'], data_S['xy_V'], units='xy', angles='uv', scale=0.5, scale_units='xy', - pivot='mid', headwidth=0., headlength=0., headaxislength=0., width=0.2, color='b', alpha=0.75, label="PA through this pipeline") -quiv1 = ax.quiver(data_K['X'], data_K['Y'], data_K['xy_U'], data_K['xy_V'], units='xy', angles='uv', scale=0.5, scale_units='xy', - pivot='mid', headwidth=0., headlength=0., headaxislength=0., width=0.1, color='r', alpha=0.75, label="PA through Kishimoto's pipeline") - -ax.set_title(r"$SNR_P \geq$ "+str(SNRi_cut)+r"$\; & \; SNR_I \geq $"+str(SNRp_cut)) -# ax.coords.grid(True, color='white', ls='dotted', alpha=0.5) -ax.coords[0].set_axislabel('Right Ascension (J2000)') -ax.coords[0].set_axislabel_position('b') -ax.coords[0].set_ticklabel_position('b') -ax.coords[1].set_axislabel('Declination (J2000)') -ax.coords[1].set_axislabel_position('l') -ax.coords[1].set_ticklabel_position('l') -# ax.axis('equal') - -cbar = plt.colorbar(im0, cax=cbar_ax, label=r"$F_{\lambda}$ [$ergs \cdot cm^{-2} \cdot s^{-1} \cdot \AA^{-1}$]") -ax.legend(loc='upper right') -fig.savefig(path_join(root_dir_plot_S, "NGC1068_K_comparison.png"), bbox_inches="tight", dpi=300) - -# compute integrated polarization parameters on a specific cut -for d in [data_S, data_K]: - d['I_dil'] = np.sum(d['I'][d['mask']]) - d['sI_dil'] = np.sqrt(np.sum(d['sI'][d['mask']]**2)) - d['Q_dil'] = np.sum(d['Q'][d['mask']]) - d['sQ_dil'] = np.sqrt(np.sum(d['sQ'][d['mask']]**2)) - d['U_dil'] = np.sum(d['U'][d['mask']]) - d['sU_dil'] = np.sqrt(np.sum(d['sU'][d['mask']]**2)) - - d['P_dil'] = np.sqrt(d['Q_dil']**2+d['U_dil']**2)/d['I_dil'] - d['sP_dil'] = np.sqrt((d['Q_dil']**2*d['sQ_dil']**2+d['U_dil']**2*d['sU_dil']**2)/(d['Q_dil']**2+d['U_dil']**2) + - ((d['Q_dil']/d['I_dil'])**2+(d['U_dil']/d['I_dil'])**2)*d['sI_dil']**2)/d['I_dil'] - d['d_P_dil'] = np.sqrt(d['P_dil']**2-d['sP_dil']**2) - d['PA_dil'] = princ_angle((90./np.pi)*np.arctan2(d['U_dil'], d['Q_dil'])) - d['sPA_dil'] = princ_angle((90./(np.pi*(d['Q_dil']**2+d['U_dil']**2)))*np.sqrt(d['Q_dil']**2*d['sU_dil']**2+d['U_dil']**2*d['sU_dil']**2)) -print('From this pipeline :\n', "P = {0:.2f} ± {1:.2f} %\n".format( - data_S['d_P_dil']*100., data_S['sP_dil']*100.), "PA = {0:.2f} ± {1:.2f} °".format(data_S['PA_dil'], data_S['sPA_dil'])) -print("From Kishimoto's pipeline :\n", "P = {0:.2f} ± {1:.2f} %\n".format( - data_K['d_P_dil']*100., data_K['sP_dil']*100.), "PA = {0:.2f} ± {1:.2f} °".format(data_K['PA_dil'], data_K['sPA_dil'])) - -# compare different types of error -print("This pipeline : average sI/I={0:.2f} ; sQ/Q={1:.2f} ; sU/U={2:.2f} ; sP/P={3:.2f}".format(np.mean(data_S['sI'][data_S['mask']]/data_S['I'][data_S['mask']]), np.mean( - data_S['sQ'][data_S['mask']]/data_S['Q'][data_S['mask']]), np.mean(data_S['sU'][data_S['mask']]/data_S['U'][data_S['mask']]), np.mean(data_S['sP'][data_S['mask']]/data_S['P'][data_S['mask']]))) -print("Kishimoto's pipeline : average sI/I={0:.2f} ; sQ/Q={1:.2f} ; sU/U={2:.2f} ; sP/P={3:.2f}".format(np.mean(data_K['sI'][data_S['mask']]/data_K['I'][data_S['mask']]), np.mean( - data_K['sQ'][data_S['mask']]/data_K['Q'][data_S['mask']]), np.mean(data_K['sU'][data_S['mask']]/data_K['U'][data_S['mask']]), np.mean(data_K['sP'][data_S['mask']]/data_K['P'][data_S['mask']]))) -for d, i in zip(['I', 'Q', 'U', 'P', 'PA', 'sI', 'sQ', 'sU', 'sP', 'sPA'], [0, 1, 2, 5, 8, (3, 0, 0), (3, 1, 1), (3, 2, 2), 6, 9]): - data_K[d] = np.loadtxt(path_join(root_dir_K, d+'.txt')) - with fits.open(path_join(root_dir_data_S, filename_S)) as f: - if not type(i) is int: - data_S[d] = np.sqrt(f[i[0]].data[i[1], i[2]]) - else: - data_S[d] = f[i].data - if i == 0: - header = f[i].header - -# from Kishimoto's pipeline : IQU_dir, IQU_shift, IQU_stat, IQU_trans -# from my pipeline : raw_bg, raw_flat, raw_psf, raw_shift, raw_wav, IQU_dir -# but errors from my pipeline are propagated all along, how to compare then ? - -plt.show() diff --git a/package/src/emission_center.py b/package/src/emission_center.py new file mode 100755 index 0000000..829fb54 --- /dev/null +++ b/package/src/emission_center.py @@ -0,0 +1,77 @@ +#!/usr/bin/python +# -*- coding:utf-8 -*- +from pathlib import Path +from sys import path as syspath + +syspath.append(str(Path(__file__).parent.parent)) + + +def main(infile, target=None, output_dir=None): + from os.path import join as pathjoin + + import numpy as np + from astropy.io.fits import open as fits_open + from astropy.wcs import WCS + from lib.plots import polarization_map + from lib.utils import CenterConf, PCconf + from matplotlib.patches import Rectangle + from matplotlib.pyplot import show + + output = [] + levelssnr = np.array([3.0, 4.0]) + levelsconf = np.array([0.99]) + + Stokes = fits_open(infile) + stkI = Stokes["I_STOKES"].data + QN, UN, QN_ERR, UN_ERR = np.full((4, stkI.shape[0], stkI.shape[1]), np.nan) + for sflux, nflux in zip( + [Stokes["Q_STOKES"].data, Stokes["U_STOKES"].data, np.sqrt(Stokes["IQU_COV_MATRIX"].data[1, 1]), np.sqrt(Stokes["IQU_COV_MATRIX"].data[2, 2])], + [QN, UN, QN_ERR, UN_ERR], + ): + nflux[stkI > 0.0] = sflux[stkI > 0.0] / stkI[stkI > 0.0] + Stokesconf = PCconf(QN, UN, QN_ERR, UN_ERR) + Stokesmask = Stokes["DATA_MASK"].data.astype(bool) + Stokessnr = np.zeros(Stokesmask.shape) + Stokessnr[Stokes["POL_DEG_ERR"].data > 0.0] = ( + Stokes["POL_DEG_DEBIASED"].data[Stokes["POL_DEG_ERR"].data > 0.0] / Stokes["POL_DEG_ERR"].data[Stokes["POL_DEG_ERR"].data > 0.0] + ) + + Stokescentconf, Stokescenter = CenterConf(Stokesconf > 0.99, Stokes["POL_ANG"].data, Stokes["POL_ANG_ERR"].data) + Stokespos = WCS(Stokes[0].header).pixel_to_world(*Stokescenter) + + if target is None: + target = Stokes[0].header["TARGNAME"] + + fig, ax = polarization_map(Stokes, P_cut=0.99, step_vec=2, scale_vec=5, display="i") + + snrcont = ax.contour(Stokessnr, levelssnr, colors="b") + confcont = ax.contour(Stokesconf, levelsconf, colors="r") + confcenter = ax.plot(*Stokescenter, marker="+", color="gray", label="Best confidence for center: {0}".format(Stokespos.to_string("hmsdms"))) + confcentcont = ax.contour(Stokescentconf, [0.01], colors="gray") + handles, labels = ax.get_legend_handles_labels() + labels.append(r"$SNR_P \geq$ 3 and 4 contours") + handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=snrcont.get_edgecolor()[0])) + labels.append(r"Polarization $Conf_{99\%}$ contour") + handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=confcont.get_edgecolor()[0])) + labels.append(r"Center $Conf_{99\%}$ contour") + handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=confcentcont.get_edgecolor()[0])) + ax.legend(handles=handles, labels=labels, bbox_to_anchor=(0.0, -0.12, 1.0, 0.102), loc="lower left", mode="expand", borderaxespad=0.0) + show() + + if output_dir is not None: + filename = pathjoin(output_dir, "%s_center.pdf" % target) + fig.savefig(filename, dpi=150, facecolor="None") + output.append(filename) + return output + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="Look for the center of emission for a given reduced observation") + parser.add_argument("-t", "--target", metavar="targetname", required=False, help="the name of the target", type=str, default=None) + parser.add_argument("-f", "--file", metavar="path", required=False, help="The full or relative path to the data product", type=str, default=None) + parser.add_argument("-o", "--output_dir", metavar="directory_path", required=False, help="output directory path for the plots", type=str, default="./data") + args = parser.parse_args() + exitcode = main(infile=args.file, target=args.target, output_dir=args.output_dir) + print("Written to: ", exitcode) diff --git a/package/src/get_cdelt.py b/package/src/get_cdelt.py index b7054c6..d6ea688 100755 --- a/package/src/get_cdelt.py +++ b/package/src/get_cdelt.py @@ -1,4 +1,9 @@ #!/usr/bin/python +# -*- coding:utf-8 -*- +from pathlib import Path +from sys import path as syspath + +syspath.append(str(Path(__file__).parent.parent)) def main(infiles=None): diff --git a/package/overplot_IC5063.py b/package/src/overplot_IC5063.py similarity index 66% rename from package/overplot_IC5063.py rename to package/src/overplot_IC5063.py index 6a4fb1e..f9ac6c3 100755 --- a/package/overplot_IC5063.py +++ b/package/src/overplot_IC5063.py @@ -1,4 +1,10 @@ #!/usr/bin/python3 +# -*- coding:utf-8 -*- +from pathlib import Path +from sys import path as syspath + +syspath.append(str(Path(__file__).parent.parent)) + import numpy as np from astropy.io import fits from lib.plots import overplot_pol, overplot_radio @@ -18,33 +24,33 @@ levelsMorganti = np.logspace(-0.1249, 1.97, 7) / 100.0 levels18GHz = levelsMorganti * Stokes_18GHz[0].data.max() A = overplot_radio(Stokes_UV, Stokes_18GHz) -A.plot(levels=levels18GHz, SNRp_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/18GHz_overplot.pdf", vec_scale=None) +A.plot(levels=levels18GHz, P_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/18GHz_overplot.pdf", scale_vec=None) levels24GHz = levelsMorganti * Stokes_24GHz[0].data.max() B = overplot_radio(Stokes_UV, Stokes_24GHz) -B.plot(levels=levels24GHz, SNRp_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/24GHz_overplot.pdf", vec_scale=None) +B.plot(levels=levels24GHz, P_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/24GHz_overplot.pdf", scale_vec=None) levels103GHz = levelsMorganti * Stokes_103GHz[0].data.max() C = overplot_radio(Stokes_UV, Stokes_103GHz) -C.plot(levels=levels103GHz, SNRp_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/103GHz_overplot.pdf", vec_scale=None) +C.plot(levels=levels103GHz, P_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/103GHz_overplot.pdf", scale_vec=None) levels229GHz = levelsMorganti * Stokes_229GHz[0].data.max() D = overplot_radio(Stokes_UV, Stokes_229GHz) -D.plot(levels=levels229GHz, SNRp_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/229GHz_overplot.pdf", vec_scale=None) +D.plot(levels=levels229GHz, P_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/229GHz_overplot.pdf", scale_vec=None) levels357GHz = levelsMorganti * Stokes_357GHz[0].data.max() E = overplot_radio(Stokes_UV, Stokes_357GHz) -E.plot(levels=levels357GHz, SNRp_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/357GHz_overplot.pdf", vec_scale=None) +E.plot(levels=levels357GHz, P_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/357GHz_overplot.pdf", scale_vec=None) # F = overplot_pol(Stokes_UV, Stokes_S2) -# F.plot(SNRp_cut=3.0, SNRi_cut=80.0, savename='./plots/IC5063/S2_overplot.pdf', norm=LogNorm(vmin=5e-20,vmax=5e-18)) +# F.plot(P_cut=3.0, SNRi_cut=80.0, savename='./plots/IC5063/S2_overplot.pdf', norm=LogNorm(vmin=5e-20,vmax=5e-18)) G = overplot_pol(Stokes_UV, Stokes_IR, cmap="inferno") G.plot( - SNRp_cut=2.0, + P_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/IR_overplot.pdf", - vec_scale=None, + scale_vec=None, norm=LogNorm(Stokes_IR[0].data.max() * Stokes_IR[0].header["photflam"] / 1e3, Stokes_IR[0].data.max() * Stokes_IR[0].header["photflam"]), cmap="inferno_r", ) diff --git a/package/overplot_MRK463E.py b/package/src/overplot_MRK463E.py similarity index 66% rename from package/overplot_MRK463E.py rename to package/src/overplot_MRK463E.py index 5c3411d..a571a7a 100755 --- a/package/overplot_MRK463E.py +++ b/package/src/overplot_MRK463E.py @@ -1,20 +1,26 @@ #!/usr/bin/python3 +# -*- coding:utf-8 -*- +from pathlib import Path +from sys import path as syspath + +syspath.append(str(Path(__file__).parent.parent)) + import numpy as np from astropy.io import fits from lib.plots import overplot_chandra, overplot_pol from matplotlib.colors import LogNorm -Stokes_UV = fits.open("./data/MRK463E/5960/MRK463E_FOC_b0.05arcsec_c0.10arcsec.fits") +Stokes_UV = fits.open("./data/MRK463E/5960/MRK463E_FOC_b0.05arcsec_c0.07arcsec.fits") Stokes_IR = fits.open("./data/MRK463E/WFPC2/IR_rot_crop.fits") Stokes_Xr = fits.open("./data/MRK463E/Chandra/X_ray_crop.fits") levels = np.geomspace(1.0, 99.0, 7) A = overplot_chandra(Stokes_UV, Stokes_Xr, norm=LogNorm()) -A.plot(levels=levels, SNRp_cut=3.0, SNRi_cut=3.0, vec_scale=5, zoom=1, savename="./plots/MRK463E/Chandra_overplot.pdf") +A.plot(levels=levels, P_cut=0.99, SNRi_cut=1.0, scale_vec=5, zoom=1, savename="./plots/MRK463E/Chandra_overplot.pdf") A.write_to(path1="./data/MRK463E/FOC_data_Chandra.fits", path2="./data/MRK463E/Chandra_data.fits", suffix="aligned") levels = np.array([0.8, 2, 5, 10, 20, 50]) / 100.0 * Stokes_UV[0].header["photflam"] B = overplot_pol(Stokes_UV, Stokes_IR, norm=LogNorm()) -B.plot(levels=levels, SNRp_cut=3.0, SNRi_cut=3.0, vec_scale=5, norm=LogNorm(8.5e-18, 2.5e-15), savename="./plots/MRK463E/IR_overplot.pdf") +B.plot(levels=levels, P_cut=0.99, SNRi_cut=1.0, scale_vec=5, norm=LogNorm(8.5e-18, 2.5e-15), savename="./plots/MRK463E/IR_overplot.pdf") B.write_to(path1="./data/MRK463E/FOC_data_WFPC.fits", path2="./data/MRK463E/WFPC_data.fits", suffix="aligned") diff --git a/package/test_center.py b/package/test_center.py deleted file mode 100644 index bedfda8..0000000 --- a/package/test_center.py +++ /dev/null @@ -1,109 +0,0 @@ -import matplotlib.pyplot as plt -import numpy as np -from astropy.io.fits import open as fits_open -from astropy.wcs import WCS -from lib.utils import CenterConf, PCconf -from matplotlib.colors import LogNorm -from matplotlib.patches import Rectangle - -levelssnr = np.array([3.0, 4.0]) -levelsconf = np.array([0.99]) - -NGC1068 = fits_open("./data/NGC1068/5144/NGC1068_FOC_b0.05arcsec_c0.07arcsec.fits") -NGC1068conf = PCconf( - NGC1068["Q_STOKES"].data / NGC1068["I_STOKES"].data, - NGC1068["U_STOKES"].data / NGC1068["I_STOKES"].data, - np.sqrt(NGC1068["IQU_COV_MATRIX"].data[1, 1]) / NGC1068["I_STOKES"].data, - np.sqrt(NGC1068["IQU_COV_MATRIX"].data[2, 2]) / NGC1068["I_STOKES"].data, -) -NGC1068mask = NGC1068["DATA_MASK"].data.astype(bool) -NGC1068snr = np.full(NGC1068mask.shape, np.nan) -NGC1068snr[NGC1068["POL_DEG_ERR"].data > 0.0] = ( - NGC1068["POL_DEG_DEBIASED"].data[NGC1068["POL_DEG_ERR"].data > 0.0] / NGC1068["POL_DEG_ERR"].data[NGC1068["POL_DEG_ERR"].data > 0.0] -) - -NGC1068centconf, NGC1068center = CenterConf(NGC1068conf > 0.99, NGC1068["POL_ANG"].data, NGC1068["POL_ANG_ERR"].data) -NGC1068pos = WCS(NGC1068[0].header).pixel_to_world(*NGC1068center) - -figngc, axngc = plt.subplots(1, 2, layout="tight", figsize=(18, 9), subplot_kw=dict(projection=WCS(NGC1068[0].header)), sharex=True, sharey=True) - -axngc[0].set(xlabel="RA", ylabel="DEC", title="NGC1069 intensity map with SNR and confidence contours") -vmin, vmax = ( - 0.5 * np.median(NGC1068["I_STOKES"].data[NGC1068mask]) * NGC1068[0].header["PHOTFLAM"], - np.max(NGC1068["I_STOKES"].data[NGC1068mask]) * NGC1068[0].header["PHOTFLAM"], -) -imngc = axngc[0].imshow(NGC1068["I_STOKES"].data * NGC1068["I_STOKES"].header["PHOTFLAM"], norm=LogNorm(vmin, vmax), cmap="inferno") -ngcsnrcont = axngc[0].contour(NGC1068snr, levelssnr, colors="b") -ngcconfcont = axngc[0].contour(NGC1068conf, levelsconf, colors="r") -ngcconfcenter = axngc[0].plot(*NGC1068center, marker="+",color="gray", label="Best confidence for center: {0}".format(NGC1068pos.to_string('hmsdms'))) -ngcconfcentcont = axngc[0].contour(NGC1068centconf, [0.01], colors="gray") -handles, labels = axngc[0].get_legend_handles_labels() -labels.append("SNR contours") -handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=ngcsnrcont.collections[0].get_edgecolor()[0])) -labels.append("CONF99 contour") -handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=ngcconfcont.collections[0].get_edgecolor()[0])) -labels.append("Center CONF99 contour") -handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=ngcconfcentcont.collections[0].get_edgecolor()[0])) -axngc[0].legend(handles=handles, labels=labels) - -axngc[1].set(xlabel="RA", ylabel="DEC", title="Location of the nucleus confidence map") -ngccent = axngc[1].imshow(NGC1068centconf, vmin=0.0, cmap="inferno") -ngccentcont = axngc[1].contour(NGC1068centconf, [0.01], colors="gray") -ngccentcenter = axngc[1].plot(*NGC1068center, marker="+",color="gray", label="Best confidence for center: {0}".format(NGC1068pos.to_string('hmsdms'))) -handles, labels = axngc[1].get_legend_handles_labels() -labels.append("CONF99 contour") -handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=ngccentcont.collections[0].get_edgecolor()[0])) -axngc[1].legend(handles=handles, labels=labels) - -figngc.savefig("NGC1068_center.pdf", dpi=150, facecolor="None") - -################################################################################################### - -MRK463E = fits_open("./data/MRK463E/5960/MRK463E_FOC_b0.05arcsec_c0.07arcsec.fits") -MRK463Econf = PCconf( - MRK463E["Q_STOKES"].data / MRK463E["I_STOKES"].data, - MRK463E["U_STOKES"].data / MRK463E["I_STOKES"].data, - np.sqrt(MRK463E["IQU_COV_MATRIX"].data[1, 1]) / MRK463E["I_STOKES"].data, - np.sqrt(MRK463E["IQU_COV_MATRIX"].data[2, 2]) / MRK463E["I_STOKES"].data, -) -MRK463Emask = MRK463E["DATA_MASK"].data.astype(bool) -MRK463Esnr = np.full(MRK463Emask.shape, np.nan) -MRK463Esnr[MRK463E["POL_DEG_ERR"].data > 0.0] = ( - MRK463E["POL_DEG_DEBIASED"].data[MRK463E["POL_DEG_ERR"].data > 0.0] / MRK463E["POL_DEG_ERR"].data[MRK463E["POL_DEG_ERR"].data > 0.0] -) - -MRK463Ecentconf, MRK463Ecenter = CenterConf(MRK463Econf > 0.99, MRK463E["POL_ANG"].data, MRK463E["POL_ANG_ERR"].data) -MRK463Epos = WCS(MRK463E[0].header).pixel_to_world(*MRK463Ecenter) - -figmrk, axmrk = plt.subplots(1, 2, layout="tight", figsize=(18, 9), subplot_kw=dict(projection=WCS(MRK463E[0].header)), sharex=True, sharey=True) - -axmrk[0].set(xlabel="RA", ylabel="DEC", title="NGC1069 intensity map with SNR and confidence contours") -vmin, vmax = ( - 0.5 * np.median(MRK463E["I_STOKES"].data[MRK463Emask]) * MRK463E[0].header["PHOTFLAM"], - np.max(MRK463E["I_STOKES"].data[MRK463Emask]) * MRK463E[0].header["PHOTFLAM"], -) -immrk = axmrk[0].imshow(MRK463E["I_STOKES"].data * MRK463E["I_STOKES"].header["PHOTFLAM"], norm=LogNorm(vmin, vmax), cmap="inferno") -mrksnrcont = axmrk[0].contour(MRK463Esnr, levelssnr, colors="b") -mrkconfcont = axmrk[0].contour(MRK463Econf, levelsconf, colors="r") -mrkconfcenter = axmrk[0].plot(*MRK463Ecenter, marker="+",color="gray", label="Best confidence for center: {0}".format(MRK463Epos.to_string('hmsdms'))) -mrkconfcentcont = axmrk[0].contour(MRK463Ecentconf, [0.01], colors="gray") -handles, labels = axmrk[0].get_legend_handles_labels() -labels.append("SNR contours") -handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=mrksnrcont.collections[0].get_edgecolor()[0])) -labels.append("CONF99 contour") -handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=mrkconfcont.collections[0].get_edgecolor()[0])) -labels.append("Center CONF99 contour") -handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=mrkconfcentcont.collections[0].get_edgecolor()[0])) -axmrk[0].legend(handles=handles, labels=labels) - -axmrk[1].set(xlabel="RA", ylabel="DEC", title="Location of the nucleus confidence map") -mrkcent = axmrk[1].imshow(MRK463Ecentconf, vmin=0.0, cmap="inferno") -mrkcentcont = axmrk[1].contour(MRK463Ecentconf, [0.01], colors="gray") -mrkcentcenter = axmrk[1].plot(*MRK463Ecenter, marker="+",color="gray", label="Best confidence for center: {0}".format(MRK463Epos.to_string('hmsdms'))) -handles, labels = axmrk[1].get_legend_handles_labels() -labels.append("CONF99 contour") -handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=mrkcentcont.collections[0].get_edgecolor()[0])) -axmrk[1].legend(handles=handles, labels=labels) - -figmrk.savefig("MRK463E_center.pdf", dpi=150, facecolor="None") -plt.show() From 946e6cd5c9038f12d945e2e53fcc2d7de07b950c Mon Sep 17 00:00:00 2001 From: Thibault Barnouin Date: Mon, 23 Sep 2024 14:13:18 +0200 Subject: [PATCH 08/18] add requirements for ContourSet depreciation in matplotlib 3.8 --- package/lib/plots.py | 13 +++++++++---- package/requirements.txt | 7 +++++++ package/src/emission_center.py | 28 +++++++++++++++------------- 3 files changed, 31 insertions(+), 17 deletions(-) create mode 100644 package/requirements.txt diff --git a/package/lib/plots.py b/package/lib/plots.py index df6354f..9d05d9c 100755 --- a/package/lib/plots.py +++ b/package/lib/plots.py @@ -221,6 +221,8 @@ def polarization_map( savename=None, plots_folder="", display="default", + fig=None, + ax=None, ): """ Plots polarization map from Stokes HDUList. @@ -338,10 +340,13 @@ def polarization_map( # Plot the map plt.rcParams.update({"font.size": 14}) plt.rcdefaults() - ratiox = max(int(stkI.shape[1] / (stkI.shape[0])), 1) - ratioy = max(int((stkI.shape[0]) / stkI.shape[1]), 1) - fig, ax = plt.subplots(figsize=(7 * ratiox, 7 * ratioy), layout="compressed", subplot_kw=dict(projection=wcs)) - ax.set(aspect="equal", fc="k", ylim=[-stkI.shape[0] * 0.10, stkI.shape[0] * 1.15]) + if fig is None: + ratiox = max(int(stkI.shape[1] / (stkI.shape[0])), 1) + ratioy = max(int((stkI.shape[0]) / stkI.shape[1]), 1) + fig = plt.figure(figsize=(7 * ratiox, 7 * ratioy), layout="constrained") + if ax is None: + ax = fig.add_subplot(111, projection=wcs) + ax.set(aspect="equal", fc="k", ylim=[-stkI.shape[0] * 0.10, stkI.shape[0] * 1.15]) # fig.subplots_adjust(hspace=0, wspace=0, left=0.102, right=1.02) # ax.coords.grid(True, color='white', ls='dotted', alpha=0.5) diff --git a/package/requirements.txt b/package/requirements.txt new file mode 100644 index 0000000..0f2c0ad --- /dev/null +++ b/package/requirements.txt @@ -0,0 +1,7 @@ +# Requirements for FOC_Reduction + +numpy +scipy +astropy +astroquery # To directly query the Mast archives +matplotlib >= 3.8 # Brought some depreciation on ContourSet diff --git a/package/src/emission_center.py b/package/src/emission_center.py index 829fb54..ad3453d 100755 --- a/package/src/emission_center.py +++ b/package/src/emission_center.py @@ -15,11 +15,9 @@ def main(infile, target=None, output_dir=None): from lib.plots import polarization_map from lib.utils import CenterConf, PCconf from matplotlib.patches import Rectangle - from matplotlib.pyplot import show + from matplotlib.pyplot import figure, show output = [] - levelssnr = np.array([3.0, 4.0]) - levelsconf = np.array([0.99]) Stokes = fits_open(infile) stkI = Stokes["I_STOKES"].data @@ -42,26 +40,30 @@ def main(infile, target=None, output_dir=None): if target is None: target = Stokes[0].header["TARGNAME"] - fig, ax = polarization_map(Stokes, P_cut=0.99, step_vec=2, scale_vec=5, display="i") + fig = figure(figsize=(8,9),layout="constrained") + fig, ax = polarization_map(Stokes, P_cut=0.99, step_vec=2, scale_vec=5, display="i", fig=fig) - snrcont = ax.contour(Stokessnr, levelssnr, colors="b") - confcont = ax.contour(Stokesconf, levelsconf, colors="r") - confcenter = ax.plot(*Stokescenter, marker="+", color="gray", label="Best confidence for center: {0}".format(Stokespos.to_string("hmsdms"))) + ax.plot(*Stokescenter, marker="+", color="gray", label="Best confidence for center: {0}".format(Stokespos.to_string("hmsdms"))) confcentcont = ax.contour(Stokescentconf, [0.01], colors="gray") + confcont = ax.contour(Stokesconf, [0.99], colors="r") + snr3cont = ax.contour(Stokessnr, [3.0], colors="b", linestyles="dashed") + snr4cont = ax.contour(Stokessnr, [4.0], colors="b") handles, labels = ax.get_legend_handles_labels() - labels.append(r"$SNR_P \geq$ 3 and 4 contours") - handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=snrcont.get_edgecolor()[0])) - labels.append(r"Polarization $Conf_{99\%}$ contour") - handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=confcont.get_edgecolor()[0])) labels.append(r"Center $Conf_{99\%}$ contour") handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=confcentcont.get_edgecolor()[0])) - ax.legend(handles=handles, labels=labels, bbox_to_anchor=(0.0, -0.12, 1.0, 0.102), loc="lower left", mode="expand", borderaxespad=0.0) - show() + labels.append(r"Polarization $Conf_{99\%}$ contour") + handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=confcont.get_edgecolor()[0])) + labels.append(r"$SNR_P \geq$ 3 contour") + handles.append(Rectangle((0, 0), 1, 1, fill=False, ls="--", ec=snr3cont.get_edgecolor()[0])) + labels.append(r"$SNR_P \geq$ 4 contour") + handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=snr4cont.get_edgecolor()[0])) + ax.legend(handles=handles, labels=labels, bbox_to_anchor=(0.0, -0.02, 1.0, 0.01), loc="upper left", mode="expand", borderaxespad=0.0) if output_dir is not None: filename = pathjoin(output_dir, "%s_center.pdf" % target) fig.savefig(filename, dpi=150, facecolor="None") output.append(filename) + show() return output From 8df2fcce638acee30dbbf0bb52c61fec0070acea Mon Sep 17 00:00:00 2001 From: Thibault Barnouin Date: Mon, 23 Sep 2024 14:16:46 +0200 Subject: [PATCH 09/18] move requirements add license --- license.md | 10 ++++++++++ package/requirements.txt => requirements.txt | 0 2 files changed, 10 insertions(+) create mode 100644 license.md rename package/requirements.txt => requirements.txt (100%) diff --git a/license.md b/license.md new file mode 100644 index 0000000..5ee3421 --- /dev/null +++ b/license.md @@ -0,0 +1,10 @@ +MIT License + +Copyright (c) 2024 Thibault Barnouin + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/package/requirements.txt b/requirements.txt similarity index 100% rename from package/requirements.txt rename to requirements.txt From f84898a9b4addecb0c6d6f94da43b48ac2e13db5 Mon Sep 17 00:00:00 2001 From: Thibault Barnouin Date: Wed, 25 Sep 2024 17:36:05 +0200 Subject: [PATCH 10/18] adjustements to pdf static output --- package/lib/plots.py | 265 +++++++++++++++++--------------- package/src/emission_center.py | 10 +- package/src/overplot_MRK463E.py | 2 +- 3 files changed, 148 insertions(+), 129 deletions(-) diff --git a/package/lib/plots.py b/package/lib/plots.py index 9d05d9c..d021094 100755 --- a/package/lib/plots.py +++ b/package/lib/plots.py @@ -60,7 +60,10 @@ from mpl_toolkits.axes_grid1.anchored_artists import ( ) from scipy.ndimage import zoom as sc_zoom -from .utils import PCconf, princ_angle, rot2D, sci_not +try: + from .utils import PCconf, princ_angle, rot2D, sci_not +except ImportError: + from utils import PCconf, princ_angle, rot2D, sci_not def plot_obs(data_array, headers, rectangle=None, savename=None, plots_folder="", **kwargs): @@ -205,7 +208,6 @@ def plot_Stokes(Stokes, savename=None, plots_folder=""): else: savename = savename[:-4] + "_IQU" + savename[-4:] fig.savefig(path_join(plots_folder, savename), bbox_inches="tight", dpi=150, facecolor="None") - plt.show() return 0 @@ -562,7 +564,7 @@ def polarization_map( if savename is not None: if savename[-4:] not in [".png", ".jpg", ".pdf"]: savename += ".pdf" - fig.savefig(path_join(plots_folder, savename), bbox_inches="tight", dpi=150, facecolor="None") + fig.savefig(path_join(plots_folder, savename), bbox_inches="tight", dpi=300, facecolor="None") return fig, ax @@ -3353,132 +3355,149 @@ if __name__ == "__main__": parser.add_argument( "-pdf", "--static-pdf", metavar="static_pdf", required=False, help="Whether the analysis tool or the static pdfs should be outputed", default=None ) + parser.add_argument( + "-t", "--type", metavar="type", required=False, help="Type of plot to be be outputed", default=None + ) args = parser.parse_args() if args.file is not None: Stokes_UV = fits.open(args.file, mode="readonly") if args.static_pdf is not None: - polarization_map( - Stokes_UV, - Stokes_UV["DATA_MASK"].data.astype(bool), - P_cut=args.p_cut, - SNRi_cut=args.snri, - flux_lim=args.lim, - step_vec=args.step_vec, - scale_vec=args.scale_vec, - savename="_".join([Stokes_UV[0].header["FILENAME"]]), - plots_folder=args.static_pdf, - ) - polarization_map( - Stokes_UV, - Stokes_UV["DATA_MASK"].data.astype(bool), - P_cut=args.p_cut, - SNRi_cut=args.snri, - flux_lim=args.lim, - step_vec=args.step_vec, - scale_vec=args.scale_vec, - savename="_".join([Stokes_UV[0].header["FILENAME"], "I"]), - plots_folder=args.static_pdf, - display="Intensity", - ) - polarization_map( - Stokes_UV, - Stokes_UV["DATA_MASK"].data.astype(bool), - P_cut=args.p_cut, - SNRi_cut=args.snri, - flux_lim=args.lim, - step_vec=args.step_vec, - scale_vec=args.scale_vec, - savename="_".join([Stokes_UV[0].header["FILENAME"], "P_flux"]), - plots_folder=args.static_pdf, - display="Pol_Flux", - ) - polarization_map( - Stokes_UV, - Stokes_UV["DATA_MASK"].data.astype(bool), - P_cut=args.p_cut, - SNRi_cut=args.snri, - flux_lim=args.lim, - step_vec=args.step_vec, - scale_vec=args.scale_vec, - savename="_".join([Stokes_UV[0].header["FILENAME"], "P"]), - plots_folder=args.static_pdf, - display="Pol_deg", - ) - polarization_map( - Stokes_UV, - Stokes_UV["DATA_MASK"].data.astype(bool), - P_cut=args.p_cut, - SNRi_cut=args.snri, - flux_lim=args.lim, - step_vec=args.step_vec, - scale_vec=args.scale_vec, - savename="_".join([Stokes_UV[0].header["FILENAME"], "PA"]), - plots_folder=args.static_pdf, - display="Pol_ang", - ) - polarization_map( - Stokes_UV, - Stokes_UV["DATA_MASK"].data.astype(bool), - P_cut=args.p_cut, - SNRi_cut=args.snri, - flux_lim=args.lim, - step_vec=args.step_vec, - scale_vec=args.scale_vec, - savename="_".join([Stokes_UV[0].header["FILENAME"], "I_err"]), - plots_folder=args.static_pdf, - display="I_err", - ) - polarization_map( - Stokes_UV, - Stokes_UV["DATA_MASK"].data.astype(bool), - P_cut=args.p_cut, - SNRi_cut=args.snri, - flux_lim=args.lim, - step_vec=args.step_vec, - scale_vec=args.scale_vec, - savename="_".join([Stokes_UV[0].header["FILENAME"], "P_err"]), - plots_folder=args.static_pdf, - display="Pol_deg_err", - ) - polarization_map( - Stokes_UV, - Stokes_UV["DATA_MASK"].data.astype(bool), - P_cut=args.p_cut, - SNRi_cut=args.snri, - flux_lim=args.lim, - step_vec=args.step_vec, - scale_vec=args.scale_vec, - savename="_".join([Stokes_UV[0].header["FILENAME"], "SNRi"]), - plots_folder=args.static_pdf, - display="SNRi", - ) - polarization_map( - Stokes_UV, - Stokes_UV["DATA_MASK"].data.astype(bool), - P_cut=args.p_cut if args.p_cut >= 1.0 else 3.0, - SNRi_cut=args.snri, - flux_lim=args.lim, - step_vec=args.step_vec, - scale_vec=args.scale_vec, - savename="_".join([Stokes_UV[0].header["FILENAME"], "SNRp"]), - plots_folder=args.static_pdf, - display="SNRp", - ) - polarization_map( - Stokes_UV, - Stokes_UV["DATA_MASK"].data.astype(bool), - P_cut=args.p_cut if args.p_cut < 1.0 else 0.99, - SNRi_cut=args.snri, - flux_lim=args.lim, - step_vec=args.step_vec, - scale_vec=args.scale_vec, - savename="_".join([Stokes_UV[0].header["FILENAME"], "confP"]), - plots_folder=args.static_pdf, - display="confp", - ) + if args.type is not None: + polarization_map( + Stokes_UV, + Stokes_UV["DATA_MASK"].data.astype(bool), + P_cut=args.pcut, + SNRi_cut=args.snri, + flux_lim=args.lim, + step_vec=args.step_vec, + scale_vec=args.scale_vec, + savename="_".join([Stokes_UV[0].header["FILENAME"], args.type]), + plots_folder=args.static_pdf, + display=args.type, + ) + else: + polarization_map( + Stokes_UV, + Stokes_UV["DATA_MASK"].data.astype(bool), + P_cut=args.pcut, + SNRi_cut=args.snri, + flux_lim=args.lim, + step_vec=args.step_vec, + scale_vec=args.scale_vec, + savename="_".join([Stokes_UV[0].header["FILENAME"]]), + plots_folder=args.static_pdf, + ) + polarization_map( + Stokes_UV, + Stokes_UV["DATA_MASK"].data.astype(bool), + P_cut=args.pcut, + SNRi_cut=args.snri, + flux_lim=args.lim, + step_vec=args.step_vec, + scale_vec=args.scale_vec, + savename="_".join([Stokes_UV[0].header["FILENAME"], "I"]), + plots_folder=args.static_pdf, + display="Intensity", + ) + polarization_map( + Stokes_UV, + Stokes_UV["DATA_MASK"].data.astype(bool), + P_cut=args.pcut, + SNRi_cut=args.snri, + flux_lim=args.lim, + step_vec=args.step_vec, + scale_vec=args.scale_vec, + savename="_".join([Stokes_UV[0].header["FILENAME"], "P_flux"]), + plots_folder=args.static_pdf, + display="Pol_Flux", + ) + polarization_map( + Stokes_UV, + Stokes_UV["DATA_MASK"].data.astype(bool), + P_cut=args.pcut, + SNRi_cut=args.snri, + flux_lim=args.lim, + step_vec=args.step_vec, + scale_vec=args.scale_vec, + savename="_".join([Stokes_UV[0].header["FILENAME"], "P"]), + plots_folder=args.static_pdf, + display="Pol_deg", + ) + polarization_map( + Stokes_UV, + Stokes_UV["DATA_MASK"].data.astype(bool), + P_cut=args.pcut, + SNRi_cut=args.snri, + flux_lim=args.lim, + step_vec=args.step_vec, + scale_vec=args.scale_vec, + savename="_".join([Stokes_UV[0].header["FILENAME"], "PA"]), + plots_folder=args.static_pdf, + display="Pol_ang", + ) + polarization_map( + Stokes_UV, + Stokes_UV["DATA_MASK"].data.astype(bool), + P_cut=args.pcut, + SNRi_cut=args.snri, + flux_lim=args.lim, + step_vec=args.step_vec, + scale_vec=args.scale_vec, + savename="_".join([Stokes_UV[0].header["FILENAME"], "I_err"]), + plots_folder=args.static_pdf, + display="I_err", + ) + polarization_map( + Stokes_UV, + Stokes_UV["DATA_MASK"].data.astype(bool), + P_cut=args.pcut, + SNRi_cut=args.snri, + flux_lim=args.lim, + step_vec=args.step_vec, + scale_vec=args.scale_vec, + savename="_".join([Stokes_UV[0].header["FILENAME"], "P_err"]), + plots_folder=args.static_pdf, + display="Pol_deg_err", + ) + polarization_map( + Stokes_UV, + Stokes_UV["DATA_MASK"].data.astype(bool), + P_cut=args.pcut, + SNRi_cut=args.snri, + flux_lim=args.lim, + step_vec=args.step_vec, + scale_vec=args.scale_vec, + savename="_".join([Stokes_UV[0].header["FILENAME"], "SNRi"]), + plots_folder=args.static_pdf, + display="SNRi", + ) + polarization_map( + Stokes_UV, + Stokes_UV["DATA_MASK"].data.astype(bool), + P_cut=args.pcut if args.pcut >= 1.0 else 3.0, + SNRi_cut=args.snri, + flux_lim=args.lim, + step_vec=args.step_vec, + scale_vec=args.scale_vec, + savename="_".join([Stokes_UV[0].header["FILENAME"], "SNRp"]), + plots_folder=args.static_pdf, + display="SNRp", + ) + polarization_map( + Stokes_UV, + Stokes_UV["DATA_MASK"].data.astype(bool), + P_cut=args.pcut if args.pcut < 1.0 else 0.99, + SNRi_cut=args.snri, + flux_lim=args.lim, + step_vec=args.step_vec, + scale_vec=args.scale_vec, + savename="_".join([Stokes_UV[0].header["FILENAME"], "confP"]), + plots_folder=args.static_pdf, + display="confp", + ) else: - pol_map(Stokes_UV, P_cut=args.p_cut, SNRi_cut=args.snri, step_vec=args.step_vec, scale_vec=args.scale_vec, flux_lim=args.lim, pa_err=args.pang_err) + pol_map(Stokes_UV, P_cut=args.pcut, SNRi_cut=args.snri, step_vec=args.step_vec, scale_vec=args.scale_vec, flux_lim=args.lim, pa_err=args.pang_err, selection=args.type) else: print( "python3 plots.py -f -p -i -st -sc -l -pa --pdf " diff --git a/package/src/emission_center.py b/package/src/emission_center.py index ad3453d..a429526 100755 --- a/package/src/emission_center.py +++ b/package/src/emission_center.py @@ -40,16 +40,16 @@ def main(infile, target=None, output_dir=None): if target is None: target = Stokes[0].header["TARGNAME"] - fig = figure(figsize=(8,9),layout="constrained") + fig = figure(figsize=(8,8),layout="constrained") fig, ax = polarization_map(Stokes, P_cut=0.99, step_vec=2, scale_vec=5, display="i", fig=fig) ax.plot(*Stokescenter, marker="+", color="gray", label="Best confidence for center: {0}".format(Stokespos.to_string("hmsdms"))) - confcentcont = ax.contour(Stokescentconf, [0.01], colors="gray") - confcont = ax.contour(Stokesconf, [0.99], colors="r") + confcentcont = ax.contour(Stokescentconf, [0.001], colors="gray") + confcont = ax.contour(Stokesconf, [0.9905], colors="r") snr3cont = ax.contour(Stokessnr, [3.0], colors="b", linestyles="dashed") snr4cont = ax.contour(Stokessnr, [4.0], colors="b") handles, labels = ax.get_legend_handles_labels() - labels.append(r"Center $Conf_{99\%}$ contour") + labels.append(r"Center $Conf_{99.9\%}$ contour") handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=confcentcont.get_edgecolor()[0])) labels.append(r"Polarization $Conf_{99\%}$ contour") handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=confcont.get_edgecolor()[0])) @@ -61,7 +61,7 @@ def main(infile, target=None, output_dir=None): if output_dir is not None: filename = pathjoin(output_dir, "%s_center.pdf" % target) - fig.savefig(filename, dpi=150, facecolor="None") + fig.savefig(filename, dpi=300, facecolor="None") output.append(filename) show() return output diff --git a/package/src/overplot_MRK463E.py b/package/src/overplot_MRK463E.py index a571a7a..a05bfb0 100755 --- a/package/src/overplot_MRK463E.py +++ b/package/src/overplot_MRK463E.py @@ -10,7 +10,7 @@ from astropy.io import fits from lib.plots import overplot_chandra, overplot_pol from matplotlib.colors import LogNorm -Stokes_UV = fits.open("./data/MRK463E/5960/MRK463E_FOC_b0.05arcsec_c0.07arcsec.fits") +Stokes_UV = fits.open("./data/MRK463E/5960/MRK463E_FOC_b0.05arcsec_c0.10arcsec.fits") Stokes_IR = fits.open("./data/MRK463E/WFPC2/IR_rot_crop.fits") Stokes_Xr = fits.open("./data/MRK463E/Chandra/X_ray_crop.fits") From bd7cad46a1d3cd3bddbba0e650a495e088a00348 Mon Sep 17 00:00:00 2001 From: Thibault Barnouin Date: Thu, 3 Oct 2024 17:12:30 +0200 Subject: [PATCH 11/18] NGC1068 overplot --- package/FOC_reduction.py | 7 +- package/lib/plots.py | 128 +++++++++++++++++++++++--------- package/src/emission_center.py | 20 ++--- package/src/overplot_NGC1068.py | 42 +++++++++++ 4 files changed, 150 insertions(+), 47 deletions(-) create mode 100755 package/src/overplot_NGC1068.py diff --git a/package/FOC_reduction.py b/package/FOC_reduction.py index 58d73c2..e6920d0 100755 --- a/package/FOC_reduction.py +++ b/package/FOC_reduction.py @@ -3,6 +3,7 @@ """ Main script where are progressively added the steps for the FOC pipeline reduction. """ + from pathlib import Path from sys import path as syspath @@ -58,7 +59,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= # Smoothing smoothing_function = "combine" # gaussian_after, weighted_gaussian_after, gaussian, weighted_gaussian or combine - smoothing_FWHM = 0.075 # If None, no smoothing is done + smoothing_FWHM = 0.075 # If None, no smoothing is done smoothing_scale = "arcsec" # pixel or arcsec # Rotation @@ -391,7 +392,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= proj_plots.polarization_map( deepcopy(Stokes_hdul), data_mask, - P_cut=P_cut if P_cut >= 1. else 3., + P_cut=P_cut if P_cut >= 1.0 else 3.0, SNRi_cut=SNRi_cut, flux_lim=flux_lim, step_vec=step_vec, @@ -403,7 +404,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= proj_plots.polarization_map( deepcopy(Stokes_hdul), data_mask, - P_cut=P_cut if P_cut < 1. else 0.99, + P_cut=P_cut if P_cut < 1.0 else 0.99, SNRi_cut=SNRi_cut, flux_lim=flux_lim, step_vec=step_vec, diff --git a/package/lib/plots.py b/package/lib/plots.py index d021094..d4e49df 100755 --- a/package/lib/plots.py +++ b/package/lib/plots.py @@ -225,6 +225,7 @@ def polarization_map( display="default", fig=None, ax=None, + **kwargs, ): """ Plots polarization map from Stokes HDUList. @@ -357,6 +358,47 @@ def polarization_map( ax.coords[0].set_ticklabel_position("t") ax.set_ylabel("Declination (J2000)", labelpad=-1) + vmin, vmax = 0.0, stkI.max() * convert_flux + for key, value in [ + ["cmap", [["cmap", "inferno"]]], + ["width", [["width", 0.5]]], + ["linewidth", [["linewidth", 0.3]]], + ]: + try: + _ = kwargs[key] + except KeyError: + for key_i, val_i in value: + kwargs[key_i] = val_i + if kwargs["cmap"] in [ + "inferno", + "magma", + "Greys_r", + "binary_r", + "gist_yarg_r", + "gist_gray", + "gray", + "bone", + "pink", + "hot", + "afmhot", + "gist_heat", + "copper", + "gist_earth", + "gist_stern", + "gnuplot", + "gnuplot2", + "CMRmap", + "cubehelix", + "nipy_spectral", + "gist_ncar", + "viridis", + ]: + ax.set_facecolor("black") + font_color = "white" + else: + ax.set_facecolor("white") + font_color = "black" + if display.lower() in ["intensity"]: # If no display selected, show intensity map display = "i" @@ -367,7 +409,7 @@ def polarization_map( vmin, vmax = 1.0 / 2.0 * np.median(np.sqrt(stk_cov[0, 0][stkI > 0.0]) * convert_flux), np.max(stkI[stkI > 0.0] * convert_flux) else: vmin, vmax = flux_lim - im = ax.imshow(stkI * convert_flux, norm=LogNorm(vmin, vmax), aspect="equal", cmap="inferno", alpha=1.0) + im = ax.imshow(stkI * convert_flux, norm=LogNorm(vmin, vmax), aspect="equal", cmap=kwargs["cmap"], alpha=1.0) fig.colorbar(im, ax=ax, aspect=30, shrink=0.75, pad=0.025, label=r"$F_{\lambda}$ [$ergs \cdot cm^{-2} \cdot s^{-1} \cdot \AA^{-1}$]") levelsI = np.array([0.8, 2.0, 5.0, 10.0, 20.0, 50.0]) / 100.0 * vmax print("Total flux contour levels : ", levelsI) @@ -382,7 +424,7 @@ def polarization_map( vmin, vmax = 1.0 / 2.0 * np.median(np.sqrt(stk_cov[0, 0][stkI > 0.0]) * convert_flux), np.max(stkI[stkI > 0.0] * convert_flux) else: vmin, vmax = flux_lim - im = ax.imshow(stkI * convert_flux * pol, norm=LogNorm(vmin, vmax), aspect="equal", cmap="inferno", alpha=1.0) + im = ax.imshow(stkI * convert_flux * pol, norm=LogNorm(vmin, vmax), aspect="equal", cmap=kwargs["cmap"], alpha=1.0) fig.colorbar(im, ax=ax, aspect=50, shrink=0.75, pad=0.025, label=r"$F_{\lambda} \cdot P$ [$ergs \cdot cm^{-2} \cdot s^{-1} \cdot \AA^{-1}$]") levelsPf = np.linspace(vmax * 0.01, vmax * 0.99, 10) print("Polarized flux contour levels : ", levelsPf) @@ -391,13 +433,13 @@ def polarization_map( # Display polarization degree map display = "p" vmin, vmax = 0.0, 100.0 - im = ax.imshow(pol * 100.0, vmin=vmin, vmax=vmax, aspect="equal", cmap="inferno", alpha=1.0) + im = ax.imshow(pol * 100.0, vmin=vmin, vmax=vmax, aspect="equal", cmap=kwargs["cmap"], alpha=1.0) fig.colorbar(im, ax=ax, aspect=50, shrink=0.75, pad=0.025, label=r"$P$ [%]") elif display.lower() in ["pa", "pang", "pol_ang"]: # Display polarization degree map display = "pa" vmin, vmax = 0.0, 180.0 - im = ax.imshow(princ_angle(pang), vmin=vmin, vmax=vmax, aspect="equal", cmap="inferno", alpha=1.0) + im = ax.imshow(princ_angle(pang), vmin=vmin, vmax=vmax, aspect="equal", cmap=kwargs["cmap"], alpha=1.0) fig.colorbar(im, ax=ax, aspect=50, shrink=0.75, pad=0.025, label=r"$\theta_P$ [°]") elif display.lower() in ["s_p", "pol_err", "pol_deg_err"]: # Display polarization degree error map @@ -419,37 +461,37 @@ def polarization_map( ) im = ax.imshow(np.sqrt(stk_cov[0, 0]) * convert_flux, norm=LogNorm(vmin, vmax), aspect="equal", cmap="inferno_r", alpha=1.0) else: - im = ax.imshow(np.sqrt(stk_cov[0, 0]) * convert_flux, aspect="equal", cmap="inferno", alpha=1.0) + im = ax.imshow(np.sqrt(stk_cov[0, 0]) * convert_flux, aspect="equal", cmap=kwargs["cmap"], alpha=1.0) fig.colorbar(im, ax=ax, aspect=50, shrink=0.75, pad=0.025, label=r"$\sigma_I$ [$ergs \cdot cm^{-2} \cdot s^{-1} \cdot \AA^{-1}$]") elif display.lower() in ["snri"]: # Display I_stokes signal-to-noise map display = "snri" vmin, vmax = 0.0, np.max(SNRi[np.isfinite(SNRi)]) if vmax * 0.99 > SNRi_cut: - im = ax.imshow(SNRi, vmin=vmin, vmax=vmax, aspect="equal", cmap="inferno", alpha=1.0) + im = ax.imshow(SNRi, vmin=vmin, vmax=vmax, aspect="equal", cmap=kwargs["cmap"], alpha=1.0) levelsSNRi = np.linspace(SNRi_cut, vmax * 0.99, 5).astype(int) print("SNRi contour levels : ", levelsSNRi) ax.contour(SNRi, levels=levelsSNRi, colors="grey", linewidths=0.5) else: - im = ax.imshow(SNRi, aspect="equal", cmap="inferno", alpha=1.0) + im = ax.imshow(SNRi, aspect="equal", cmap=kwargs["cmap"], alpha=1.0) fig.colorbar(im, ax=ax, aspect=50, shrink=0.75, pad=0.025, label=r"$I_{Stokes}/\sigma_{I}$") elif display.lower() in ["snr", "snrp"]: # Display polarization degree signal-to-noise map display = "snrp" vmin, vmax = 0.0, np.max(SNRp[np.isfinite(SNRp)]) if vmax * 0.99 > P_cut: - im = ax.imshow(SNRp, vmin=vmin, vmax=vmax, aspect="equal", cmap="inferno", alpha=1.0) + im = ax.imshow(SNRp, vmin=vmin, vmax=vmax, aspect="equal", cmap=kwargs["cmap"], alpha=1.0) levelsSNRp = np.linspace(P_cut, vmax * 0.99, 5).astype(int) print("SNRp contour levels : ", levelsSNRp) ax.contour(SNRp, levels=levelsSNRp, colors="grey", linewidths=0.5) else: - im = ax.imshow(SNRp, aspect="equal", cmap="inferno", alpha=1.0) + im = ax.imshow(SNRp, aspect="equal", cmap=kwargs["cmap"], alpha=1.0) fig.colorbar(im, ax=ax, aspect=50, shrink=0.75, pad=0.025, label=r"$P/\sigma_{P}$") elif display.lower() in ["conf", "confp"]: # Display polarization degree signal-to-noise map display = "confp" vmin, vmax = 0.0, 1.0 - im = ax.imshow(confP, vmin=vmin, vmax=vmax, aspect="equal", cmap="inferno", alpha=1.0) + im = ax.imshow(confP, vmin=vmin, vmax=vmax, aspect="equal", cmap=kwargs["cmap"], alpha=1.0) levelsconfp = np.array([0.500, 0.900, 0.990, 0.999]) print("confp contour levels : ", levelsconfp) ax.contour(confP, levels=levelsconfp, colors="grey", linewidths=0.5) @@ -460,7 +502,7 @@ def polarization_map( vmin, vmax = 1.0 * np.mean(np.sqrt(stk_cov[0, 0][mask]) * convert_flux), np.max(stkI[stkI > 0.0] * convert_flux) else: vmin, vmax = 1.0 * np.mean(np.sqrt(stk_cov[0, 0][stkI > 0.0]) * convert_flux), np.max(stkI[stkI > 0.0] * convert_flux) - im = ax.imshow(stkI * convert_flux, norm=LogNorm(vmin, vmax), aspect="equal", cmap="inferno", alpha=1.0) + im = ax.imshow(stkI * convert_flux, norm=LogNorm(vmin, vmax), aspect="equal", cmap=kwargs["cmap"], alpha=1.0) fig.colorbar(im, ax=ax, aspect=50, shrink=0.75, pad=0.025, label=r"$F_{\lambda}$ [$ergs \cdot cm^{-2} \cdot s^{-1} \cdot \AA$]") # Get integrated values from header @@ -474,7 +516,7 @@ def polarization_map( plt.rcParams.update({"font.size": 10}) px_size = wcs.wcs.get_cdelt()[0] * 3600.0 - px_sc = AnchoredSizeBar(ax.transData, 1.0 / px_size, "1 arcsec", 3, pad=0.25, sep=5, borderpad=0.25, frameon=False, size_vertical=0.005, color="w") + px_sc = AnchoredSizeBar(ax.transData, 1.0 / px_size, "1 arcsec", 3, pad=0.25, sep=5, borderpad=0.25, frameon=False, size_vertical=0.005, color=font_color) north_dir = AnchoredDirectionArrows( ax.transAxes, "E", @@ -489,8 +531,8 @@ def polarization_map( head_length=10.0, head_width=10.0, angle=-Stokes[0].header["orientat"], - text_props={"ec": "k", "fc": "w", "alpha": 1, "lw": 0.4}, - arrow_props={"ec": "k", "fc": "w", "alpha": 1, "lw": 1}, + text_props={"ec": "k", "fc": font_color, "alpha": 1, "lw": 0.4}, + arrow_props={"ec": "k", "fc": font_color, "alpha": 1, "lw": 1}, ) if display.lower() in ["i", "s_i", "snri", "pf", "p", "pa", "s_p", "snrp", "confp"]: @@ -513,12 +555,14 @@ def polarization_map( headwidth=0.0, headlength=0.0, headaxislength=0.0, - width=0.5, - linewidth=0.75, + width=kwargs["width"], + linewidth=kwargs["linewidth"], color="w", edgecolor="k", ) - pol_sc = AnchoredSizeBar(ax.transData, scale_vec, r"$P$= 100 %", 4, pad=0.25, sep=5, borderpad=0.25, frameon=False, size_vertical=0.005, color="w") + pol_sc = AnchoredSizeBar( + ax.transData, scale_vec, r"$P$= 100 %", 4, pad=0.25, sep=5, borderpad=0.25, frameon=False, size_vertical=0.005, color=font_color + ) ax.add_artist(pol_sc) ax.add_artist(px_sc) @@ -1302,7 +1346,7 @@ class overplot_pol(align_maps): Inherit from class align_maps in order to get the same WCS on both maps. """ - def overplot(self, levels=None, P_cut=0.99, SNRi_cut=1.0, scale_vec=2.0, savename=None, **kwargs): + def overplot(self, levels=None, P_cut=0.99, SNRi_cut=1.0, scale_vec=2.0, step_vec=1, savename=None, **kwargs): self.Stokes_UV = self.map self.wcs_UV = self.map_wcs # Get Data @@ -1339,8 +1383,8 @@ class overplot_pol(align_maps): plt.rcParams.update({"font.size": 16}) ratiox = max(int(stkI.shape[1] / stkI.shape[0]), 1) ratioy = max(int(stkI.shape[0] / stkI.shape[1]), 1) - px_scale = self.wcs_UV.wcs.get_cdelt()[0] / self.other_wcs.wcs.get_cdelt()[0] - self.fig_overplot, self.ax_overplot = plt.subplots(figsize=(10 * ratiox, 10 * ratioy), subplot_kw=dict(projection=self.other_wcs)) + self.px_scale = self.wcs_UV.wcs.get_cdelt()[0] / self.other_wcs.wcs.get_cdelt()[0] + self.fig_overplot, self.ax_overplot = plt.subplots(figsize=(10 * ratiox, 12 * ratioy), subplot_kw=dict(projection=self.other_wcs)) self.fig_overplot.subplots_adjust(hspace=0, wspace=0, bottom=0.1, left=0.1, top=0.80, right=1.02) self.ax_overplot.set_xlabel(label="Right Ascension (J2000)") @@ -1357,8 +1401,8 @@ class overplot_pol(align_maps): for key, value in [ ["cmap", [["cmap", "inferno"]]], ["norm", [["vmin", vmin], ["vmax", vmax]]], - ["width", [["width", 0.5 * px_scale]]], - ["linewidth", [["linewidth", 0.3 * px_scale]]], + ["width", [["width", 0.5 * self.px_scale]]], + ["linewidth", [["linewidth", 0.3 * self.px_scale]]], ]: try: _ = kwargs[key] @@ -1403,11 +1447,10 @@ class overplot_pol(align_maps): # Display full size polarization vectors if scale_vec is None: - self.scale_vec = 2.0 * px_scale + self.scale_vec = 2.0 * self.px_scale pol[np.isfinite(pol)] = 1.0 / 2.0 else: - self.scale_vec = scale_vec * px_scale - step_vec = 1 + self.scale_vec = scale_vec * self.px_scale self.X, self.Y = np.meshgrid(np.arange(stkI.shape[1]), np.arange(stkI.shape[0])) self.U, self.V = pol * np.cos(np.pi / 2.0 + pang * np.pi / 180.0), pol * np.sin(np.pi / 2.0 + pang * np.pi / 180.0) self.Q = self.ax_overplot.quiver( @@ -1518,18 +1561,18 @@ class overplot_pol(align_maps): while not self.aligned: self.align() self.overplot(levels=levels, P_cut=P_cut, SNRi_cut=SNRi_cut, scale_vec=scale_vec, savename=savename, **kwargs) - plt.show(block=True) def add_vector(self, position="center", pol_deg=1.0, pol_ang=0.0, **kwargs): - if position == "center": + if isinstance(position, str) and position == "center": position = np.array(self.X.shape) / 2.0 if isinstance(position, SkyCoord): position = self.other_wcs.world_to_pixel(position) u, v = pol_deg * np.cos(np.radians(pol_ang) + np.pi / 2.0), pol_deg * np.sin(np.radians(pol_ang) + np.pi / 2.0) for key, value in [ - ["scale", [["scale", self.scale_vec]]], - ["width", [["width", 0.1]]], + ["scale", [["scale", 1.0 / self.scale_vec]]], + ["width", [["width", 0.5 * self.px_scale]]], + ["linewidth", [["linewidth", 0.3 * self.px_scale]]], ["color", [["color", "k"]]], ["edgecolor", [["edgecolor", "w"]]], ]: @@ -1540,7 +1583,17 @@ class overplot_pol(align_maps): kwargs[key_i] = val_i handles, labels = self.legend.legend_handles, [l.get_text() for l in self.legend.texts] new_vec = self.ax_overplot.quiver( - *position, u, v, units="xy", angles="uv", scale_units="xy", pivot="mid", headwidth=0.0, headlength=0.0, headaxislength=0.0, **kwargs + *position, + u, + v, + units="xy", + angles="uv", + scale_units="xy", + pivot="mid", + headwidth=0.0, + headlength=0.0, + headaxislength=0.0, + **kwargs, ) handles.append(FancyArrowPatch((0, 0), (0, 1), arrowstyle="-", fc=new_vec.get_fc(), ec=new_vec.get_ec())) labels.append(new_vec.get_label()) @@ -3355,9 +3408,7 @@ if __name__ == "__main__": parser.add_argument( "-pdf", "--static-pdf", metavar="static_pdf", required=False, help="Whether the analysis tool or the static pdfs should be outputed", default=None ) - parser.add_argument( - "-t", "--type", metavar="type", required=False, help="Type of plot to be be outputed", default=None - ) + parser.add_argument("-t", "--type", metavar="type", required=False, help="Type of plot to be be outputed", default=None) args = parser.parse_args() if args.file is not None: @@ -3497,7 +3548,16 @@ if __name__ == "__main__": display="confp", ) else: - pol_map(Stokes_UV, P_cut=args.pcut, SNRi_cut=args.snri, step_vec=args.step_vec, scale_vec=args.scale_vec, flux_lim=args.lim, pa_err=args.pang_err, selection=args.type) + pol_map( + Stokes_UV, + P_cut=args.pcut, + SNRi_cut=args.snri, + step_vec=args.step_vec, + scale_vec=args.scale_vec, + flux_lim=args.lim, + pa_err=args.pang_err, + selection=args.type, + ) else: print( "python3 plots.py -f -p -i -st -sc -l -pa --pdf " diff --git a/package/src/emission_center.py b/package/src/emission_center.py index a429526..8f9142d 100755 --- a/package/src/emission_center.py +++ b/package/src/emission_center.py @@ -40,23 +40,23 @@ def main(infile, target=None, output_dir=None): if target is None: target = Stokes[0].header["TARGNAME"] - fig = figure(figsize=(8,8),layout="constrained") - fig, ax = polarization_map(Stokes, P_cut=0.99, step_vec=2, scale_vec=5, display="i", fig=fig) + fig = figure(figsize=(8, 8.5), layout="constrained") + fig, ax = polarization_map(Stokes, P_cut=0.99, step_vec=1, scale_vec=3, display="i", fig=fig, width=0.33, linewidth=0.5) ax.plot(*Stokescenter, marker="+", color="gray", label="Best confidence for center: {0}".format(Stokespos.to_string("hmsdms"))) - confcentcont = ax.contour(Stokescentconf, [0.001], colors="gray") + confcentcont = ax.contour(Stokescentconf, [0.01], colors="gray") confcont = ax.contour(Stokesconf, [0.9905], colors="r") - snr3cont = ax.contour(Stokessnr, [3.0], colors="b", linestyles="dashed") - snr4cont = ax.contour(Stokessnr, [4.0], colors="b") + # snr3cont = ax.contour(Stokessnr, [3.0], colors="b", linestyles="dashed") + # snr4cont = ax.contour(Stokessnr, [4.0], colors="b") handles, labels = ax.get_legend_handles_labels() - labels.append(r"Center $Conf_{99.9\%}$ contour") + labels.append(r"Center $Conf_{99\%}$ contour") handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=confcentcont.get_edgecolor()[0])) labels.append(r"Polarization $Conf_{99\%}$ contour") handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=confcont.get_edgecolor()[0])) - labels.append(r"$SNR_P \geq$ 3 contour") - handles.append(Rectangle((0, 0), 1, 1, fill=False, ls="--", ec=snr3cont.get_edgecolor()[0])) - labels.append(r"$SNR_P \geq$ 4 contour") - handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=snr4cont.get_edgecolor()[0])) + # labels.append(r"$SNR_P \geq$ 3 contour") + # handles.append(Rectangle((0, 0), 1, 1, fill=False, ls="--", ec=snr3cont.get_edgecolor()[0])) + # labels.append(r"$SNR_P \geq$ 4 contour") + # handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=snr4cont.get_edgecolor()[0])) ax.legend(handles=handles, labels=labels, bbox_to_anchor=(0.0, -0.02, 1.0, 0.01), loc="upper left", mode="expand", borderaxespad=0.0) if output_dir is not None: diff --git a/package/src/overplot_NGC1068.py b/package/src/overplot_NGC1068.py new file mode 100755 index 0000000..fa4f31f --- /dev/null +++ b/package/src/overplot_NGC1068.py @@ -0,0 +1,42 @@ +#!/usr/bin/python3 +# -*- coding:utf-8 -*- +from pathlib import Path +from sys import path as syspath + +syspath.append(str(Path(__file__).parent.parent)) + +import numpy as np +from astropy.io import fits +from lib.plots import overplot_pol, plt +from matplotlib.colors import LogNorm + +Stokes_UV = fits.open("./data/NGC1068/5144/NGC1068_FOC_b0.05arcsec_c0.07arcsec_crop.fits") +Radio = fits.open("./data/NGC1068/MERLIN-VLA/Combined_crop.fits") + +levels = np.logspace(-0.5, 1.99, 7) / 100.0 * Stokes_UV[0].data.max() * Stokes_UV[0].header["photflam"] +A = overplot_pol(Stokes_UV, Radio, norm=LogNorm()) +A.plot( + levels=levels, + P_cut=0.99, + SNRi_cut=1.0, + scale_vec=3, + step_vec=1, + norm=LogNorm(5e-5, 1e-1), + cmap="inferno_r", + width=0.8, + linewidth=1.2, +) +A.add_vector( + A.other_wcs.celestial.wcs.crpix - (1.0, 1.0), + pol_deg=0.124, + pol_ang=100.7, + width=2, + linewidth=2, + scale=1.0 / (A.px_scale * 6.0), + edgecolor="b", + color="b", + label=r"IXPE torus: P = $12.4 (\pm 3.6)$%, PA = $100.7 (\pm 8.3)$°", +) +A.fig_overplot.savefig("./plots/NGC1068/NGC1068_radio_overplot_full.pdf", dpi=300, bbox_inches="tight") +plt.show() +A.write_to(path1="./data/NGC1068/FOC_Radio.fits", path2="./data/NGC1068/Radio_FOC.fits", suffix="aligned") From f6d62bff734ebc115ad68beb4bc15daa6bce3eb8 Mon Sep 17 00:00:00 2001 From: Thibault Barnouin Date: Thu, 17 Oct 2024 17:05:35 +0200 Subject: [PATCH 12/18] small fixes and improvments --- README.md | 4 + doc/pipeline.pdf | Bin 0 -> 377764 bytes package/FOC_reduction.py | 134 ++++++-------------------------- package/lib/plots.py | 60 ++++++++------ package/src/Combine.py | 6 +- package/src/overplot_IC5063.py | 48 ++++++------ package/src/overplot_MRK463E.py | 35 ++++++--- package/src/overplot_NGC1068.py | 6 +- 8 files changed, 119 insertions(+), 174 deletions(-) create mode 100644 doc/pipeline.pdf diff --git a/README.md b/README.md index 1731062..3fe06c9 100755 --- a/README.md +++ b/README.md @@ -1,2 +1,6 @@ # FOC_Reduction FOC reduction pipeline + +TODO: + - Add all polarimetry capables instruments from HST (starting with FOS and ACS) + - Build science case for future UV polarimeters (AGN outflow geometry, dust scattering, torus outline ?) diff --git a/doc/pipeline.pdf b/doc/pipeline.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d6e7e052df75ae18376deb83d6c461745d4e5f0e GIT binary patch literal 377764 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�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 z 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

u9wkbtIF`-2u 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�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

~<^+;g&alyb=}XAtr_0hK>^#S0 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 Vevb$i4i07}c6iXADt{1%|6dndbe8}C literal 0 HcmV?d00001 diff --git a/package/FOC_reduction.py b/package/FOC_reduction.py index e6920d0..42a7bab 100755 --- a/package/FOC_reduction.py +++ b/package/FOC_reduction.py @@ -41,8 +41,8 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= # Background estimation error_sub_type = "freedman-diaconis" # sqrt, sturges, rice, scott, freedman-diaconis (default) or shape (example (51, 51)) - subtract_error = 0.5 - display_bkg = False + subtract_error = 1.0 + display_bkg = True # Data binning pxsize = 0.05 @@ -51,7 +51,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= # Alignement align_center = "center" # If None will not align the images - display_align = False + display_align = True display_data = False # Transmittance correction @@ -176,6 +176,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= proj_plots.plot_obs( data_array, headers, + shifts=shifts, savename="_".join([figname, str(align_center)]), plots_folder=plots_folder, norm=LogNorm(vmin=data_array[data_array > 0.0].min() * headers[0]["photflam"], vmax=data_array[data_array > 0.0].max() * headers[0]["photflam"]), @@ -305,114 +306,25 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= savename="_".join([figname]), plots_folder=plots_folder, ) - proj_plots.polarization_map( - deepcopy(Stokes_hdul), - data_mask, - P_cut=P_cut, - SNRi_cut=SNRi_cut, - flux_lim=flux_lim, - step_vec=step_vec, - scale_vec=scale_vec, - savename="_".join([figname, "I"]), - plots_folder=plots_folder, - display="Intensity", - ) - proj_plots.polarization_map( - deepcopy(Stokes_hdul), - data_mask, - P_cut=P_cut, - SNRi_cut=SNRi_cut, - flux_lim=flux_lim, - step_vec=step_vec, - scale_vec=scale_vec, - savename="_".join([figname, "P_flux"]), - plots_folder=plots_folder, - display="Pol_Flux", - ) - proj_plots.polarization_map( - deepcopy(Stokes_hdul), - data_mask, - P_cut=P_cut, - SNRi_cut=SNRi_cut, - flux_lim=flux_lim, - step_vec=step_vec, - scale_vec=scale_vec, - savename="_".join([figname, "P"]), - plots_folder=plots_folder, - display="Pol_deg", - ) - proj_plots.polarization_map( - deepcopy(Stokes_hdul), - data_mask, - P_cut=P_cut, - SNRi_cut=SNRi_cut, - flux_lim=flux_lim, - step_vec=step_vec, - scale_vec=scale_vec, - savename="_".join([figname, "PA"]), - plots_folder=plots_folder, - display="Pol_ang", - ) - proj_plots.polarization_map( - deepcopy(Stokes_hdul), - data_mask, - P_cut=P_cut, - SNRi_cut=SNRi_cut, - flux_lim=flux_lim, - step_vec=step_vec, - scale_vec=scale_vec, - savename="_".join([figname, "I_err"]), - plots_folder=plots_folder, - display="I_err", - ) - proj_plots.polarization_map( - deepcopy(Stokes_hdul), - data_mask, - P_cut=P_cut, - SNRi_cut=SNRi_cut, - flux_lim=flux_lim, - step_vec=step_vec, - scale_vec=scale_vec, - savename="_".join([figname, "P_err"]), - plots_folder=plots_folder, - display="Pol_deg_err", - ) - proj_plots.polarization_map( - deepcopy(Stokes_hdul), - data_mask, - P_cut=P_cut, - SNRi_cut=SNRi_cut, - flux_lim=flux_lim, - step_vec=step_vec, - scale_vec=scale_vec, - savename="_".join([figname, "SNRi"]), - plots_folder=plots_folder, - display="SNRi", - ) - proj_plots.polarization_map( - deepcopy(Stokes_hdul), - data_mask, - P_cut=P_cut if P_cut >= 1.0 else 3.0, - SNRi_cut=SNRi_cut, - flux_lim=flux_lim, - step_vec=step_vec, - scale_vec=scale_vec, - savename="_".join([figname, "SNRp"]), - plots_folder=plots_folder, - display="SNRp", - ) - proj_plots.polarization_map( - deepcopy(Stokes_hdul), - data_mask, - P_cut=P_cut if P_cut < 1.0 else 0.99, - SNRi_cut=SNRi_cut, - flux_lim=flux_lim, - step_vec=step_vec, - scale_vec=scale_vec, - savename="_".join([figname, "confP"]), - plots_folder=plots_folder, - display="confp", - ) + for figtype, figsuffix in zip( + ["Intensity", "Pol_flux", "Pol_deg", "Pol_ang", "I_err", "P_err", "SNRi", "SNRp", "confp"], + ["I", "P_flux", "P", "PA", "I_err", "P_err", "SNRi", "SNRp", "confP"], + ): + try: + proj_plots.polarization_map( + deepcopy(Stokes_hdul), + data_mask, + P_cut=P_cut, + SNRi_cut=SNRi_cut, + flux_lim=flux_lim, + step_vec=step_vec, + scale_vec=scale_vec, + savename="_".join([figname, figsuffix]), + plots_folder=plots_folder, + display=figtype, + ) + except ValueError: + pass elif not interactive: proj_plots.polarization_map( deepcopy(Stokes_hdul), data_mask, P_cut=P_cut, SNRi_cut=SNRi_cut, savename=figname, plots_folder=plots_folder, display="integrate" diff --git a/package/lib/plots.py b/package/lib/plots.py index d4e49df..12e3b2e 100755 --- a/package/lib/plots.py +++ b/package/lib/plots.py @@ -66,7 +66,7 @@ except ImportError: from utils import PCconf, princ_angle, rot2D, sci_not -def plot_obs(data_array, headers, rectangle=None, savename=None, plots_folder="", **kwargs): +def plot_obs(data_array, headers, rectangle=None, shifts=None, savename=None, plots_folder="", **kwargs): """ Plots raw observation imagery with some information on the instrument and filters. @@ -77,16 +77,14 @@ def plot_obs(data_array, headers, rectangle=None, savename=None, plots_folder="" single observation with multiple polarizers of an instrument headers : header list List of headers corresponding to the images in data_array - vmin : float, optional - Min pixel value that should be displayed. - Defaults to 0. - vmax : float, optional - Max pixel value that should be displayed. - Defaults to 6. rectangle : numpy.ndarray, optional Array of parameters for matplotlib.patches.Rectangle objects that will be displayed on each output image. If None, no rectangle displayed. Defaults to None. + shifts : numpy.ndarray, optional + Array of vector coordinates corresponding to images shifts with respect + to the others. If None, no shifts displayed. + Defaults to None. savename : str, optional Name of the figure the map should be saved to. If None, the map won't be saved (only displayed). @@ -100,6 +98,7 @@ def plot_obs(data_array, headers, rectangle=None, savename=None, plots_folder="" nb_obs = np.max([np.sum([head["filtnam1"] == curr_pol for head in headers]) for curr_pol in ["POL0", "POL60", "POL120"]]) shape = np.array((3, nb_obs)) fig, ax = plt.subplots(shape[0], shape[1], figsize=(3 * shape[1], 3 * shape[0]), layout="constrained", sharex=True, sharey=True) + used = np.zeros(shape, dtype=bool) r_pol = dict(pol0=0, pol60=1, pol120=2) c_pol = dict(pol0=0, pol60=0, pol120=0) for i, (data, head) in enumerate(zip(data_array, headers)): @@ -112,15 +111,17 @@ def plot_obs(data_array, headers, rectangle=None, savename=None, plots_folder="" c_pol[filt.lower()] += 1 if shape[1] != 1: ax_curr = ax[r_ax][c_ax] + used[r_ax][c_ax] = True else: ax_curr = ax[r_ax] + ax_curr[r_ax] = True # plots if "vmin" in kwargs.keys() or "vmax" in kwargs.keys(): vmin, vmax = kwargs["vmin"], kwargs["vmax"] del kwargs["vmin"], kwargs["vmax"] else: vmin, vmax = convert * data[data > 0.0].min() / 10.0, convert * data[data > 0.0].max() - for key, value in [["cmap", [["cmap", "gray"]]], ["norm", [["norm", LogNorm(vmin, vmax)]]]]: + for key, value in [["cmap", [["cmap", "inferno"]]], ["norm", [["norm", LogNorm(vmin, vmax)]]]]: try: _ = kwargs[key] except KeyError: @@ -129,17 +130,29 @@ def plot_obs(data_array, headers, rectangle=None, savename=None, plots_folder="" # im = ax[r_ax][c_ax].imshow(convert*data, origin='lower', **kwargs) data[data * convert < vmin * 10.0] = vmin * 10.0 / convert im = ax_curr.imshow(convert * data, origin="lower", **kwargs) + if shifts is not None: + x, y = np.array(data.shape[::-1]) / 2.0 - shifts[i] + dx, dy = shifts[i] + ax_curr.arrow(x, y, dx, dy, length_includes_head=True, width=0.1, head_width=0.3, color="g") + ax_curr.plot([x, x], [0, data.shape[0] - 1], "--", lw=2, color="g", alpha=0.85) + ax_curr.plot([0, data.shape[1] - 1], [y, y], "--", lw=2, color="g", alpha=0.85) if rectangle is not None: x, y, width, height, angle, color = rectangle[i] ax_curr.add_patch(Rectangle((x, y), width, height, angle=angle, edgecolor=color, fill=False)) # position of centroid - ax_curr.plot([data.shape[1] / 2, data.shape[1] / 2], [0, data.shape[0] - 1], "--", lw=1, color="grey", alpha=0.5) - ax_curr.plot([0, data.shape[1] - 1], [data.shape[1] / 2, data.shape[1] / 2], "--", lw=1, color="grey", alpha=0.5) + ax_curr.plot([data.shape[1] / 2, data.shape[1] / 2], [0, data.shape[0] - 1], "--", lw=2, color="b", alpha=0.85) + ax_curr.plot([0, data.shape[1] - 1], [data.shape[0] / 2, data.shape[0] / 2], "--", lw=2, color="b", alpha=0.85) ax_curr.annotate( - instr + ":" + rootname, color="white", fontsize=5, xy=(0.01, 1.00), xycoords="axes fraction", verticalalignment="top", horizontalalignment="left" + instr + ":" + rootname, color="white", fontsize=10, xy=(0.01, 1.00), xycoords="axes fraction", verticalalignment="top", horizontalalignment="left" ) - ax_curr.annotate(filt, color="white", fontsize=10, xy=(0.01, 0.01), xycoords="axes fraction", verticalalignment="bottom", horizontalalignment="left") - ax_curr.annotate(exptime, color="white", fontsize=5, xy=(1.00, 0.01), xycoords="axes fraction", verticalalignment="bottom", horizontalalignment="right") + ax_curr.annotate(filt, color="white", fontsize=15, xy=(0.01, 0.01), xycoords="axes fraction", verticalalignment="bottom", horizontalalignment="left") + ax_curr.annotate( + exptime, color="white", fontsize=10, xy=(1.00, 0.01), xycoords="axes fraction", verticalalignment="bottom", horizontalalignment="right" + ) + unused = np.logical_not(used) + ii, jj = np.indices(shape) + for i, j in zip(ii[unused], jj[unused]): + fig.delaxes(ax[i][j]) # fig.subplots_adjust(hspace=0.01, wspace=0.01, right=1.02) fig.colorbar(im, ax=ax, location="right", shrink=0.75, aspect=50, pad=0.025, label=r"Flux [$ergs \cdot cm^{-2} \cdot s^{-1} \cdot \AA^{-1}$]") @@ -349,7 +362,7 @@ def polarization_map( fig = plt.figure(figsize=(7 * ratiox, 7 * ratioy), layout="constrained") if ax is None: ax = fig.add_subplot(111, projection=wcs) - ax.set(aspect="equal", fc="k", ylim=[-stkI.shape[0] * 0.10, stkI.shape[0] * 1.15]) + ax.set(aspect="equal", fc="k", ylim=[-stkI.shape[0] * 0.01, stkI.shape[0] * 1.01]) # fig.subplots_adjust(hspace=0, wspace=0, left=0.102, right=1.02) # ax.coords.grid(True, color='white', ls='dotted', alpha=0.5) @@ -677,7 +690,7 @@ class align_maps(object): except KeyError: for key_i, val_i in value: kwargs[key_i] = val_i - self.map_ax.imshow(self.map_data * self.map_convert, aspect="equal", **kwargs) + self.im = self.map_ax.imshow(self.map_data * self.map_convert, aspect="equal", **kwargs) if kwargs["cmap"] in [ "inferno", @@ -766,7 +779,7 @@ class align_maps(object): except KeyError: for key_i, val_i in value: other_kwargs[key_i] = val_i - self.other_ax.imshow(self.other_data * self.other_convert, aspect="equal", **other_kwargs) + self.other_im = self.other_ax.imshow(self.other_data * self.other_convert, aspect="equal", **other_kwargs) px_size2 = self.other_wcs.wcs.get_cdelt()[0] * 3600.0 px_sc2 = AnchoredSizeBar( @@ -1561,6 +1574,7 @@ class overplot_pol(align_maps): while not self.aligned: self.align() self.overplot(levels=levels, P_cut=P_cut, SNRi_cut=SNRi_cut, scale_vec=scale_vec, savename=savename, **kwargs) + plt.show(block=True) def add_vector(self, position="center", pol_deg=1.0, pol_ang=0.0, **kwargs): if isinstance(position, str) and position == "center": @@ -2148,7 +2162,7 @@ class image_lasso_selector(object): self.mask = np.zeros(self.img.shape[:2], dtype=bool) self.mask[self.indices] = True if hasattr(self, "cont"): - for coll in self.cont: + for coll in self.cont.collections: coll.remove() self.cont = self.ax.contour(self.mask.astype(float), levels=[0.5], colors="white", linewidths=1) if not self.embedded: @@ -2261,7 +2275,7 @@ class slit(object): for p in self.pix: self.mask[tuple(p)] = (np.abs(np.dot(rot2D(-self.angle), p - self.rect.get_center()[::-1])) < (self.height / 2.0, self.width / 2.0)).all() if hasattr(self, "cont"): - for coll in self.cont: + for coll in self.cont.collections: try: coll.remove() except AttributeError: @@ -2364,7 +2378,7 @@ class aperture(object): x0, y0 = self.circ.center self.mask = np.sqrt((xx - x0) ** 2 + (yy - y0) ** 2) < self.radius if hasattr(self, "cont"): - for coll in self.cont: + for coll in self.cont.collections: try: coll.remove() except AttributeError: @@ -2499,7 +2513,7 @@ class pol_map(object): self.selected = False self.region = deepcopy(self.select_instance.mask.astype(bool)) self.select_instance.displayed.remove() - for coll in self.select_instance.cont: + for coll in self.select_instance.cont.collections: coll.remove() self.select_instance.lasso.set_active(False) self.set_data_mask(deepcopy(self.region)) @@ -2543,7 +2557,7 @@ class pol_map(object): self.select_instance.update_mask() self.region = deepcopy(self.select_instance.mask.astype(bool)) self.select_instance.displayed.remove() - for coll in self.select_instance.cont: + for coll in self.select_instance.cont.collections: coll.remove() self.select_instance.circ.set_visible(False) self.set_data_mask(deepcopy(self.region)) @@ -2601,7 +2615,7 @@ class pol_map(object): self.select_instance.update_mask() self.region = deepcopy(self.select_instance.mask.astype(bool)) self.select_instance.displayed.remove() - for coll in self.select_instance.cont: + for coll in self.select_instance.cont.collections: coll.remove() self.select_instance.rect.set_visible(False) self.set_data_mask(deepcopy(self.region)) @@ -3324,7 +3338,7 @@ class pol_map(object): ) if hasattr(self, "cont"): - for coll in self.cont: + for coll in self.cont.collections: try: coll.remove() except AttributeError: diff --git a/package/src/Combine.py b/package/src/Combine.py index 87b9632..59bc2ce 100755 --- a/package/src/Combine.py +++ b/package/src/Combine.py @@ -173,7 +173,7 @@ def main(infiles, target=None, output_dir="./data/"): # Reduction parameters kwargs = {} # Polarization map output - kwargs["SNRp_cut"] = 3.0 + kwargs["P_cut"] = 0.99 kwargs["SNRi_cut"] = 1.0 kwargs["flux_lim"] = 1e-19, 3e-17 kwargs["scale_vec"] = 5 @@ -186,9 +186,7 @@ def main(infiles, target=None, output_dir="./data/"): new_infiles = [] for i, group in enumerate(grouped_infiles): - new_infiles.append( - FOC_reduction(target=target + "-" + str(i + 1), infiles=["/".join([data_folder, file]) for file in group], interactive=True)[0] - ) + new_infiles.append(FOC_reduction(target=target + "-" + str(i + 1), infiles=["/".join([data_folder, file]) for file in group], interactive=True)[0]) infiles = new_infiles diff --git a/package/src/overplot_IC5063.py b/package/src/overplot_IC5063.py index f9ac6c3..1d58c88 100755 --- a/package/src/overplot_IC5063.py +++ b/package/src/overplot_IC5063.py @@ -11,46 +11,46 @@ from lib.plots import overplot_pol, overplot_radio from matplotlib.colors import LogNorm Stokes_UV = fits.open("./data/IC5063/5918/IC5063_FOC_b0.10arcsec_c0.20arcsec.fits") -Stokes_18GHz = fits.open("./data/IC5063/radio/IC5063_18GHz.fits") -Stokes_24GHz = fits.open("./data/IC5063/radio/IC5063_24GHz.fits") -Stokes_103GHz = fits.open("./data/IC5063/radio/IC5063_103GHz.fits") -Stokes_229GHz = fits.open("./data/IC5063/radio/IC5063_229GHz.fits") -Stokes_357GHz = fits.open("./data/IC5063/radio/IC5063_357GHz.fits") +# Stokes_18GHz = fits.open("./data/IC5063/radio/IC5063_18GHz.fits") +# Stokes_24GHz = fits.open("./data/IC5063/radio/IC5063_24GHz.fits") +# Stokes_103GHz = fits.open("./data/IC5063/radio/IC5063_103GHz.fits") +# Stokes_229GHz = fits.open("./data/IC5063/radio/IC5063_229GHz.fits") +# Stokes_357GHz = fits.open("./data/IC5063/radio/IC5063_357GHz.fits") # Stokes_S2 = fits.open("./data/IC5063/POLARIZATION_COMPARISON/S2_rot_crop.fits") Stokes_IR = fits.open("./data/IC5063/IR/u2e65g01t_c0f_rot.fits") # levelsMorganti = np.array([1.,2.,3.,8.,16.,32.,64.,128.]) -levelsMorganti = np.logspace(-0.1249, 1.97, 7) / 100.0 +# levelsMorganti = np.logspace(-0.1249, 1.97, 7) / 100.0 -levels18GHz = levelsMorganti * Stokes_18GHz[0].data.max() -A = overplot_radio(Stokes_UV, Stokes_18GHz) -A.plot(levels=levels18GHz, P_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/18GHz_overplot.pdf", scale_vec=None) +# levels18GHz = levelsMorganti * Stokes_18GHz[0].data.max() +# A = overplot_radio(Stokes_UV, Stokes_18GHz) +# A.plot(levels=levels18GHz, P_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/18GHz_overplot.pdf", scale_vec=None) -levels24GHz = levelsMorganti * Stokes_24GHz[0].data.max() -B = overplot_radio(Stokes_UV, Stokes_24GHz) -B.plot(levels=levels24GHz, P_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/24GHz_overplot.pdf", scale_vec=None) +# levels24GHz = levelsMorganti * Stokes_24GHz[0].data.max() +# B = overplot_radio(Stokes_UV, Stokes_24GHz) +# B.plot(levels=levels24GHz, P_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/24GHz_overplot.pdf", scale_vec=None) -levels103GHz = levelsMorganti * Stokes_103GHz[0].data.max() -C = overplot_radio(Stokes_UV, Stokes_103GHz) -C.plot(levels=levels103GHz, P_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/103GHz_overplot.pdf", scale_vec=None) +# levels103GHz = levelsMorganti * Stokes_103GHz[0].data.max() +# C = overplot_radio(Stokes_UV, Stokes_103GHz) +# C.plot(levels=levels103GHz, P_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/103GHz_overplot.pdf", scale_vec=None) -levels229GHz = levelsMorganti * Stokes_229GHz[0].data.max() -D = overplot_radio(Stokes_UV, Stokes_229GHz) -D.plot(levels=levels229GHz, P_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/229GHz_overplot.pdf", scale_vec=None) +# levels229GHz = levelsMorganti * Stokes_229GHz[0].data.max() +# D = overplot_radio(Stokes_UV, Stokes_229GHz) +# D.plot(levels=levels229GHz, P_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/229GHz_overplot.pdf", scale_vec=None) -levels357GHz = levelsMorganti * Stokes_357GHz[0].data.max() -E = overplot_radio(Stokes_UV, Stokes_357GHz) -E.plot(levels=levels357GHz, P_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/357GHz_overplot.pdf", scale_vec=None) +# levels357GHz = levelsMorganti * Stokes_357GHz[0].data.max() +# E = overplot_radio(Stokes_UV, Stokes_357GHz) +# E.plot(levels=levels357GHz, P_cut=2.0, SNRi_cut=10.0, savename="./plots/IC5063/357GHz_overplot.pdf", scale_vec=None) # F = overplot_pol(Stokes_UV, Stokes_S2) # F.plot(P_cut=3.0, SNRi_cut=80.0, savename='./plots/IC5063/S2_overplot.pdf', norm=LogNorm(vmin=5e-20,vmax=5e-18)) G = overplot_pol(Stokes_UV, Stokes_IR, cmap="inferno") G.plot( - P_cut=2.0, - SNRi_cut=10.0, + P_cut=0.99, + SNRi_cut=1.0, savename="./plots/IC5063/IR_overplot.pdf", scale_vec=None, norm=LogNorm(Stokes_IR[0].data.max() * Stokes_IR[0].header["photflam"] / 1e3, Stokes_IR[0].data.max() * Stokes_IR[0].header["photflam"]), - cmap="inferno_r", + cmap="inferno", ) diff --git a/package/src/overplot_MRK463E.py b/package/src/overplot_MRK463E.py index a05bfb0..d89845e 100755 --- a/package/src/overplot_MRK463E.py +++ b/package/src/overplot_MRK463E.py @@ -11,16 +11,33 @@ from lib.plots import overplot_chandra, overplot_pol from matplotlib.colors import LogNorm Stokes_UV = fits.open("./data/MRK463E/5960/MRK463E_FOC_b0.05arcsec_c0.10arcsec.fits") -Stokes_IR = fits.open("./data/MRK463E/WFPC2/IR_rot_crop.fits") -Stokes_Xr = fits.open("./data/MRK463E/Chandra/X_ray_crop.fits") +# Stokes_IR = fits.open("./data/MRK463E/WFPC2/IR_rot_crop.fits") +# Stokes_Xr = fits.open("./data/MRK463E/Chandra/X_ray_crop.fits") +Radio = fits.open("./data/MRK463E/EMERLIN/Voorwerpjes_1356+1822_1356+1822_uniform-image.fits") -levels = np.geomspace(1.0, 99.0, 7) +# levels = np.geomspace(1.0, 99.0, 7) -A = overplot_chandra(Stokes_UV, Stokes_Xr, norm=LogNorm()) -A.plot(levels=levels, P_cut=0.99, SNRi_cut=1.0, scale_vec=5, zoom=1, savename="./plots/MRK463E/Chandra_overplot.pdf") -A.write_to(path1="./data/MRK463E/FOC_data_Chandra.fits", path2="./data/MRK463E/Chandra_data.fits", suffix="aligned") +# A = overplot_chandra(Stokes_UV, Stokes_Xr, norm=LogNorm()) +# A.plot(levels=levels, P_cut=0.99, SNRi_cut=1.0, scale_vec=5, zoom=1, savename="./plots/MRK463E/Chandra_overplot.pdf") +# A.write_to(path1="./data/MRK463E/FOC_data_Chandra.fits", path2="./data/MRK463E/Chandra_data.fits", suffix="aligned") + +# levels = np.array([0.8, 2, 5, 10, 20, 50]) / 100.0 * Stokes_UV[0].header["photflam"] +# B = overplot_pol(Stokes_UV, Stokes_IR, norm=LogNorm()) +# B.plot(levels=levels, P_cut=0.99, SNRi_cut=1.0, scale_vec=5, norm=LogNorm(8.5e-18, 2.5e-15), savename="./plots/MRK463E/IR_overplot.pdf") +# B.write_to(path1="./data/MRK463E/FOC_data_WFPC.fits", path2="./data/MRK463E/WFPC_data.fits", suffix="aligned") levels = np.array([0.8, 2, 5, 10, 20, 50]) / 100.0 * Stokes_UV[0].header["photflam"] -B = overplot_pol(Stokes_UV, Stokes_IR, norm=LogNorm()) -B.plot(levels=levels, P_cut=0.99, SNRi_cut=1.0, scale_vec=5, norm=LogNorm(8.5e-18, 2.5e-15), savename="./plots/MRK463E/IR_overplot.pdf") -B.write_to(path1="./data/MRK463E/FOC_data_WFPC.fits", path2="./data/MRK463E/WFPC_data.fits", suffix="aligned") +C = overplot_pol(Stokes_UV, Radio, norm=LogNorm()) +C.other_im.set(norm=LogNorm(1e-4, 2e-2)) +C.plot( + levels=levels, + P_cut=0.999, + SNRi_cut=5.0, + scale_vec=3, + norm=LogNorm(1e-4, 2e-2), + cmap="inferno_r", + width=0.5, + linewidth=0.5, + savename="./plots/MRK463E/EMERLIN_overplot.pdf", +) +C.write_to(path1="./data/MRK463E/FOC_data_EMERLIN.fits", path2="./data/MRK463E/EMERLIN_data.fits", suffix="aligned") diff --git a/package/src/overplot_NGC1068.py b/package/src/overplot_NGC1068.py index fa4f31f..52ca188 100755 --- a/package/src/overplot_NGC1068.py +++ b/package/src/overplot_NGC1068.py @@ -30,10 +30,10 @@ A.add_vector( A.other_wcs.celestial.wcs.crpix - (1.0, 1.0), pol_deg=0.124, pol_ang=100.7, - width=2, - linewidth=2, + width=2.0, + linewidth=1.0, scale=1.0 / (A.px_scale * 6.0), - edgecolor="b", + edgecolor="w", color="b", label=r"IXPE torus: P = $12.4 (\pm 3.6)$%, PA = $100.7 (\pm 8.3)$°", ) From 3f97202a03fc7014b2af5d7a53a9dcaa4cb42bb4 Mon Sep 17 00:00:00 2001 From: Thibault Barnouin Date: Tue, 19 Nov 2024 13:50:23 +0100 Subject: [PATCH 13/18] modify shebang --- package/FOC_reduction.py | 14 +- package/lib/deconvolve.py | 6 +- package/lib/plots.py | 226 +++++++++++++++++++------------- package/lib/query.py | 2 +- package/lib/reduction.py | 6 +- package/src/Combine.py | 2 +- package/src/emission_center.py | 14 +- package/src/get_cdelt.py | 4 +- package/src/overplot_IC5063.py | 2 +- package/src/overplot_MRK463E.py | 13 +- package/src/overplot_NGC1068.py | 2 +- 11 files changed, 173 insertions(+), 118 deletions(-) diff --git a/package/FOC_reduction.py b/package/FOC_reduction.py index 42a7bab..f8986a7 100755 --- a/package/FOC_reduction.py +++ b/package/FOC_reduction.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # -*- coding:utf-8 -*- """ Main script where are progressively added the steps for the FOC pipeline reduction. @@ -30,7 +30,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= # from lib.deconvolve import from_file_psf psf = "gaussian" # Can be user-defined as well # psf = from_file_psf(data_folder+psf_file) - psf_FWHM = 3.1 + psf_FWHM = 1.55 psf_scale = "px" psf_shape = None # (151, 151) iterations = 1 @@ -42,7 +42,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= # Background estimation error_sub_type = "freedman-diaconis" # sqrt, sturges, rice, scott, freedman-diaconis (default) or shape (example (51, 51)) subtract_error = 1.0 - display_bkg = True + display_bkg = False # Data binning pxsize = 0.05 @@ -51,7 +51,7 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= # Alignement align_center = "center" # If None will not align the images - display_align = True + display_align = False display_data = False # Transmittance correction @@ -66,10 +66,10 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= rotate_North = True # Polarization map output - P_cut = 0.99 # if >=1.0 cut on the signal-to-noise else cut on the confidence level in Q, U - SNRi_cut = 1.0 # I measurments with SNR>30, which implies an uncertainty in P of 4.7%. + P_cut = 0.999 # if >=1.0 cut on the signal-to-noise else cut on the confidence level in Q, U + SNRi_cut = 3.0 # I measurments with SNR>30, which implies an uncertainty in P of 4.7%. flux_lim = None # lowest and highest flux displayed on plot, defaults to bkg and maximum in cut if None - scale_vec = 3 + scale_vec = 2 step_vec = 1 # plot all vectors in the array. if step_vec = 2, then every other vector will be plotted if step_vec = 0 then all vectors are displayed at full length # Pipeline start diff --git a/package/lib/deconvolve.py b/package/lib/deconvolve.py index f89eee5..d2afd64 100755 --- a/package/lib/deconvolve.py +++ b/package/lib/deconvolve.py @@ -286,11 +286,13 @@ def richardson_lucy(image, psf, iterations=20, clip=True, filter_epsilon=None): image = image.astype(float_type, copy=False) psf = psf.astype(float_type, copy=False) psf /= psf.sum() - im_deconv = image.copy() + im_deconv = np.full(image.shape, 0.5, dtype=float_type) psf_mirror = np.flip(psf) + eps = 1e-20 + for _ in range(iterations): - conv = convolve(im_deconv, psf, mode="same") + conv = convolve(im_deconv, psf, mode="same") + eps if filter_epsilon: relative_blur = np.where(conv < filter_epsilon, 0, image / conv) else: diff --git a/package/lib/plots.py b/package/lib/plots.py index 12e3b2e..0b908b9 100755 --- a/package/lib/plots.py +++ b/package/lib/plots.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 """ Library functions for displaying informations using matplotlib @@ -270,6 +270,7 @@ def polarization_map( scale_vec : float, optional Pixel length of displayed 100% polarization vector. If scale_vec = 2, a vector of 50% polarization will be 1 pixel wide. + If scale_vec = 0, all polarization vectors will be displayed at full length. Defaults to 2. savename : str, optional Name of the figure the map should be saved to. If None, the map won't @@ -412,7 +413,7 @@ def polarization_map( ax.set_facecolor("white") font_color = "black" - if display.lower() in ["intensity"]: + if display.lower() in ["i", "intensity"]: # If no display selected, show intensity map display = "i" if flux_lim is None: @@ -427,19 +428,22 @@ def polarization_map( levelsI = np.array([0.8, 2.0, 5.0, 10.0, 20.0, 50.0]) / 100.0 * vmax print("Total flux contour levels : ", levelsI) ax.contour(stkI * convert_flux, levels=levelsI, colors="grey", linewidths=0.5) - elif display.lower() in ["pol_flux"]: + elif display.lower() in ["pf", "pol_flux"]: # Display polarization flux display = "pf" if flux_lim is None: if mask.sum() > 0.0: vmin, vmax = 1.0 / 2.0 * np.median(np.sqrt(stk_cov[0, 0][mask]) * convert_flux), np.max(stkI[stkI > 0.0] * convert_flux) + pfmax = (stkI[mask] * pol[mask] * convert_flux).max() else: vmin, vmax = 1.0 / 2.0 * np.median(np.sqrt(stk_cov[0, 0][stkI > 0.0]) * convert_flux), np.max(stkI[stkI > 0.0] * convert_flux) + pfmax = (stkI[stkI > 0.0] * pol[stkI > 0.0] * convert_flux).max() else: vmin, vmax = flux_lim im = ax.imshow(stkI * convert_flux * pol, norm=LogNorm(vmin, vmax), aspect="equal", cmap=kwargs["cmap"], alpha=1.0) fig.colorbar(im, ax=ax, aspect=50, shrink=0.75, pad=0.025, label=r"$F_{\lambda} \cdot P$ [$ergs \cdot cm^{-2} \cdot s^{-1} \cdot \AA^{-1}$]") - levelsPf = np.linspace(vmax * 0.01, vmax * 0.99, 10) + # levelsPf = np.linspace(0.0175, 0.50, 5) * pfmax + levelsPf = np.array([1.73, 13.0, 33.0, 66.0]) / 100.0 * pfmax print("Polarized flux contour levels : ", levelsPf) ax.contour(stkI * convert_flux * pol, levels=levelsPf, colors="grey", linewidths=0.5) elif display.lower() in ["p", "pol", "pol_deg"]: @@ -548,8 +552,8 @@ def polarization_map( arrow_props={"ec": "k", "fc": font_color, "alpha": 1, "lw": 1}, ) - if display.lower() in ["i", "s_i", "snri", "pf", "p", "pa", "s_p", "snrp", "confp"]: - if step_vec == 0: + if display.lower() in ["i", "s_i", "snri", "pf", "p", "pa", "s_p", "snrp", "confp"] and step_vec != 0: + if scale_vec == -1: poldata[np.isfinite(poldata)] = 1.0 / 2.0 step_vec = 1 scale_vec = 2.0 @@ -1359,7 +1363,7 @@ class overplot_pol(align_maps): Inherit from class align_maps in order to get the same WCS on both maps. """ - def overplot(self, levels=None, P_cut=0.99, SNRi_cut=1.0, scale_vec=2.0, step_vec=1, savename=None, **kwargs): + def overplot(self, levels=None, P_cut=0.99, SNRi_cut=1.0, step_vec=1, scale_vec=2.0, disptype="i", savename=None, **kwargs): self.Stokes_UV = self.map self.wcs_UV = self.map_wcs # Get Data @@ -1402,13 +1406,6 @@ class overplot_pol(align_maps): self.ax_overplot.set_xlabel(label="Right Ascension (J2000)") self.ax_overplot.set_ylabel(label="Declination (J2000)", labelpad=-1) - self.fig_overplot.suptitle( - "{0:s} observation from {1:s} overplotted with polarization vectors and Stokes I contours from {2:s}".format( - obj, self.other_observer, self.map_observer - ), - wrap=True, - ) - # Display "other" intensity map vmin, vmax = other_data[other_data > 0.0].max() / 1e3 * self.other_convert, other_data[other_data > 0.0].max() * self.other_convert for key, value in [ @@ -1459,59 +1456,85 @@ class overplot_pol(align_maps): ) # Display full size polarization vectors - if scale_vec is None: - self.scale_vec = 2.0 * self.px_scale - pol[np.isfinite(pol)] = 1.0 / 2.0 - else: - self.scale_vec = scale_vec * self.px_scale - self.X, self.Y = np.meshgrid(np.arange(stkI.shape[1]), np.arange(stkI.shape[0])) - self.U, self.V = pol * np.cos(np.pi / 2.0 + pang * np.pi / 180.0), pol * np.sin(np.pi / 2.0 + pang * np.pi / 180.0) - self.Q = self.ax_overplot.quiver( - self.X[::step_vec, ::step_vec], - self.Y[::step_vec, ::step_vec], - self.U[::step_vec, ::step_vec], - self.V[::step_vec, ::step_vec], - units="xy", - angles="uv", - scale=1.0 / self.scale_vec, - scale_units="xy", - pivot="mid", - headwidth=0.0, - headlength=0.0, - headaxislength=0.0, - width=kwargs["width"], - linewidth=kwargs["linewidth"], - color="white", - edgecolor="black", - transform=self.ax_overplot.get_transform(self.wcs_UV), - label="{0:s} polarization map".format(self.map_observer), - ) + vecstr = "" + if step_vec != 0: + vecstr = "polarization vectors " + if scale_vec is None: + self.scale_vec = 2.0 * self.px_scale + pol[np.isfinite(pol)] = 1.0 / 2.0 + else: + self.scale_vec = scale_vec * self.px_scale + self.X, self.Y = np.meshgrid(np.arange(stkI.shape[1]), np.arange(stkI.shape[0])) + self.U, self.V = pol * np.cos(np.pi / 2.0 + pang * np.pi / 180.0), pol * np.sin(np.pi / 2.0 + pang * np.pi / 180.0) + self.Q = self.ax_overplot.quiver( + self.X[::step_vec, ::step_vec], + self.Y[::step_vec, ::step_vec], + self.U[::step_vec, ::step_vec], + self.V[::step_vec, ::step_vec], + units="xy", + angles="uv", + scale=1.0 / self.scale_vec, + scale_units="xy", + pivot="mid", + headwidth=0.0, + headlength=0.0, + headaxislength=0.0, + width=kwargs["width"], + linewidth=kwargs["linewidth"], + color="white", + edgecolor="black", + transform=self.ax_overplot.get_transform(self.wcs_UV), + label="{0:s} polarization map".format(self.map_observer), + ) - # Display Stokes I as contours - if levels is None: - levels = np.array([2.0, 5.0, 10.0, 20.0, 90.0]) / 100.0 * np.max(stkI[stkI > 0.0]) * self.map_convert - cont_stkI = self.ax_overplot.contour( - stkI * self.map_convert, levels=levels, colors="grey", alpha=0.75, transform=self.ax_overplot.get_transform(self.wcs_UV) - ) - # self.ax_overplot.clabel(cont_stkI, inline=True, fontsize=5) + # Display Stokes as contours + disptypestr = "" + if disptype.lower() == "p": + disptypestr = "polarization degree" + if levels is None: + levels = np.array([2.0, 5.0, 10.0, 20.0, 90.0]) / 100.0 * np.max(pol[stkI > 0.0]) + cont_stk = self.ax_overplot.contour( + pol * 100.0, levels=levels * 100.0, colors="grey", alpha=0.75, transform=self.ax_overplot.get_transform(self.wcs_UV) + ) + if disptype.lower() == "pf": + disptypestr = "polarized flux" + if levels is None: + levels = np.array([2.0, 5.0, 10.0, 20.0, 90.0]) / 100.0 * np.max(stkI[stkI > 0.0] * pol[stkI > 0.0]) * self.map_convert + cont_stk = self.ax_overplot.contour( + stkI * pol * self.map_convert, levels=levels, colors="grey", alpha=0.75, transform=self.ax_overplot.get_transform(self.wcs_UV) + ) + if disptype.lower() == "snri": + disptypestr = "Stokes I signal-to-noise" + if levels is None: + levels = np.array([2.0, 5.0, 10.0, 20.0, 90.0]) / 100.0 * np.max(SNRi[stk_cov[0, 0] > 0.0]) + cont_stk = self.ax_overplot.contour(SNRi, levels=levels, colors="grey", alpha=0.75, transform=self.ax_overplot.get_transform(self.wcs_UV)) + else: # default to intensity contours + disptypestr = "Stokes I" + if levels is None: + levels = np.array([2.0, 5.0, 10.0, 20.0, 90.0]) / 100.0 * np.max(stkI[stkI > 0.0]) * self.map_convert + cont_stk = self.ax_overplot.contour( + stkI * self.map_convert, levels=levels, colors="grey", alpha=0.75, transform=self.ax_overplot.get_transform(self.wcs_UV) + ) + # self.ax_overplot.clabel(cont_stk, inline=False, colors="k", fontsize=7) # Display pixel scale and North direction - fontprops = fm.FontProperties(size=16) - px_size = self.other_wcs.wcs.get_cdelt()[0] * 3600.0 - px_sc = AnchoredSizeBar( - self.ax_overplot.transData, - 1.0 / px_size, - "1 arcsec", - 3, - pad=0.5, - sep=5, - borderpad=0.5, - frameon=False, - size_vertical=0.005, - color=font_color, - fontproperties=fontprops, - ) - self.ax_overplot.add_artist(px_sc) + if step_vec != 0: + fontprops = fm.FontProperties(size=16) + px_size = self.other_wcs.wcs.get_cdelt()[0] * 3600.0 + px_sc = AnchoredSizeBar( + self.ax_overplot.transData, + 1.0 / px_size, + "1 arcsec", + 3, + pad=0.5, + sep=5, + borderpad=0.5, + frameon=False, + size_vertical=0.005, + color=font_color, + fontproperties=fontprops, + ) + self.ax_overplot.add_artist(px_sc) north_dir = AnchoredDirectionArrows( self.ax_overplot.transAxes, "E", @@ -1528,20 +1551,21 @@ class overplot_pol(align_maps): arrow_props={"ec": "k", "fc": "w", "alpha": 1, "lw": 0.5}, ) self.ax_overplot.add_artist(north_dir) - pol_sc = AnchoredSizeBar( - self.ax_overplot.transData, - self.scale_vec, - r"$P$= 100%", - 4, - pad=0.5, - sep=5, - borderpad=0.5, - frameon=False, - size_vertical=0.005, - color=font_color, - fontproperties=fontprops, - ) - self.ax_overplot.add_artist(pol_sc) + if step_vec != 0: + pol_sc = AnchoredSizeBar( + self.ax_overplot.transData, + self.scale_vec, + r"$P$= 100%", + 4, + pad=0.5, + sep=5, + borderpad=0.5, + frameon=False, + size_vertical=0.005, + color=font_color, + fontproperties=fontprops, + ) + self.ax_overplot.add_artist(pol_sc) (self.cr_map,) = self.ax_overplot.plot(*(self.map_wcs.celestial.wcs.crpix - (1.0, 1.0)), "r+", transform=self.ax_overplot.get_transform(self.wcs_UV)) (self.cr_other,) = self.ax_overplot.plot(*(self.other_wcs.celestial.wcs.crpix - (1.0, 1.0)), "g+") @@ -1554,15 +1578,21 @@ class overplot_pol(align_maps): self.legend_title = r"{0:s} image".format(self.other_observer) handles, labels = self.ax_overplot.get_legend_handles_labels() - handles[np.argmax([li == "{0:s} polarization map".format(self.map_observer) for li in labels])] = FancyArrowPatch( - (0, 0), (0, 1), arrowstyle="-", fc="w", ec="k", lw=2 - ) - labels.append("{0:s} Stokes I contour".format(self.map_observer)) - handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=cont_stkI.get_edgecolor()[0])) + if step_vec != 0: + handles[np.argmax([li == "{0:s} polarization map".format(self.map_observer) for li in labels])] = FancyArrowPatch( + (0, 0), (0, 1), arrowstyle="-", fc="w", ec="k", lw=2 + ) + labels.append("{0:s} {1:s} contour".format(self.map_observer, disptypestr)) + handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=cont_stk.get_edgecolor()[0])) self.legend = self.ax_overplot.legend( handles=handles, labels=labels, bbox_to_anchor=(0.0, 1.02, 1.0, 0.102), loc="lower left", mode="expand", borderaxespad=0.0 ) + self.fig_overplot.suptitle( + "{0:s} observation from {1:s} overplotted with {2:s} contours from {3:s}".format(obj, self.other_observer, vecstr + disptypestr, self.map_observer), + wrap=True, + ) + if savename is not None: if savename[-4:] not in [".png", ".jpg", ".pdf"]: savename += ".pdf" @@ -1570,10 +1600,10 @@ class overplot_pol(align_maps): self.fig_overplot.canvas.draw() - def plot(self, levels=None, P_cut=0.99, SNRi_cut=1.0, scale_vec=2.0, savename=None, **kwargs) -> None: + def plot(self, levels=None, P_cut=0.99, SNRi_cut=1.0, step_vec=1, scale_vec=2.0, disptype="i", savename=None, **kwargs) -> None: while not self.aligned: self.align() - self.overplot(levels=levels, P_cut=P_cut, SNRi_cut=SNRi_cut, scale_vec=scale_vec, savename=savename, **kwargs) + self.overplot(levels=levels, P_cut=P_cut, SNRi_cut=SNRi_cut, step_vec=step_vec, scale_vec=scale_vec, disptype=disptype, savename=savename, **kwargs) plt.show(block=True) def add_vector(self, position="center", pol_deg=1.0, pol_ang=0.0, **kwargs): @@ -3360,8 +3390,17 @@ class pol_map(object): + r"$\theta_{{P}}^{{int}}$ = {0:.1f} $\pm$ {1:.1f} °".format(PA_reg, np.ceil(PA_reg_err * 10.0) / 10.0) + str_conf ) - self.str_cut = "" - # self.str_cut = "\n"+r"$F_{{\lambda}}^{{cut}}$({0:.0f} $\AA$) = {1} $ergs \cdot cm^{{-2}} \cdot s^{{-1}} \cdot \AA^{{-1}}$".format(self.pivot_wav, sci_not(I_cut*self.map_convert, I_cut_err*self.map_convert, 2))+"\n"+r"$P^{{cut}}$ = {0:.1f} $\pm$ {1:.1f} %".format(P_cut*100., np.ceil(P_cut_err*1000.)/10.)+"\n"+r"$\theta_{{P}}^{{cut}}$ = {0:.1f} $\pm$ {1:.1f} °".format(PA_cut, np.ceil(PA_cut_err*10.)/10.) + # self.str_cut = "" + self.str_cut = ( + "\n" + + r"$F_{{\lambda}}^{{cut}}$({0:.0f} $\AA$) = {1} $ergs \cdot cm^{{-2}} \cdot s^{{-1}} \cdot \AA^{{-1}}$".format( + self.pivot_wav, sci_not(I_cut * self.map_convert, I_cut_err * self.map_convert, 2) + ) + + "\n" + + r"$P^{{cut}}$ = {0:.1f} $\pm$ {1:.1f} %".format(P_cut * 100.0, np.ceil(P_cut_err * 1000.0) / 10.0) + + "\n" + + r"$\theta_{{P}}^{{cut}}$ = {0:.1f} $\pm$ {1:.1f} °".format(PA_cut, np.ceil(PA_cut_err * 10.0) / 10.0) + ) self.an_int = ax.annotate( self.str_int + self.str_cut, color="white", @@ -3387,8 +3426,17 @@ class pol_map(object): + r"$\theta_{{P}}^{{int}}$ = {0:.1f} $\pm$ {1:.1f} °".format(PA_reg, np.ceil(PA_reg_err * 10.0) / 10.0) + str_conf ) - str_cut = "" - # str_cut = "\n"+r"$F_{{\lambda}}^{{cut}}$({0:.0f} $\AA$) = {1} $ergs \cdot cm^{{-2}} \cdot s^{{-1}} \cdot \AA^{{-1}}$".format(self.pivot_wav, sci_not(I_cut*self.map_convert, I_cut_err*self.map_convert, 2))+"\n"+r"$P^{{cut}}$ = {0:.1f} $\pm$ {1:.1f} %".format(P_cut*100., np.ceil(P_cut_err*1000.)/10.)+"\n"+r"$\theta_{{P}}^{{cut}}$ = {0:.1f} $\pm$ {1:.1f} °".format(PA_cut, np.ceil(PA_cut_err*10.)/10.) + # str_cut = "" + str_cut = ( + "\n" + + r"$F_{{\lambda}}^{{cut}}$({0:.0f} $\AA$) = {1} $ergs \cdot cm^{{-2}} \cdot s^{{-1}} \cdot \AA^{{-1}}$".format( + self.pivot_wav, sci_not(I_cut * self.map_convert, I_cut_err * self.map_convert, 2) + ) + + "\n" + + r"$P^{{cut}}$ = {0:.1f} $\pm$ {1:.1f} %".format(P_cut * 100.0, np.ceil(P_cut_err * 1000.0) / 10.0) + + "\n" + + r"$\theta_{{P}}^{{cut}}$ = {0:.1f} $\pm$ {1:.1f} °".format(PA_cut, np.ceil(PA_cut_err * 10.0) / 10.0) + ) ax.annotate( str_int + str_cut, color="white", diff --git a/package/lib/query.py b/package/lib/query.py index ba99d49..76033cd 100755 --- a/package/lib/query.py +++ b/package/lib/query.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # -*- coding:utf-8 -*- """ Library function to query and download datatsets from MAST api. diff --git a/package/lib/reduction.py b/package/lib/reduction.py index a9ce0f1..7bd86f5 100755 --- a/package/lib/reduction.py +++ b/package/lib/reduction.py @@ -416,12 +416,12 @@ def deconvolve_array(data_array, headers, psf="gaussian", FWHM=1.0, scale="px", FWHM /= pxsize[0].min() # Define Point-Spread-Function kernel - if psf.lower() in ["gauss", "gaussian"]: + if isinstance(psf, np.ndarray) and (len(psf.shape) == 2): + kernel = psf + elif psf.lower() in ["gauss", "gaussian"]: if shape is None: shape = np.min(data_array[0].shape) - 2, np.min(data_array[0].shape) - 2 kernel = gaussian_psf(FWHM=FWHM, shape=shape) - elif isinstance(psf, np.ndarray) and (len(psf.shape) == 2): - kernel = psf else: raise ValueError("{} is not a valid value for 'psf'".format(psf)) diff --git a/package/src/Combine.py b/package/src/Combine.py index 59bc2ce..d5b19bb 100755 --- a/package/src/Combine.py +++ b/package/src/Combine.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # -*- coding:utf-8 -*- from pathlib import Path from sys import path as syspath diff --git a/package/src/emission_center.py b/package/src/emission_center.py index 8f9142d..9c05fde 100755 --- a/package/src/emission_center.py +++ b/package/src/emission_center.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # -*- coding:utf-8 -*- from pathlib import Path from sys import path as syspath @@ -41,18 +41,20 @@ def main(infile, target=None, output_dir=None): target = Stokes[0].header["TARGNAME"] fig = figure(figsize=(8, 8.5), layout="constrained") - fig, ax = polarization_map(Stokes, P_cut=0.99, step_vec=1, scale_vec=3, display="i", fig=fig, width=0.33, linewidth=0.5) + fig, ax = polarization_map(Stokes, P_cut=0.99, step_vec=1, scale_vec=3, display="pf", fig=fig, width=0.33, linewidth=0.5) - ax.plot(*Stokescenter, marker="+", color="gray", label="Best confidence for center: {0}".format(Stokespos.to_string("hmsdms"))) + ax.plot(*Stokescenter, marker="+", color="k", lw=3) + ax.plot(*Stokescenter, marker="+", color="gray", lw=1.5, label="Best confidence for center: {0}".format(Stokespos.to_string("hmsdms"))) + ax.contour(Stokescentconf, [0.01], colors="k", linewidths=3) confcentcont = ax.contour(Stokescentconf, [0.01], colors="gray") - confcont = ax.contour(Stokesconf, [0.9905], colors="r") + # confcont = ax.contour(Stokesconf, [0.9905], colors="r") # snr3cont = ax.contour(Stokessnr, [3.0], colors="b", linestyles="dashed") # snr4cont = ax.contour(Stokessnr, [4.0], colors="b") handles, labels = ax.get_legend_handles_labels() labels.append(r"Center $Conf_{99\%}$ contour") handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=confcentcont.get_edgecolor()[0])) - labels.append(r"Polarization $Conf_{99\%}$ contour") - handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=confcont.get_edgecolor()[0])) + # labels.append(r"Polarization $Conf_{99\%}$ contour") + # handles.append(Rectangle((0, 0), 1, 1, fill=False, ec=confcont.get_edgecolor()[0])) # labels.append(r"$SNR_P \geq$ 3 contour") # handles.append(Rectangle((0, 0), 1, 1, fill=False, ls="--", ec=snr3cont.get_edgecolor()[0])) # labels.append(r"$SNR_P \geq$ 4 contour") diff --git a/package/src/get_cdelt.py b/package/src/get_cdelt.py index d6ea688..7c06713 100755 --- a/package/src/get_cdelt.py +++ b/package/src/get_cdelt.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # -*- coding:utf-8 -*- from pathlib import Path from sys import path as syspath @@ -18,7 +18,7 @@ def main(infiles=None): from numpy.linalg import eig if infiles is None: - print('Usage: "python get_cdelt.py -f infiles"') + print('Usage: "env python3 get_cdelt.py -f infiles"') return 1 prod = [["/".join(filepath.split("/")[:-1]), filepath.split("/")[-1]] for filepath in infiles] data_folder = prod[0][0] diff --git a/package/src/overplot_IC5063.py b/package/src/overplot_IC5063.py index 1d58c88..bea2fbe 100755 --- a/package/src/overplot_IC5063.py +++ b/package/src/overplot_IC5063.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # -*- coding:utf-8 -*- from pathlib import Path from sys import path as syspath diff --git a/package/src/overplot_MRK463E.py b/package/src/overplot_MRK463E.py index d89845e..505e39d 100755 --- a/package/src/overplot_MRK463E.py +++ b/package/src/overplot_MRK463E.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # -*- coding:utf-8 -*- from pathlib import Path from sys import path as syspath @@ -26,18 +26,21 @@ Radio = fits.open("./data/MRK463E/EMERLIN/Voorwerpjes_1356+1822_1356+1822_unifor # B.plot(levels=levels, P_cut=0.99, SNRi_cut=1.0, scale_vec=5, norm=LogNorm(8.5e-18, 2.5e-15), savename="./plots/MRK463E/IR_overplot.pdf") # B.write_to(path1="./data/MRK463E/FOC_data_WFPC.fits", path2="./data/MRK463E/WFPC_data.fits", suffix="aligned") -levels = np.array([0.8, 2, 5, 10, 20, 50]) / 100.0 * Stokes_UV[0].header["photflam"] +# levels = np.array([0.8, 2, 5, 10, 20, 50]) / 100.0 * Stokes_UV[0].header["photflam"] +levels = np.array([5, 10, 20, 50]) C = overplot_pol(Stokes_UV, Radio, norm=LogNorm()) C.other_im.set(norm=LogNorm(1e-4, 2e-2)) C.plot( levels=levels, - P_cut=0.999, - SNRi_cut=5.0, + P_cut=0.99, + SNRi_cut=1.0, + step_vec=0, scale_vec=3, norm=LogNorm(1e-4, 2e-2), cmap="inferno_r", width=0.5, linewidth=0.5, - savename="./plots/MRK463E/EMERLIN_overplot.pdf", + disptype="snri", + savename="./plots/MRK463E/EMERLIN_snri_overplot.pdf", ) C.write_to(path1="./data/MRK463E/FOC_data_EMERLIN.fits", path2="./data/MRK463E/EMERLIN_data.fits", suffix="aligned") diff --git a/package/src/overplot_NGC1068.py b/package/src/overplot_NGC1068.py index 52ca188..8642458 100755 --- a/package/src/overplot_NGC1068.py +++ b/package/src/overplot_NGC1068.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # -*- coding:utf-8 -*- from pathlib import Path from sys import path as syspath From 83e58d6a26c33a17a55f39831caa20680a77ecad Mon Sep 17 00:00:00 2001 From: Thibault Barnouin Date: Tue, 26 Nov 2024 16:58:37 +0100 Subject: [PATCH 14/18] fix depreciation warning matplotlib --- package/FOC_reduction.py | 12 ++--- package/lib/plots.py | 105 +++++++++++++++++++++------------------ 2 files changed, 64 insertions(+), 53 deletions(-) diff --git a/package/FOC_reduction.py b/package/FOC_reduction.py index f8986a7..eab1da7 100755 --- a/package/FOC_reduction.py +++ b/package/FOC_reduction.py @@ -40,9 +40,9 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= display_crop = False # Background estimation - error_sub_type = "freedman-diaconis" # sqrt, sturges, rice, scott, freedman-diaconis (default) or shape (example (51, 51)) - subtract_error = 1.0 - display_bkg = False + error_sub_type = "scott" # sqrt, sturges, rice, scott, freedman-diaconis (default) or shape (example (51, 51)) + subtract_error = 2.0 + display_bkg = True # Data binning pxsize = 0.05 @@ -66,10 +66,10 @@ def main(target=None, proposal_id=None, infiles=None, output_dir="./data", crop= rotate_North = True # Polarization map output - P_cut = 0.999 # if >=1.0 cut on the signal-to-noise else cut on the confidence level in Q, U - SNRi_cut = 3.0 # I measurments with SNR>30, which implies an uncertainty in P of 4.7%. + P_cut = 5 # if >=1.0 cut on the signal-to-noise else cut on the confidence level in Q, U + SNRi_cut = 5.0 # I measurments with SNR>30, which implies an uncertainty in P of 4.7%. flux_lim = None # lowest and highest flux displayed on plot, defaults to bkg and maximum in cut if None - scale_vec = 2 + scale_vec = 3 step_vec = 1 # plot all vectors in the array. if step_vec = 2, then every other vector will be plotted if step_vec = 0 then all vectors are displayed at full length # Pipeline start diff --git a/package/lib/plots.py b/package/lib/plots.py index 0b908b9..21d0a17 100755 --- a/package/lib/plots.py +++ b/package/lib/plots.py @@ -2192,8 +2192,7 @@ class image_lasso_selector(object): self.mask = np.zeros(self.img.shape[:2], dtype=bool) self.mask[self.indices] = True if hasattr(self, "cont"): - for coll in self.cont.collections: - coll.remove() + self.cont.remove() self.cont = self.ax.contour(self.mask.astype(float), levels=[0.5], colors="white", linewidths=1) if not self.embedded: self.displayed.set_data(array) @@ -2305,11 +2304,7 @@ class slit(object): for p in self.pix: self.mask[tuple(p)] = (np.abs(np.dot(rot2D(-self.angle), p - self.rect.get_center()[::-1])) < (self.height / 2.0, self.width / 2.0)).all() if hasattr(self, "cont"): - for coll in self.cont.collections: - try: - coll.remove() - except AttributeError: - return + self.cont.remove() self.cont = self.ax.contour(self.mask.astype(float), levels=[0.5], colors="white", linewidths=1) if not self.embedded: self.displayed.set_data(array) @@ -2408,11 +2403,7 @@ class aperture(object): x0, y0 = self.circ.center self.mask = np.sqrt((xx - x0) ** 2 + (yy - y0) ** 2) < self.radius if hasattr(self, "cont"): - for coll in self.cont.collections: - try: - coll.remove() - except AttributeError: - return + self.cont.remove() self.cont = self.ax.contour(self.mask.astype(float), levels=[0.5], colors="white", linewidths=1) if not self.embedded: self.displayed.set_data(array) @@ -2441,7 +2432,7 @@ class pol_map(object): self.step_vec = step_vec self.scale_vec = scale_vec self.pa_err = pa_err - self.conf = PCconf(self.Q / self.I, self.U / self.I, np.sqrt(self.IQU_cov[1, 1]) / self.I, np.sqrt(self.IQU_cov[2, 2]) / self.I) + self.conf = PCconf(self.QN, self.UN, self.QN_ERR, self.UN_ERR) # Get data self.targ = self.Stokes[0].header["targname"] @@ -2543,8 +2534,7 @@ class pol_map(object): self.selected = False self.region = deepcopy(self.select_instance.mask.astype(bool)) self.select_instance.displayed.remove() - for coll in self.select_instance.cont.collections: - coll.remove() + self.select_instance.cont.remove() self.select_instance.lasso.set_active(False) self.set_data_mask(deepcopy(self.region)) self.pol_int() @@ -2587,8 +2577,7 @@ class pol_map(object): self.select_instance.update_mask() self.region = deepcopy(self.select_instance.mask.astype(bool)) self.select_instance.displayed.remove() - for coll in self.select_instance.cont.collections: - coll.remove() + self.select_instance.cont.remove() self.select_instance.circ.set_visible(False) self.set_data_mask(deepcopy(self.region)) self.pol_int() @@ -2645,8 +2634,7 @@ class pol_map(object): self.select_instance.update_mask() self.region = deepcopy(self.select_instance.mask.astype(bool)) self.select_instance.displayed.remove() - for coll in self.select_instance.cont.collections: - coll.remove() + self.select_instance.cont.remove() self.select_instance.rect.set_visible(False) self.set_data_mask(deepcopy(self.region)) self.pol_int() @@ -2923,14 +2911,42 @@ class pol_map(object): def I(self): return self.Stokes["I_STOKES"].data + @property + def I_ERR(self): + return np.sqrt(self.Stokes["IQU_COV_MATRIX"].data[0, 0]) + @property def Q(self): return self.Stokes["Q_STOKES"].data + @property + def QN(self): + return self.Q / np.where(self.I > 0, self.I, np.nan) + + @property + def Q_ERR(self): + return np.sqrt(self.Stokes["IQU_COV_MATRIX"].data[1, 1]) + + @property + def QN_ERR(self): + return self.Q_ERR / np.where(self.I > 0, self.I, np.nan) + @property def U(self): return self.Stokes["U_STOKES"].data + @property + def UN(self): + return self.U / np.where(self.I > 0, self.I, np.nan) + + @property + def U_ERR(self): + return np.sqrt(self.Stokes["IQU_COV_MATRIX"].data[2, 2]) + + @property + def UN_ERR(self): + return self.U_ERR / np.where(self.I > 0, self.I, np.nan) + @property def IQU_cov(self): return self.Stokes["IQU_COV_MATRIX"].data @@ -3368,12 +3384,7 @@ class pol_map(object): ) if hasattr(self, "cont"): - for coll in self.cont.collections: - try: - coll.remove() - except AttributeError: - del coll - del self.cont + self.cont.remove() if fig is None: fig = self.fig if ax is None: @@ -3390,17 +3401,17 @@ class pol_map(object): + r"$\theta_{{P}}^{{int}}$ = {0:.1f} $\pm$ {1:.1f} °".format(PA_reg, np.ceil(PA_reg_err * 10.0) / 10.0) + str_conf ) - # self.str_cut = "" - self.str_cut = ( - "\n" - + r"$F_{{\lambda}}^{{cut}}$({0:.0f} $\AA$) = {1} $ergs \cdot cm^{{-2}} \cdot s^{{-1}} \cdot \AA^{{-1}}$".format( - self.pivot_wav, sci_not(I_cut * self.map_convert, I_cut_err * self.map_convert, 2) - ) - + "\n" - + r"$P^{{cut}}$ = {0:.1f} $\pm$ {1:.1f} %".format(P_cut * 100.0, np.ceil(P_cut_err * 1000.0) / 10.0) - + "\n" - + r"$\theta_{{P}}^{{cut}}$ = {0:.1f} $\pm$ {1:.1f} °".format(PA_cut, np.ceil(PA_cut_err * 10.0) / 10.0) - ) + self.str_cut = "" + # self.str_cut = ( + # "\n" + # + r"$F_{{\lambda}}^{{cut}}$({0:.0f} $\AA$) = {1} $ergs \cdot cm^{{-2}} \cdot s^{{-1}} \cdot \AA^{{-1}}$".format( + # self.pivot_wav, sci_not(I_cut * self.map_convert, I_cut_err * self.map_convert, 2) + # ) + # + "\n" + # + r"$P^{{cut}}$ = {0:.1f} $\pm$ {1:.1f} %".format(P_cut * 100.0, np.ceil(P_cut_err * 1000.0) / 10.0) + # + "\n" + # + r"$\theta_{{P}}^{{cut}}$ = {0:.1f} $\pm$ {1:.1f} °".format(PA_cut, np.ceil(PA_cut_err * 10.0) / 10.0) + # ) self.an_int = ax.annotate( self.str_int + self.str_cut, color="white", @@ -3426,17 +3437,17 @@ class pol_map(object): + r"$\theta_{{P}}^{{int}}$ = {0:.1f} $\pm$ {1:.1f} °".format(PA_reg, np.ceil(PA_reg_err * 10.0) / 10.0) + str_conf ) - # str_cut = "" - str_cut = ( - "\n" - + r"$F_{{\lambda}}^{{cut}}$({0:.0f} $\AA$) = {1} $ergs \cdot cm^{{-2}} \cdot s^{{-1}} \cdot \AA^{{-1}}$".format( - self.pivot_wav, sci_not(I_cut * self.map_convert, I_cut_err * self.map_convert, 2) - ) - + "\n" - + r"$P^{{cut}}$ = {0:.1f} $\pm$ {1:.1f} %".format(P_cut * 100.0, np.ceil(P_cut_err * 1000.0) / 10.0) - + "\n" - + r"$\theta_{{P}}^{{cut}}$ = {0:.1f} $\pm$ {1:.1f} °".format(PA_cut, np.ceil(PA_cut_err * 10.0) / 10.0) - ) + str_cut = "" + # str_cut = ( + # "\n" + # + r"$F_{{\lambda}}^{{cut}}$({0:.0f} $\AA$) = {1} $ergs \cdot cm^{{-2}} \cdot s^{{-1}} \cdot \AA^{{-1}}$".format( + # self.pivot_wav, sci_not(I_cut * self.map_convert, I_cut_err * self.map_convert, 2) + # ) + # + "\n" + # + r"$P^{{cut}}$ = {0:.1f} $\pm$ {1:.1f} %".format(P_cut * 100.0, np.ceil(P_cut_err * 1000.0) / 10.0) + # + "\n" + # + r"$\theta_{{P}}^{{cut}}$ = {0:.1f} $\pm$ {1:.1f} °".format(PA_cut, np.ceil(PA_cut_err * 10.0) / 10.0) + # ) ax.annotate( str_int + str_cut, color="white", From 50c73f245f150b06730bff8776290cdefea11774 Mon Sep 17 00:00:00 2001 From: Thibault Barnouin Date: Wed, 4 Dec 2024 18:30:48 +0100 Subject: [PATCH 15/18] correct photflam when rebinning --- package/lib/fits.py | 1 + package/lib/plots.py | 9 +++++++-- package/lib/reduction.py | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/package/lib/fits.py b/package/lib/fits.py index 1506a29..6ea842a 100755 --- a/package/lib/fits.py +++ b/package/lib/fits.py @@ -141,6 +141,7 @@ def save_Stokes( header["TELESCOP"] = (header_stokes["TELESCOP"] if "TELESCOP" in list(header_stokes.keys()) else "HST", "telescope used to acquire data") header["INSTRUME"] = (header_stokes["INSTRUME"] if "INSTRUME" in list(header_stokes.keys()) else "FOC", "identifier for instrument used to acuire data") header["PHOTPLAM"] = (header_stokes["PHOTPLAM"], "Pivot Wavelength") + header["PHOTBW"] = (header_stokes["PHOTBW"], "RMS Bandwidth of the Filter and Detector") header["PHOTFLAM"] = (header_stokes["PHOTFLAM"], "Inverse Sensitivity in DN/sec/cm**2/Angst") header["EXPTIME"] = (header_stokes["EXPTIME"], "Total exposure time in sec") header["PROPOSID"] = (header_stokes["PROPOSID"], "PEP proposal identifier for observation") diff --git a/package/lib/plots.py b/package/lib/plots.py index 21d0a17..37d0304 100755 --- a/package/lib/plots.py +++ b/package/lib/plots.py @@ -97,7 +97,7 @@ def plot_obs(data_array, headers, rectangle=None, shifts=None, savename=None, pl plt.rcParams.update({"font.size": 10}) nb_obs = np.max([np.sum([head["filtnam1"] == curr_pol for head in headers]) for curr_pol in ["POL0", "POL60", "POL120"]]) shape = np.array((3, nb_obs)) - fig, ax = plt.subplots(shape[0], shape[1], figsize=(3 * shape[1], 3 * shape[0]), layout="constrained", sharex=True, sharey=True) + fig, ax = plt.subplots(shape[0], shape[1], figsize=(3 * shape[1], 3 * shape[0]), layout="compressed", sharex=True, sharey=True) used = np.zeros(shape, dtype=bool) r_pol = dict(pol0=0, pol60=1, pol120=2) c_pol = dict(pol0=0, pol60=0, pol120=0) @@ -317,9 +317,9 @@ def polarization_map( for j in range(3): stk_cov[i][j][np.logical_not(data_mask)] = np.nan + wcs = WCS(Stokes[0]).deepcopy() pivot_wav = Stokes[0].header["photplam"] convert_flux = Stokes[0].header["photflam"] - wcs = WCS(Stokes[0]).deepcopy() # Plot Stokes parameters map if display is None or display.lower() in ["default"]: @@ -3275,6 +3275,7 @@ class pol_map(object): str_conf = "" if self.region is None: s_I = np.sqrt(self.IQU_cov[0, 0]) + N_pix = self.I.size I_reg = self.I.sum() I_reg_err = np.sqrt(np.sum(s_I**2)) P_reg = self.Stokes[0].header["P_int"] @@ -3289,6 +3290,7 @@ class pol_map(object): s_IU = self.IQU_cov[0, 2] s_QU = self.IQU_cov[1, 2] + N_cut = self.cut.sum() I_cut = self.I[self.cut].sum() Q_cut = self.Q[self.cut].sum() U_cut = self.U[self.cut].sum() @@ -3324,6 +3326,7 @@ class pol_map(object): s_IU = self.IQU_cov[0, 2] s_QU = self.IQU_cov[1, 2] + N_pix = self.region.sum() I_reg = self.I[self.region].sum() Q_reg = self.Q[self.region].sum() U_reg = self.U[self.region].sum() @@ -3356,6 +3359,7 @@ class pol_map(object): ) new_cut = np.logical_and(self.region, self.cut) + N_cut = new_cut.sum() I_cut = self.I[new_cut].sum() Q_cut = self.Q[new_cut].sum() U_cut = self.U[new_cut].sum() @@ -3385,6 +3389,7 @@ class pol_map(object): if hasattr(self, "cont"): self.cont.remove() + del self.cont if fig is None: fig = self.fig if ax is None: diff --git a/package/lib/reduction.py b/package/lib/reduction.py index 7bd86f5..613e0d7 100755 --- a/package/lib/reduction.py +++ b/package/lib/reduction.py @@ -676,6 +676,7 @@ def rebin_array(data_array, error_array, headers, pxsize=2, scale="px", operatio nw.wcs.crpix /= Dxy nw.array_shape = new_shape new_header["NAXIS1"], new_header["NAXIS2"] = nw.array_shape + new_header["PHOTFLAM"] = header["PHOTFLAM"] * (Dxy[0] * Dxy[1]) for key, val in nw.to_header().items(): new_header.set(key, val) new_header["SAMPLING"] = (str(pxsize) + scale, "Resampling performed during reduction") From 82168cd67fa12582a63a7831b0d182ce6817ad64 Mon Sep 17 00:00:00 2001 From: Thibault Barnouin Date: Thu, 5 Dec 2024 17:00:09 +0100 Subject: [PATCH 16/18] change flux display to Flambda --- package/lib/plots.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/lib/plots.py b/package/lib/plots.py index 37d0304..8120809 100755 --- a/package/lib/plots.py +++ b/package/lib/plots.py @@ -155,7 +155,7 @@ def plot_obs(data_array, headers, rectangle=None, shifts=None, savename=None, pl fig.delaxes(ax[i][j]) # fig.subplots_adjust(hspace=0.01, wspace=0.01, right=1.02) - fig.colorbar(im, ax=ax, location="right", shrink=0.75, aspect=50, pad=0.025, label=r"Flux [$ergs \cdot cm^{-2} \cdot s^{-1} \cdot \AA^{-1}$]") + fig.colorbar(im, ax=ax, location="right", shrink=0.75, aspect=50, pad=0.025, label=r"$F_{\lambda}$ [$ergs \cdot cm^{-2} \cdot s^{-1} \cdot \AA^{-1}$]") if savename is not None: # fig.suptitle(savename) @@ -426,7 +426,7 @@ def polarization_map( im = ax.imshow(stkI * convert_flux, norm=LogNorm(vmin, vmax), aspect="equal", cmap=kwargs["cmap"], alpha=1.0) fig.colorbar(im, ax=ax, aspect=30, shrink=0.75, pad=0.025, label=r"$F_{\lambda}$ [$ergs \cdot cm^{-2} \cdot s^{-1} \cdot \AA^{-1}$]") levelsI = np.array([0.8, 2.0, 5.0, 10.0, 20.0, 50.0]) / 100.0 * vmax - print("Total flux contour levels : ", levelsI) + print("Flux density contour levels : ", levelsI) ax.contour(stkI * convert_flux, levels=levelsI, colors="grey", linewidths=0.5) elif display.lower() in ["pf", "pol_flux"]: # Display polarization flux @@ -444,7 +444,7 @@ def polarization_map( fig.colorbar(im, ax=ax, aspect=50, shrink=0.75, pad=0.025, label=r"$F_{\lambda} \cdot P$ [$ergs \cdot cm^{-2} \cdot s^{-1} \cdot \AA^{-1}$]") # levelsPf = np.linspace(0.0175, 0.50, 5) * pfmax levelsPf = np.array([1.73, 13.0, 33.0, 66.0]) / 100.0 * pfmax - print("Polarized flux contour levels : ", levelsPf) + print("Polarized flux density contour levels : ", levelsPf) ax.contour(stkI * convert_flux * pol, levels=levelsPf, colors="grey", linewidths=0.5) elif display.lower() in ["p", "pol", "pol_deg"]: # Display polarization degree map From b218279fefdd8fc0da52deab4a2f6b96fda7f729 Mon Sep 17 00:00:00 2001 From: Thibault Barnouin Date: Thu, 19 Dec 2024 11:39:56 +0100 Subject: [PATCH 17/18] add script to read/dump/plot fos spectropol --- package/src/readfos.py | 419 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 419 insertions(+) create mode 100755 package/src/readfos.py diff --git a/package/src/readfos.py b/package/src/readfos.py new file mode 100755 index 0000000..2f88c0e --- /dev/null +++ b/package/src/readfos.py @@ -0,0 +1,419 @@ +#!/usr/bin/env python3 +import matplotlib.pyplot as plt +import numpy as np +from astropy.io.fits import getheader, getdata, hdu +from os.path import join as join_path, exists as path_exists +from os import system +from copy import deepcopy + +# consecutive spectra are made up of the summ of all previous ACCUMs, so the S/N increases along sequence +# _c0f.fits - calibrated vacuum wavelength +# _c1f.fits - calibrated fluxes (ergs sec^-1 cm^-2 Angs^-1) +# _c2f.fits - statistical errors (no sky, bkg subtraction, flatfield or sensitivity error) +# _c3f.fits - for SPECTROPOLARIMETRY mode contains I, Q, U, V, linear and circular polarization and polarization position angle +# _c4f.fits - object+sky count rate spectrum (corrected for overscanning, noise rejection, lost signal) +# _c5f.fits - flat-fielded object count rate spectrum (corrected for paired pulses, detector background, flatfield structure, GIM effects) +# _c6f.fits - flat-fielded sky count rate spectrum (corrected for paired pulses, detector background, flatfield structure, GIM effects) +# _c7f.fits - background count rate spectrum (scaled background subtracted from c4 products) +# _c8f.fits - flat-fielded and sky-subtracted object count rate spectrum + + +def princ_angle(ang): + """ + Return the principal angle in the 0° to 180° quadrant as PA is always + defined at p/m 180°. + ---------- + Inputs: + ang : float, numpy.ndarray + Angle in degrees. Can be an array of angles. + ---------- + Returns: + princ_ang : float, numpy.ndarray + Principal angle in the 0°-180° quadrant in the same shape as input. + """ + if not isinstance(ang, np.ndarray): + A = np.array([ang]) + else: + A = np.array(ang) + while np.any(A < 0.0): + A[A < 0.0] = A[A < 0.0] + 360.0 + while np.any(A >= 180.0): + A[A >= 180.0] = A[A >= 180.0] - 180.0 + if type(ang) is type(A): + return A + else: + return A[0] + + +class specpol(object): + """ + Class object for studying spectropolarimetry. + """ + + def __init__(self, other=None): + if isinstance(other, specpol): + # Copy constructor + self.wav = deepcopy(other.wav) + self.wav_err = deepcopy(other.wav_err) + self.I = deepcopy(other.I) + self.Q = deepcopy(other.Q) + self.U = deepcopy(other.U) + self.V = deepcopy(other.V) + self.IQU_cov = deepcopy(other.IQU_cov) + else: + # Initialise to zero + if isinstance(other, int): + self.zero(other) + else: + self.zero() + + @classmethod + def zero(self, n=1): + """ + Set all values to zero. + """ + self.wav = np.zeros(n) + self.wav_err = np.zeros((n, 2)) + self.I = np.zeros(n) + self.Q = np.zeros(n) + self.U = np.zeros(n) + self.V = np.zeros(n) + self.IQU_cov = np.zeros((4, 4, n)) + + @property + def I_err(self): + return np.sqrt(self.IQU_cov[0][0]) + + @property + def Q_err(self): + return np.sqrt(self.IQU_cov[1][1]) + + @property + def U_err(self): + return np.sqrt(self.IQU_cov[2][2]) + + @property + def V_err(self): + return np.sqrt(self.IQU_cov[3][3]) + + @property + def QN(self): + return self.Q / np.where(self.I > 0, self.I, np.nan) + + @property + def QN_err(self): + return self.Q_err / np.where(self.I > 0, self.I, np.nan) + + @property + def UN(self): + return self.U / np.where(self.I > 0, self.I, np.nan) + + @property + def UN_err(self): + return self.U_err / np.where(self.I > 0, self.I, np.nan) + + @property + def VN(self): + return self.V / np.where(self.I > 0, self.I, np.nan) + + @property + def VN_err(self): + return self.V_err / np.where(self.I > 0, self.I, np.nan) + + @property + def PF(self): + return np.sqrt(self.Q**2 + self.U**2 + self.V**2) + + @property + def PF_err(self): + return np.sqrt(self.Q**2 * self.Q_err**2 + self.U**2 * self.U_err**2 + self.V**2 * self.V_err**2) / np.where(self.PF > 0, self.PF, np.nan) + + @property + def P(self): + return self.PF / np.where(self.I > 0, self.I, np.nan) + + @property + def P_err(self): + return np.sqrt(self.PF_err**2 + (self.PF / self.I) ** 2 * self.I_err**2) / np.where(self.I > 0, self.I, np.nan) + + @property + def PA(self): + return princ_angle((90.0 / np.pi) * np.arctan2(self.U, self.Q)) + + @property + def PA_err(self): + return princ_angle((90.0 / np.pi) * np.sqrt(self.U**2 * self.Q_err**2 + self.Q**2 * self.U_err**2) / np.where(self.PF > 0, self.PF**2, np.nan)) + + def rotate(self, angle): + alpha = np.pi / 180.0 * angle + mrot = np.array( + [ + [1.0, 0.0, 0.0, 0.0], + [0.0, np.cos(2.0 * alpha), np.sin(2.0 * alpha), 0.0], + [0.0, -np.sin(2.0 * alpha), np.cos(2.0 * alpha), 0.0], + [0.0, 0.0, 0.0, 1.0], + ] + ) + self.I, self.Q, self.U, self.V = np.dot(mrot, np.array([self.I, self.Q, self.U, self.V])) + self.IQU_cov = np.dot(mrot, np.dot(self.IQU_cov.T, mrot.T).T) + + def bin_size(self, size): + """ + Rebin spectra to selected bin size in Angstrom. + """ + bin_edges = np.arange(np.floor(self.wav.min()), np.ceil(self.wav.max()), size) + in_bin = np.digitize(self.wav, bin_edges) - 1 + spec_b = specpol(bin_edges.shape[0] - 1) + for i in range(bin_edges.shape[0] - 1): + spec_b.wav[i] = np.mean(self.wav[in_bin == i]) + spec_b.wav_err[i] = (spec_b.wav[i] - bin_edges[i], bin_edges[i + 1] - spec_b.wav[i]) + + spec_b.I[i] = np.sum(self.I[in_bin == i]) + spec_b.Q[i] = np.sum(self.Q[in_bin == i]) + spec_b.U[i] = np.sum(self.U[in_bin == i]) + spec_b.V[i] = np.sum(self.V[in_bin == i]) + for m in range(4): + spec_b.IQU_cov[m][m][i] = np.sum(self.IQU_cov[m][m][in_bin == i]) + for n in [k for k in range(4) if k != m]: + spec_b.IQU_cov[m][n][i] = np.sqrt(np.sum(self.IQU_cov[m][n][in_bin == i] ** 2)) + return spec_b + + def dump_txt(self, filename, output_dir=""): + """ + Dump current spectra to a text file. + """ + data_dump = np.array([self.wav, self.I, self.Q, self.U, self.V, self.P, self.PA]).T + np.savetxt(join_path(output_dir, filename + ".txt"), data_dump) + return join_path(output_dir, filename) + + def plot(self, fig=None, ax=None, savename=None, plots_folder=""): + """ + Display current spectra. + """ + if fig is None: + if ax is None: + self.fig, self.ax = plt.subplots(1, 2, sharex=True, figsize=(20, 5), layout="constrained") + else: + self.ax = ax + else: + if ax is None: + self.fig = fig + self.ax = self.fig.add_subplot(111) + else: + self.fig = fig + self.ax = ax + + self.ax[0].set_xlabel(r"Wavelength [$\AA$]") + self.ax[1].set_xlabel(r"Wavelength [$\AA$]") + + self.ax[0].errorbar(self.wav, self.I, xerr=self.wav_err.T, yerr=self.I_err, color="k", fmt=".", label="I") + self.ax[0].errorbar(self.wav, self.PF, xerr=self.wav_err.T, yerr=self.PF_err, color="b", fmt=".", label="PF") + self.ax[0].set_ylabel(r"F$_\lambda$ [erg s$^{-1}$ cm$^{-2} \AA^{-1}$]") + self.ax[0].legend() + # ax1 = self.ax[0].twinx() + # ax1.errorbar(self.wav, self.QN, xerr=self.wav_err.T, yerr=self.QN_err, fmt=".", label="QN") + # ax1.errorbar(self.wav, self.UN, xerr=self.wav_err.T, yerr=self.UN_err, fmt=".", label="UN") + # ax1.errorbar(self.wav, self.VN, xerr=self.wav_err.T, yerr=self.VN_err, fmt=".", label="VN") + # ax1.set_ylim([-1.0, 1.0]) + # ax1.set_ylabel(r"Normalised stokes flux", color="g") + # ax1.tick_params(axis="y", color="g", labelcolor="g") + # h0, l0 = self.ax[0].get_legend_handles_labels() + # h1, l1 = ax1.get_legend_handles_labels() + # self.ax[0].legend(h0 + h1, l0 + l1, ncols=5) + + self.ax[1].errorbar(self.wav, self.P, xerr=self.wav_err.T, yerr=self.P_err, color="b", fmt=".", label="P") + self.ax[1].set_ylim([0.0, 1.0]) + self.ax[1].set_ylabel(r"P", color="b") + self.ax[1].tick_params(axis="y", color="b", labelcolor="b") + ax2 = self.ax[1].twinx() + ax2.errorbar(self.wav, self.PA, xerr=self.wav_err.T, yerr=self.PA_err, color="r", fmt=".", label="PA [°]") + ax2.set_ylim([0.0, 180.0]) + ax2.set_ylabel(r"PA", color="r") + ax2.tick_params(axis="y", color="r", labelcolor="r") + + if hasattr(self, "fig") and savename is not None: + self.fig.savefig(join_path(plots_folder, savename + ".pdf"), dpi=300, bbox_inches="tight") + return self.fig, self.ax, join_path(plots_folder, savename + ".pdf") + elif hasattr(self, "fig"): + return self.fig, self.ax + else: + return self.ax + + +class FOSspecpol(specpol): + """ + Class object for studying FOS SPECTROPOLARYMETRY mode spectra. + """ + + def __init__(self, stokes, data_folder=""): + """ + Initialise object from fits filename or hdulist. + """ + if isinstance(stokes, str): + self.file_root = stokes.split("_")[0] + self.hd = getheader(join_path(data_folder, self.file_root + "_c0f.fits")) + wav = getdata(join_path(data_folder, self.file_root + "_c0f.fits")) + stokes = getdata(join_path(data_folder, self.file_root + "_c3f.fits")) + elif isinstance(stokes, hdu.hdulist.HDUList): + self.hd = stokes.header + self.file_root = self.hd["FILENAME"].split("_")[0] + wav = getdata(join_path(data_folder, self.file_root + "_c0f")) + stokes = stokes.data + else: + raise ValueError("Input must be a path to a fits file or an HDUlist") + + self.wav = np.concat((wav[0:2, :], wav[0].reshape(1, wav.shape[1]), wav[0].reshape(1, wav.shape[1])), axis=0) + self.wav_err = np.zeros((self.wav.shape[0], self.wav.shape[1], 2)) + + self.IQU_cov = np.zeros((4, 4, self.wav.shape[0], self.wav.shape[1])) + + self.I = stokes[0::14] + self.IQU_cov[0, 0] = stokes[4::14] ** 2 + self.Q = stokes[1::14] + self.IQU_cov[1, 1] = stokes[5::14] ** 2 + self.U = stokes[2::14] + self.IQU_cov[2, 2] = stokes[6::14] ** 2 + self.V = stokes[3::14] + self.IQU_cov[3, 3] = stokes[7::14] ** 2 + + self.subspec = {} + for i, name in enumerate(["PASS1", "PASS2", "PASS12", "PASS12corr"]): + spec = specpol(self.wav[i].shape[0]) + spec.wav, spec.wav_err, spec.I, spec.Q, spec.U, spec.V = self.wav[i], self.wav_err[i], self.I[i], self.Q[i], self.U[i], self.V[i] + spec.IQU_cov = self.IQU_cov[:, :, i, :] + spec.rotate((i != 3) * self.hd["PA_APER"]) + self.subspec[name] = spec + + self.P_fos = stokes[8::14] + self.P_fos_err = stokes[11::14] + self.PC_fos = stokes[9::14] + self.PC_fos_err = stokes[12::14] + self.PA_fos = princ_angle( + np.degrees(stokes[10::14]) + np.concat((np.ones((3, stokes.shape[1])), np.zeros((1, stokes.shape[1]))), axis=0) * self.hd["PA_APER"] + ) + self.PA_fos_err = princ_angle(np.degrees(stokes[13::14])) + + def __del__(self): + if hasattr(self, "ax"): + del self.ax + if hasattr(self, "fig"): + del self.fig + + def dump_txt(self, filename, output_dir=""): + """ + Dump current spectra to a text file. + """ + outfiles = [] + for i in range(min(self.wav.shape[0], 4)): + data_dump = np.array([self.wav[i], self.I[i], self.Q[i], self.U[i], self.V[i], self.P[i], self.PA[i]]).T + np.savetxt(join_path(output_dir, filename + "_%d.txt" % i), data_dump) + outfiles.append(join_path(output_dir, filename + "_%d" % i)) + return outfiles + + def plot(self, savename=None, plots_folder=""): + """ + Display current spectra in single figure. + """ + outfiles = [] + if hasattr(self, "ax"): + del self.ax + if hasattr(self, "fig"): + del self.fig + self.fig, self.ax = plt.subplots(min(self.wav.shape[0], 4), 2, sharex=True, figsize=(20, 10), layout="constrained") + self.ax[-1][0].set_xlabel(r"Wavelength [$\AA$]", size="large") + self.ax[-1][1].set_xlabel(r"Wavelength [$\AA$]", size="large") + for i, name in enumerate(["Pass Direction 1", "Pass Direction 2", "Pass Direction 1&2", "Pass Direction 1&2 corrected"]): + self.ax[i][0].set_title(name) + + self.ax[i][0].errorbar(self.wav[i], self.I[i], xerr=self.wav_err[i].T, yerr=self.I_err[i], color="k", fmt=".", label="I") + self.ax[i][0].errorbar( + self.wav[i], + self.P_fos[i] * self.I[i], + xerr=self.wav_err[i].T, + yerr=(self.P_fos_err[i] * self.I[i] + self.P_fos_err[i] * self.I_err[i]), + color="b", + fmt=".", + label="PF_fos", + ) + self.ax[i][0].set_ylabel(r"F$_\lambda$ [erg s$^{-1}$ cm$^{-2} \AA^{-1}$]") + # ax1 = self.ax[i][0].twinx() + # ax1.errorbar(self.wav[i], self.QN[i], xerr=self.wav_err[i].T, yerr=self.QN_err[i], fmt=".", label="QN") + # ax1.errorbar(self.wav[i], self.UN[i], xerr=self.wav_err[i].T, yerr=self.UN_err[i], fmt=".", label="UN") + # ax1.errorbar(self.wav[i], self.VN[i], xerr=self.wav_err[i].T, yerr=self.VN_err[i], fmt=".", label="VN") + # ax1.set_ylabel(r"Normalised stokes flux", color="g") + # ax1.tick_params(axis="y", color="g", labelcolor="g") + # ax1.set_ylim([-1.0, 1.0]) + # h0, l0 = self.ax[i][0].get_legend_handles_labels() + # h1, l1 = ax1.get_legend_handles_labels() + # self.ax[i][0].legend(h0 + h1, l0 + l1, ncols=5) + self.ax[i][0].legend() + + self.ax[i][1].errorbar(self.wav[i], self.P_fos[i], xerr=self.wav_err[i].T, yerr=self.P_fos_err[i], color="b", fmt=".", label="P_fos") + self.ax[i][1].set(ylabel=r"P_fos", ylim=[0.0, 1.0]) + ax2 = self.ax[i][1].twinx() + ax2.errorbar(self.wav[i], self.PA_fos[i], xerr=self.wav_err[i].T, yerr=self.PA_fos_err[i], color="r", fmt=".", label="P_fos") + ax2.set_ylabel(r"PA_fos", color="r") + ax2.tick_params(axis="y", color="r", labelcolor="r") + ax2.set_ylim([0.0, 180.0]) + + self.fig.suptitle("_".join([self.hd["TARGNAME"], str(self.hd["PROPOSID"]), self.hd["FILENAME"], self.hd["APER_ID"]])) + if savename is not None: + self.fig.savefig(join_path(plots_folder, savename + ".pdf"), dpi=300, bbox_inches="tight") + outfiles.append(join_path(plots_folder, savename + ".pdf")) + return outfiles + + def bin_size(self, size): + """ + Rebin spectra to selected bin size in Angstrom. + """ + self.bin_edges = np.arange(np.floor(self.wav_fos.min()), np.ceil(self.wav_fos.max()), size) + self.in_bin = np.zeros(self.wav_fos.shape) + for i in range(self.wav_fos.shape[0]): + self.in_bin[i] = np.digitize(self.wav_fos[i], self.bin_edges) - 1 + + +def main(infiles, output_dir=None): + outfiles = [] + if infiles is not None: + prod = np.array([["/".join(filepath.split("/")[:-1]), filepath.split("/")[-1]] for filepath in infiles], dtype=str) + obs_dir = "/".join(infiles[0].split("/")[:-1]) + if not path_exists(obs_dir): + system("mkdir -p {0:s} {1:s}".format(obs_dir, obs_dir.replace("data", "plots"))) + else: + print("Must input files to process.") + return 1 + data_folder = prod[0][0] + if output_dir is None: + output_dir = data_folder + try: + plots_folder = data_folder.replace("data", "plots") + except ValueError: + plots_folder = "." + if not path_exists(plots_folder): + system("mkdir -p {0:s} ".format(plots_folder)) + infiles = [p[1] for p in prod] + + roots = np.unique([file.split("_")[0] for file in infiles]) + for file_root in roots: + print(file_root) + spec = FOSspecpol(file_root, data_folder) + filename = "_".join([spec.hd["TARGNAME"], "FOS", str(spec.hd["PROPOSID"]), spec.file_root, spec.hd["APER_ID"]]) + outfiles += spec.dump_txt(filename, output_dir) + outfiles += spec.plot(filename, plots_folder) + del spec + plt.show() + + return outfiles + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="Display and dump FOS Spectropolarimetry") + parser.add_argument("-f", "--files", metavar="path", required=False, nargs="*", help="the full or relative path to the data products", default=None) + parser.add_argument( + "-o", "--output_dir", metavar="directory_path", required=False, help="output directory path for the data products", type=str, default=None + ) + args = parser.parse_args() + exitcode = main(infiles=args.files, output_dir=args.output_dir) + print("Written to: ", exitcode) From 729720c5bb76f7db823d4d7f7a41bae1ca342840 Mon Sep 17 00:00:00 2001 From: Thibault Barnouin Date: Thu, 19 Dec 2024 16:46:01 +0100 Subject: [PATCH 18/18] add batch binning in FOSspecpol in readfos scr --- package/src/readfos.py | 161 +++++++++++++++++++++-------------------- 1 file changed, 84 insertions(+), 77 deletions(-) diff --git a/package/src/readfos.py b/package/src/readfos.py index 2f88c0e..8a32cd1 100755 --- a/package/src/readfos.py +++ b/package/src/readfos.py @@ -98,43 +98,53 @@ class specpol(object): @property def QN(self): + np.seterr(divide="ignore", invalid="ignore") return self.Q / np.where(self.I > 0, self.I, np.nan) @property def QN_err(self): + np.seterr(divide="ignore", invalid="ignore") return self.Q_err / np.where(self.I > 0, self.I, np.nan) @property def UN(self): + np.seterr(divide="ignore", invalid="ignore") return self.U / np.where(self.I > 0, self.I, np.nan) @property def UN_err(self): + np.seterr(divide="ignore", invalid="ignore") return self.U_err / np.where(self.I > 0, self.I, np.nan) @property def VN(self): + np.seterr(divide="ignore", invalid="ignore") return self.V / np.where(self.I > 0, self.I, np.nan) @property def VN_err(self): + np.seterr(divide="ignore", invalid="ignore") return self.V_err / np.where(self.I > 0, self.I, np.nan) @property def PF(self): + np.seterr(divide="ignore", invalid="ignore") return np.sqrt(self.Q**2 + self.U**2 + self.V**2) @property def PF_err(self): + np.seterr(divide="ignore", invalid="ignore") return np.sqrt(self.Q**2 * self.Q_err**2 + self.U**2 * self.U_err**2 + self.V**2 * self.V_err**2) / np.where(self.PF > 0, self.PF, np.nan) @property def P(self): + np.seterr(divide="ignore", invalid="ignore") return self.PF / np.where(self.I > 0, self.I, np.nan) @property def P_err(self): - return np.sqrt(self.PF_err**2 + (self.PF / self.I) ** 2 * self.I_err**2) / np.where(self.I > 0, self.I, np.nan) + np.seterr(divide="ignore", invalid="ignore") + return np.where(self.I > 0, np.sqrt(self.PF_err**2 + (self.PF / self.I) ** 2 * self.I_err**2) / self.I, np.nan) @property def PA(self): @@ -202,34 +212,33 @@ class specpol(object): else: self.fig = fig self.ax = ax + if isinstance(ax, np.ndarray): + ax1, ax2 = self.ax[:2] + else: + ax1 = self.ax - self.ax[0].set_xlabel(r"Wavelength [$\AA$]") - self.ax[1].set_xlabel(r"Wavelength [$\AA$]") + # Display flux and polarized flux on first ax + ax1.set_xlabel(r"Wavelength [$\AA$]") + ax1.errorbar(self.wav, self.I, xerr=self.wav_err.T, yerr=self.I_err, color="k", fmt=".", label="I") + ax1.errorbar(self.wav, self.PF, xerr=self.wav_err.T, yerr=self.PF_err, color="b", fmt=".", label="PF") + ax1.set_ylabel(r"F$_\lambda$ [erg s$^{-1}$ cm$^{-2} \AA^{-1}$]") + ax1.legend(ncols=2, loc=1) - self.ax[0].errorbar(self.wav, self.I, xerr=self.wav_err.T, yerr=self.I_err, color="k", fmt=".", label="I") - self.ax[0].errorbar(self.wav, self.PF, xerr=self.wav_err.T, yerr=self.PF_err, color="b", fmt=".", label="PF") - self.ax[0].set_ylabel(r"F$_\lambda$ [erg s$^{-1}$ cm$^{-2} \AA^{-1}$]") - self.ax[0].legend() - # ax1 = self.ax[0].twinx() - # ax1.errorbar(self.wav, self.QN, xerr=self.wav_err.T, yerr=self.QN_err, fmt=".", label="QN") - # ax1.errorbar(self.wav, self.UN, xerr=self.wav_err.T, yerr=self.UN_err, fmt=".", label="UN") - # ax1.errorbar(self.wav, self.VN, xerr=self.wav_err.T, yerr=self.VN_err, fmt=".", label="VN") - # ax1.set_ylim([-1.0, 1.0]) - # ax1.set_ylabel(r"Normalised stokes flux", color="g") - # ax1.tick_params(axis="y", color="g", labelcolor="g") - # h0, l0 = self.ax[0].get_legend_handles_labels() - # h1, l1 = ax1.get_legend_handles_labels() - # self.ax[0].legend(h0 + h1, l0 + l1, ncols=5) - - self.ax[1].errorbar(self.wav, self.P, xerr=self.wav_err.T, yerr=self.P_err, color="b", fmt=".", label="P") - self.ax[1].set_ylim([0.0, 1.0]) - self.ax[1].set_ylabel(r"P", color="b") - self.ax[1].tick_params(axis="y", color="b", labelcolor="b") - ax2 = self.ax[1].twinx() - ax2.errorbar(self.wav, self.PA, xerr=self.wav_err.T, yerr=self.PA_err, color="r", fmt=".", label="PA [°]") - ax2.set_ylim([0.0, 180.0]) - ax2.set_ylabel(r"PA", color="r") - ax2.tick_params(axis="y", color="r", labelcolor="r") + if isinstance(ax, np.ndarray): + # When given 2 axes, display P and PA on second + ax2.set_xlabel(r"Wavelength [$\AA$]") + ax2.errorbar(self.wav, self.P, xerr=self.wav_err.T, yerr=self.P_err, color="b", fmt=".", label="P") + ax2.set_ylim([0.0, 1.0]) + ax2.set_ylabel(r"P", color="b") + ax2.tick_params(axis="y", color="b", labelcolor="b") + ax22 = ax2.twinx() + ax22.errorbar(self.wav, self.PA, xerr=self.wav_err.T, yerr=self.PA_err, color="r", fmt=".", label="PA [°]") + ax22.set_ylim([0.0, 180.0]) + ax22.set_ylabel(r"PA", color="r") + ax22.tick_params(axis="y", color="r", labelcolor="r") + h2, l2 = ax2.get_legend_handles_labels() + h22, l22 = ax22.get_legend_handles_labels() + ax2.legend(h2 + h22, l2 + l22, ncols=2, loc=1) if hasattr(self, "fig") and savename is not None: self.fig.savefig(join_path(plots_folder, savename + ".pdf"), dpi=300, bbox_inches="tight") @@ -299,18 +308,18 @@ class FOSspecpol(specpol): if hasattr(self, "fig"): del self.fig - def dump_txt(self, filename, output_dir=""): + def dump_txt(self, filename, spec_list=None, output_dir=""): """ Dump current spectra to a text file. """ outfiles = [] - for i in range(min(self.wav.shape[0], 4)): - data_dump = np.array([self.wav[i], self.I[i], self.Q[i], self.U[i], self.V[i], self.P[i], self.PA[i]]).T - np.savetxt(join_path(output_dir, filename + "_%d.txt" % i), data_dump) - outfiles.append(join_path(output_dir, filename + "_%d" % i)) + if spec_list is None: + spec_list = self.subspec + for i, name in enumerate(["PASS1", "PASS2", "PASS12", "PASS12corr"]): + outfiles.append(spec_list[name].dump_txt(filename="_".join([filename, name]), output_dir=output_dir)) return outfiles - def plot(self, savename=None, plots_folder=""): + def plot(self, spec_list=None, savename=None, plots_folder="", fos=False): """ Display current spectra in single figure. """ @@ -319,42 +328,31 @@ class FOSspecpol(specpol): del self.ax if hasattr(self, "fig"): del self.fig - self.fig, self.ax = plt.subplots(min(self.wav.shape[0], 4), 2, sharex=True, figsize=(20, 10), layout="constrained") - self.ax[-1][0].set_xlabel(r"Wavelength [$\AA$]", size="large") - self.ax[-1][1].set_xlabel(r"Wavelength [$\AA$]", size="large") - for i, name in enumerate(["Pass Direction 1", "Pass Direction 2", "Pass Direction 1&2", "Pass Direction 1&2 corrected"]): - self.ax[i][0].set_title(name) - - self.ax[i][0].errorbar(self.wav[i], self.I[i], xerr=self.wav_err[i].T, yerr=self.I_err[i], color="k", fmt=".", label="I") - self.ax[i][0].errorbar( - self.wav[i], - self.P_fos[i] * self.I[i], - xerr=self.wav_err[i].T, - yerr=(self.P_fos_err[i] * self.I[i] + self.P_fos_err[i] * self.I_err[i]), - color="b", - fmt=".", - label="PF_fos", - ) - self.ax[i][0].set_ylabel(r"F$_\lambda$ [erg s$^{-1}$ cm$^{-2} \AA^{-1}$]") - # ax1 = self.ax[i][0].twinx() - # ax1.errorbar(self.wav[i], self.QN[i], xerr=self.wav_err[i].T, yerr=self.QN_err[i], fmt=".", label="QN") - # ax1.errorbar(self.wav[i], self.UN[i], xerr=self.wav_err[i].T, yerr=self.UN_err[i], fmt=".", label="UN") - # ax1.errorbar(self.wav[i], self.VN[i], xerr=self.wav_err[i].T, yerr=self.VN_err[i], fmt=".", label="VN") - # ax1.set_ylabel(r"Normalised stokes flux", color="g") - # ax1.tick_params(axis="y", color="g", labelcolor="g") - # ax1.set_ylim([-1.0, 1.0]) - # h0, l0 = self.ax[i][0].get_legend_handles_labels() - # h1, l1 = ax1.get_legend_handles_labels() - # self.ax[i][0].legend(h0 + h1, l0 + l1, ncols=5) - self.ax[i][0].legend() - - self.ax[i][1].errorbar(self.wav[i], self.P_fos[i], xerr=self.wav_err[i].T, yerr=self.P_fos_err[i], color="b", fmt=".", label="P_fos") - self.ax[i][1].set(ylabel=r"P_fos", ylim=[0.0, 1.0]) - ax2 = self.ax[i][1].twinx() - ax2.errorbar(self.wav[i], self.PA_fos[i], xerr=self.wav_err[i].T, yerr=self.PA_fos_err[i], color="r", fmt=".", label="P_fos") - ax2.set_ylabel(r"PA_fos", color="r") - ax2.tick_params(axis="y", color="r", labelcolor="r") - ax2.set_ylim([0.0, 180.0]) + if spec_list is None: + spec_list = self.subspec + self.fig, self.ax = plt.subplots(4, 2, sharex=True, sharey="col", figsize=(20, 10), layout="constrained") + for i, (name, title) in enumerate( + [("PASS1", "Pass Direction 1"), ("PASS2", "Pass Direction 2"), ("PASS12", "Pass Direction 1&2"), ("PASS12corr", "Pass Direction 1&2 corrected")] + ): + self.ax[i][0].set_title(title) + if fos: + self.ax[i][0] = spec_list[name].plot(ax=self.ax[i][0]) + self.ax[i][1].set_xlabel(r"Wavelength [$\AA$]") + self.ax[i][1].errorbar(self.wav[i], self.P_fos[i], xerr=self.wav_err[i].T, yerr=self.P_fos_err[i], color="b", fmt=".", label="P_fos") + self.ax[i][1].set_ylim([0.0, 1.0]) + self.ax[i][1].set_ylabel(r"P", color="b") + self.ax[i][1].tick_params(axis="y", color="b", labelcolor="b") + ax22 = self.ax[i][1].twinx() + ax22.errorbar(self.wav[i], self.PA_fos[i], xerr=self.wav_err[i].T, yerr=self.PA_fos_err[i], color="r", fmt=".", label="PA_fos [°]") + ax22.set_ylim([0.0, 180.0]) + ax22.set_ylabel(r"PA", color="r") + ax22.tick_params(axis="y", color="r", labelcolor="r") + h2, l2 = self.ax[i][1].get_legend_handles_labels() + h22, l22 = ax22.get_legend_handles_labels() + self.ax[i][1].legend(h2 + h22, l2 + l22, ncols=2, loc=1) + else: + self.ax[i] = spec_list[name].plot(ax=self.ax[i]) + self.ax[0][0].set_ylim(ymin=0.0) self.fig.suptitle("_".join([self.hd["TARGNAME"], str(self.hd["PROPOSID"]), self.hd["FILENAME"], self.hd["APER_ID"]])) if savename is not None: @@ -366,13 +364,15 @@ class FOSspecpol(specpol): """ Rebin spectra to selected bin size in Angstrom. """ - self.bin_edges = np.arange(np.floor(self.wav_fos.min()), np.ceil(self.wav_fos.max()), size) - self.in_bin = np.zeros(self.wav_fos.shape) - for i in range(self.wav_fos.shape[0]): - self.in_bin[i] = np.digitize(self.wav_fos[i], self.bin_edges) - 1 + key = "{0:.2f}bin".format(size) + if key not in self.subspec.keys(): + self.subspec[key] = dict([]) + for name in ["PASS1", "PASS2", "PASS12", "PASS12corr"]: + self.subspec[key][name] = self.subspec[name].bin_size(size) + return self.subspec[key] -def main(infiles, output_dir=None): +def main(infiles, bin_size=None, output_dir=None): outfiles = [] if infiles is not None: prod = np.array([["/".join(filepath.split("/")[:-1]), filepath.split("/")[-1]] for filepath in infiles], dtype=str) @@ -398,8 +398,14 @@ def main(infiles, output_dir=None): print(file_root) spec = FOSspecpol(file_root, data_folder) filename = "_".join([spec.hd["TARGNAME"], "FOS", str(spec.hd["PROPOSID"]), spec.file_root, spec.hd["APER_ID"]]) - outfiles += spec.dump_txt(filename, output_dir) - outfiles += spec.plot(filename, plots_folder) + if bin_size is not None: + key = "{0:.2f}bin".format(bin_size) + spec.bin_size(bin_size) + outfiles += spec.dump_txt("_".join([filename, key]), spec_list=spec.subspec[key], output_dir=output_dir) + outfiles += spec.plot(savename="_".join([filename, key]), spec_list=spec.subspec[key], plots_folder=plots_folder) + else: + outfiles += spec.dump_txt(filename, output_dir=output_dir) + outfiles += spec.plot(savename=filename, plots_folder=plots_folder) del spec plt.show() @@ -411,9 +417,10 @@ if __name__ == "__main__": parser = argparse.ArgumentParser(description="Display and dump FOS Spectropolarimetry") parser.add_argument("-f", "--files", metavar="path", required=False, nargs="*", help="the full or relative path to the data products", default=None) + parser.add_argument("-b", "--bin", metavar="bin_size", required=False, help="The bin size to resample spectra", type=float, default=None) parser.add_argument( "-o", "--output_dir", metavar="directory_path", required=False, help="output directory path for the data products", type=str, default=None ) args = parser.parse_args() - exitcode = main(infiles=args.files, output_dir=args.output_dir) + exitcode = main(infiles=args.files, bin_size=args.bin, output_dir=args.output_dir) print("Written to: ", exitcode)