From e43c03f1bc46f73b4fd4304fbfa67891f9b1c2c3 Mon Sep 17 00:00:00 2001 From: Victor de Souza Magalhaes Date: Fri, 27 Feb 2026 11:38:44 -0700 Subject: [PATCH 1/9] First pass at a beamcut phase implementation. --- src/astrohack/io/beamcut_mds.py | 162 +++++++++++++++++++++++++++++++- 1 file changed, 160 insertions(+), 2 deletions(-) diff --git a/src/astrohack/io/beamcut_mds.py b/src/astrohack/io/beamcut_mds.py index 7f55c212..5c8660d5 100644 --- a/src/astrohack/io/beamcut_mds.py +++ b/src/astrohack/io/beamcut_mds.py @@ -1,6 +1,6 @@ import pathlib import numpy as np -from typing import List, Union +from typing import List, Union, Tuple from toolviper.utils.parameter import validate @@ -293,6 +293,31 @@ def plot_beam_cuts_over_sky( ) return + def plot_beamcut_in_phase( + self, + destination: str, + ant: Union[str, List[str]] = "all", + ddi: Union[str, int, List[int]] = "all", + lm_unit: str = "amin", + azel_unit: str = "deg", + phase_unit: str = "deg", + phase_scale: Union[List[float], Tuple[float], np.array] = None, + display: bool = False, + dpi: int = 300, + parallel: bool = False, + ) -> None: + param_dict = locals() + + pathlib.Path(param_dict["destination"]).mkdir(exist_ok=True) + create_and_execute_graph_from_dict( + looping_dict=self, + chunk_function=_plot_beamcut_in_phase_chunk, + param_dict=param_dict, + key_order=["ant", "ddi"], + parallel=parallel, + ) + return + @validate(custom_checker=custom_plots_checker) def create_beam_fit_report( self, @@ -407,6 +432,32 @@ def _plot_cuts_in_lm_chunk(par_dict): _plot_cuts_in_lm_sub(cut_xdtree, par_dict) +def _plot_beamcut_in_phase_chunk(par_dict): + """ + Produce phase beam cut plots from a xdtree containing beam cuts. + + :param par_dict: Paremeter dictionary controlling plot aspects + :type par_dict: dict + + :return: None + :rtype: NoneType + """ + cut_xdtree = par_dict["xdt_data"] + n_cuts = len(cut_xdtree.children.values()) + # Loop over cuts + fig, axes = create_figure_and_axes([12, 1 + n_cuts * 4], [n_cuts, 2]) + for icut, cut_xds in enumerate(cut_xdtree.children.values()): + _plot_single_cut_in_phase(cut_xds, axes[icut, :], par_dict) + + # Header creation + summary = cut_xdtree.attrs["summary"] + title = _create_beamcut_header(summary, par_dict) + + filename = _file_name_factory("phase", par_dict) + close_figure(fig, title, filename, par_dict["dpi"], par_dict["display"]) + return + + def _create_report_chunk(par_dict, spacing=2, item_marker="-", precision=3): """ Produce a report on beamcut fit results from a xdtree containing beam cuts. @@ -486,7 +537,7 @@ def _file_name_factory(file_type, par_dict): destination = par_dict["destination"] antenna = par_dict["this_ant"] ddi = par_dict["this_ddi"] - if file_type in ["attenuation", "amplitude", "lm_offsets"]: + if file_type in ["attenuation", "amplitude", "lm_offsets", "phase"]: ext = "png" elif file_type == "report": ext = "txt" @@ -710,6 +761,113 @@ def _plot_single_cut_in_amplitude(cut_xds, axes, par_dict): ) +def _plot_single_cut_in_phase(cut_xds, axes, par_dict): + """ + Plot a single beam cut in phase with each correlation in a different panel + + :param cut_xds: xarray dataset containing the beamcut + :type cut_xds: xarray.Dataset + + :param axes: numpy array with the Matplotlib Axes objects for the different panels + :type axes: numpy.array([Matplotlib.axes.Axes]) + + :param par_dict: Parameter dictionary containing plot configuration + :type par_dict: dict + + :return: None + :rtype: NoneType + """ + # Init + sub_title = _make_parallel_hand_sub_title(cut_xds.attrs) + phase_unit = par_dict["phase_unit"] + phase_fac = convert_unit("rad", phase_unit, "trigonometric") + lm_unit = par_dict["lm_unit"] + lm_fac = convert_unit("rad", lm_unit, "trigonometric") + + phase_scale = par_dict["phase_scale"] + if phase_scale is None: + phase_scale = phase_fac * np.array([-np.pi, np.pi]) + # max_amp = cut_xds.attrs["all_corr_ymax"] + y_off = 0.05 * (phase_scale[1] - phase_scale[0]) + + # Loop over correlations + for i_corr, parallel_hand in enumerate(cut_xds.attrs["available_corrs"]): + # Init labels + this_ax = axes[i_corr] + x_data = lm_fac * cut_xds["lm_dist"].values + y_data = phase_fac * cut_xds[f"{parallel_hand}_phase"].values + raw_fit_data = cut_xds[f"{parallel_hand}_amp_fit"].values + max_fit_data = np.max(raw_fit_data) + fit_data = phase_fac * ((np.pi * raw_fit_data / max_fit_data) - np.pi / 2) + xlabel = f"{cut_xds.attrs['xlabel']} [{lm_unit}]" + ylabel = f"{parallel_hand} Phase [{phase_unit}]" + + # Call plotting tool + if cut_xds.attrs[f"{parallel_hand}_fit_succeeded"]: + scatter_plot( + this_ax, + x_data, + xlabel, + y_data, + ylabel, + model=fit_data, + model_marker="", + title=sub_title, + data_marker="+", + model_linestyle="-", + data_label=f"{parallel_hand} phase", + model_label=f"{parallel_hand} amp. fit", + hlines=[phase_fac * (-np.pi / 2)], + hv_linestyle="--", + hv_color="black", + data_color="red", + model_color="blue", + plot_residuals=False, + legend_location="upper right", + ) + + # Add fit peak identifiers + centers = lm_fac * np.array( + cut_xds.attrs[f"{parallel_hand}_amp_fit_pars"][0::3] + ) + amps = np.array(cut_xds.attrs[f"{parallel_hand}_amp_fit_pars"][1::3]) + + _add_lobe_identification_to_plot( + this_ax, + centers, + amps, + y_off, + ) + else: + scatter_plot( + this_ax, + x_data, + xlabel, + y_data, + ylabel, + title=sub_title, + data_marker="+", + data_label=f"{parallel_hand} phase", + data_color="red", + legend_location="upper right", + ) + + this_ax.set_ylim(phase_scale) + + _add_secondary_beam_hpbw_x_axis_to_plot( + cut_xds.attrs[f"{parallel_hand}_pb_fwhm"] * lm_fac, this_ax + ) + + # Add bounded box with Beam parameters + _add_beam_parameters_box( + this_ax, + cut_xds.attrs[f"{parallel_hand}_pb_center"] * lm_fac, + cut_xds.attrs[f"{parallel_hand}_pb_fwhm"] * lm_fac, + cut_xds.attrs[f"{parallel_hand}_first_side_lobe_ratio"], + lm_unit, + ) + + def _plot_single_cut_in_attenuation(cut_xds, ax, par_dict): """ Plot a single beam cut in attenuation with superposed correlations From 6936fb1dc0d825bb313332ed37a1f63f75a2c005 Mon Sep 17 00:00:00 2001 From: Victor de Souza Magalhaes Date: Fri, 27 Feb 2026 11:51:44 -0700 Subject: [PATCH 2/9] Added docstring to plot_beamcut_in_phase, made positioning of the amp fit plot dynamic. --- src/astrohack/io/beamcut_mds.py | 48 ++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/src/astrohack/io/beamcut_mds.py b/src/astrohack/io/beamcut_mds.py index 5c8660d5..02bb3bf3 100644 --- a/src/astrohack/io/beamcut_mds.py +++ b/src/astrohack/io/beamcut_mds.py @@ -306,6 +306,43 @@ def plot_beamcut_in_phase( dpi: int = 300, parallel: bool = False, ) -> None: + """ + Plot beamcuts contained in the beamcut_mds in phase + + :param destination: Directory into which to save plots. + :type destination: str + + :param ant: Antenna ID to use in subselection, e.g. ea25, defaults to "all". + :type ant: list or str, optional + + :param ddi: Data description ID to use in subselection, e.g. 0, defaults to "all". + :type ddi: list or int, optional + + :param lm_unit: Unit for L/M offsets, default is "amin". + :type lm_unit: str, optional + + :param azel_unit: Unit for Az/El information, default is "deg". + :type azel_unit: str, optional + + :param phase_unit: Unit for the phase plots, default is "deg". + :type phase_unit: str, optional + + :param phase_scale: Scale for the phase plots, in phase_unit, default is None, meaning 1 full cycle. + :type phase_scale: Union[List[float], Tuple[float], np.array], optional + + :param display: Display plots during execution, default is False. + :type display: bool, optional + + :param dpi: Pixel resolution for plots, default is 300. + :type dpi: int, optional + + :param parallel: Run in parallel, defaults to False. + :type parallel: bool, optional + + :return: None + :rtype: NoneType + """ + param_dict = locals() pathlib.Path(param_dict["destination"]).mkdir(exist_ok=True) @@ -787,8 +824,11 @@ def _plot_single_cut_in_phase(cut_xds, axes, par_dict): phase_scale = par_dict["phase_scale"] if phase_scale is None: phase_scale = phase_fac * np.array([-np.pi, np.pi]) - # max_amp = cut_xds.attrs["all_corr_ymax"] - y_off = 0.05 * (phase_scale[1] - phase_scale[0]) + + y_range = phase_scale[1] - phase_scale[0] + y_off = 0.05 * y_range + fit_scale = y_range / 2 + fit_offset = phase_scale[0] + y_range / 4 # Loop over correlations for i_corr, parallel_hand in enumerate(cut_xds.attrs["available_corrs"]): @@ -798,7 +838,7 @@ def _plot_single_cut_in_phase(cut_xds, axes, par_dict): y_data = phase_fac * cut_xds[f"{parallel_hand}_phase"].values raw_fit_data = cut_xds[f"{parallel_hand}_amp_fit"].values max_fit_data = np.max(raw_fit_data) - fit_data = phase_fac * ((np.pi * raw_fit_data / max_fit_data) - np.pi / 2) + fit_data = (fit_scale * raw_fit_data / max_fit_data) + fit_offset xlabel = f"{cut_xds.attrs['xlabel']} [{lm_unit}]" ylabel = f"{parallel_hand} Phase [{phase_unit}]" @@ -817,7 +857,7 @@ def _plot_single_cut_in_phase(cut_xds, axes, par_dict): model_linestyle="-", data_label=f"{parallel_hand} phase", model_label=f"{parallel_hand} amp. fit", - hlines=[phase_fac * (-np.pi / 2)], + hlines=[fit_offset], hv_linestyle="--", hv_color="black", data_color="red", From ec336fde8690e04c8aeca88261b75675b55f2b52 Mon Sep 17 00:00:00 2001 From: Victor de Souza Magalhaes Date: Fri, 27 Feb 2026 11:57:35 -0700 Subject: [PATCH 3/9] Added parameter validation to plot_beamcut_in_phase --- src/astrohack/config/beamcut_mds.param.json | 82 +++++++++++++++++++++ src/astrohack/io/beamcut_mds.py | 1 + 2 files changed, 83 insertions(+) diff --git a/src/astrohack/config/beamcut_mds.param.json b/src/astrohack/config/beamcut_mds.param.json index ff7307ef..fcc10109 100644 --- a/src/astrohack/config/beamcut_mds.param.json +++ b/src/astrohack/config/beamcut_mds.param.json @@ -287,6 +287,88 @@ "type": ["boolean"] } }, + "AstrohackBeamcutFile.plot_beamcut_in_phase":{ + "destination":{ + "nullable": false, + "required": true, + "type": ["string"] + }, + "ant": { + "nullable": false, + "required": false, + "struct_type": [ + "str" + ], + "minlength": 1, + "type": [ + "string", + "list" + ] + }, + "ddi": { + "nullable": false, + "required": false, + "struct_type": [ + "int" + ], + "minlength": 1, + "type": [ + "int", + "list", + "string" + ] + }, + "lm_unit":{ + "nullable": false, + "required": false, + "type": ["string"], + "check allowed with": "units.trig" + }, + "azel_unit":{ + "nullable": false, + "required": false, + "type": ["string"], + "check allowed with": "units.trig" + }, + "phase_unit":{ + "nullable": false, + "required": false, + "type": ["string"], + "check allowed with": "units.trig" + }, + "dpi":{ + "nullable": false, + "required": false, + "type": ["int"], + "min": 1, + "max": 1200 + }, + "display":{ + "nullable": false, + "required": false, + "type": ["boolean"] + }, + "phase_scale":{ + "nullable": true, + "required": false, + "struct_type": [ + "float", + "int" + ], + "minlength": 2, + "maxlength": 2, + "type": [ + "list", + "tuple", + "ndarray" + ] + }, + "parallel":{ + "nullable": false, + "required": false, + "type": ["boolean"] + } + }, "AstrohackBeamcutFile.create_beam_fit_report":{ "destination":{ "nullable": false, diff --git a/src/astrohack/io/beamcut_mds.py b/src/astrohack/io/beamcut_mds.py index 02bb3bf3..1375e344 100644 --- a/src/astrohack/io/beamcut_mds.py +++ b/src/astrohack/io/beamcut_mds.py @@ -293,6 +293,7 @@ def plot_beam_cuts_over_sky( ) return + @validate(custom_checker=custom_plots_checker) def plot_beamcut_in_phase( self, destination: str, From 53056b2ea1a5378a16b5e8ebcb13075349a12ccb Mon Sep 17 00:00:00 2001 From: Victor de Souza Magalhaes Date: Fri, 27 Feb 2026 12:07:13 -0700 Subject: [PATCH 4/9] Beamcut now also creates phase plots when destinations is not None. --- src/astrohack/beamcut.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/astrohack/beamcut.py b/src/astrohack/beamcut.py index edb05a55..ca57fa56 100644 --- a/src/astrohack/beamcut.py +++ b/src/astrohack/beamcut.py @@ -1,4 +1,5 @@ import pathlib +import numpy as np from toolviper.utils.parameter import validate @@ -10,7 +11,7 @@ from astrohack.io.dio import open_holog from astrohack.utils.validation import custom_plots_checker -from typing import Union, List +from typing import Union, List, Tuple @validate(custom_checker=custom_plots_checker) @@ -22,9 +23,11 @@ def beamcut( destination: str = None, lm_unit: str = "amin", azel_unit: str = "deg", + phase_unit: str = "deg", + phase_scale: Union[List[float], Tuple[float], np.array] = None, + y_scale: list[float] = None, dpi: int = 300, display: bool = False, - y_scale: list[float] = None, parallel: bool = False, overwrite: bool = False, ): @@ -52,6 +55,12 @@ def beamcut( :param azel_unit: Unit for Az/El information in plots and report, default is "deg". :type azel_unit: str, optional + :param phase_unit: Unit for phase plots, default is "deg". + :type phase_unit: str, optional + + :param phase_scale: Scale for the phase plots, in phase_unit, default is None, meaning 1 full cycle. + :type phase_scale: Union[List[float], Tuple[float], np.array], optional + :param dpi: Resolution in pixels, defaults to 300. :type dpi: int, optional @@ -152,6 +161,16 @@ def beamcut( dpi=dpi, parallel=parallel, ) + beamcut_mds.plot_beamcut_in_phase( + destination, + lm_unit=lm_unit, + azel_unit=azel_unit, + phase_unit=phase_unit, + phase_scale=phase_scale, + display=display, + dpi=dpi, + parallel=parallel, + ) beamcut_mds.plot_beam_cuts_over_sky( destination, lm_unit=lm_unit, From a6eb4fc92e0ad12fa93a70f127d4611667845c76 Mon Sep 17 00:00:00 2001 From: Victor de Souza Magalhaes Date: Fri, 27 Feb 2026 16:06:46 -0700 Subject: [PATCH 5/9] Added phase unit and scale to beamcut parameter checking. --- src/astrohack/config/beamcut.param.json | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/astrohack/config/beamcut.param.json b/src/astrohack/config/beamcut.param.json index cecafc0e..18dc432e 100644 --- a/src/astrohack/config/beamcut.param.json +++ b/src/astrohack/config/beamcut.param.json @@ -38,6 +38,12 @@ "type": ["string"], "check allowed with": "units.trig" }, + "phase_unit":{ + "nullable": false, + "required": false, + "type": ["string"], + "check allowed with": "units.trig" + }, "dpi":{ "nullable": false, "required": false, @@ -65,6 +71,21 @@ "ndarray" ] }, + "phase_scale":{ + "nullable": true, + "required": false, + "struct_type": [ + "float", + "int" + ], + "minlength": 2, + "maxlength": 2, + "type": [ + "list", + "tuple", + "ndarray" + ] + }, "parallel":{ "nullable": false, "required": false, From 56a1bfc7061265074ae8ec650824347d5a425a5e Mon Sep 17 00:00:00 2001 From: Victor de Souza Magalhaes Date: Fri, 27 Feb 2026 16:09:25 -0700 Subject: [PATCH 6/9] Returning the summary as a string may screw up display in notebooks, hence removed. --- src/astrohack/io/base_mds.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/astrohack/io/base_mds.py b/src/astrohack/io/base_mds.py index 03806657..f640f394 100644 --- a/src/astrohack/io/base_mds.py +++ b/src/astrohack/io/base_mds.py @@ -204,7 +204,6 @@ def summary(self) -> None: outstr += get_method_list_string(self) outstr += get_data_content_string(self.root) print(outstr) - return outstr @classmethod def create_from_input_parameters(cls, file_name: str, input_parameters: dict): From 13f022304d2436c2f6890344c19ff4a3bd653779 Mon Sep 17 00:00:00 2001 From: Victor de Souza Magalhaes Date: Fri, 27 Feb 2026 16:15:35 -0700 Subject: [PATCH 7/9] Added phase plotting to beamcut_tutorial.ipynb --- docs/tutorials/beamcut_tutorial.ipynb | 519 ++++++++++---------------- 1 file changed, 188 insertions(+), 331 deletions(-) diff --git a/docs/tutorials/beamcut_tutorial.ipynb b/docs/tutorials/beamcut_tutorial.ipynb index 9ca42c86..ca4114ab 100644 --- a/docs/tutorials/beamcut_tutorial.ipynb +++ b/docs/tutorials/beamcut_tutorial.ipynb @@ -91,13 +91,13 @@ "name": "stdout", "output_type": "stream", "text": [ - "[\u001b[38;2;128;05;128m2026-02-25 17:12:33,073\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Updating file metadata information ... \n" + "[\u001b[38;2;128;05;128m2026-02-27 16:13:50,880\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Updating file metadata information ... \n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "4af27ae699a94728b0546f6f7b004f57", + "model_id": "db50f616fdb74f58b08c36698acdfd2f", "version_major": 2, "version_minor": 0 }, @@ -122,8 +122,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "[\u001b[38;2;128;05;128m2026-02-25 17:12:33,485\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Module path: \u001b[38;2;50;50;205m/export/home/arya/miniforge3/envs/casadev/lib/python3.12/site-packages/toolviper\u001b[0m \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:33,488\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Downloading from [cloudflare] .... \n" + "[\u001b[38;2;128;05;128m2026-02-27 16:13:51,422\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Module path: \u001b[38;2;50;50;205m/home/victor/mambaforge/envs/casadev/lib/python3.12/site-packages/toolviper\u001b[0m \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:13:51,429\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Downloading from [cloudflare] .... \n" ] }, { @@ -151,13 +151,13 @@ "name": "stdout", "output_type": "stream", "text": [ - "[\u001b[38;2;128;05;128m2026-02-25 17:12:33,490\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m File exists: data/kband_beamcut_small.ms \n" + "[\u001b[38;2;128;05;128m2026-02-27 16:13:51,432\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m File exists: data/kband_beamcut_small.ms \n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "7ad6d60636fc47dfa09cbe72b752e309", + "model_id": "8a6e9c1faf22475fb0cb0e9c1421f487", "version_major": 2, "version_minor": 0 }, @@ -213,26 +213,10 @@ "name": "stdout", "output_type": "stream", "text": [ - "[\u001b[38;2;128;05;128m2026-02-25 17:12:33,514\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Module path: \u001b[38;2;50;50;205m/export/home/arya/miniforge3/envs/casadev/lib/python3.12/site-packages/toolviper\u001b[0m \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:33,516\u001b[0m] \u001b[38;2;255;160;0m WARNING\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m It is recommended that the local cache directory be set using the \u001b[38;2;50;50;205mdask_local_dir\u001b[0m parameter. \n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/export/home/arya/miniforge3/envs/casadev/lib/python3.12/site-packages/distributed/node.py:188: UserWarning: Port 8787 is already in use.\n", - "Perhaps you already have a cluster running?\n", - "Hosting the HTTP server on port 34267 instead\n", - " warnings.warn(\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[\u001b[38;2;128;05;128m2026-02-25 17:12:34,391\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Client \n", - "\n" + "[\u001b[38;2;128;05;128m2026-02-27 16:13:51,478\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Module path: \u001b[38;2;50;50;205m/home/victor/mambaforge/envs/casadev/lib/python3.12/site-packages/toolviper\u001b[0m \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:13:51,484\u001b[0m] \u001b[38;2;255;160;0m WARNING\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m It is recommended that the local cache directory be set using the \u001b[38;2;50;50;205mdask_local_dir\u001b[0m parameter. \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:13:52,975\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Client \n", + "\n" ] } ], @@ -273,22 +257,22 @@ "name": "stdout", "output_type": "stream", "text": [ - "[\u001b[38;2;128;05;128m2026-02-25 17:12:34,395\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Module path: \u001b[38;2;50;50;205m/export/home/arya/work/Holography-1022/astrohack/src/astrohack\u001b[0m \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:34,397\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Creating output file name: data/kband_beamcut_small.point.zarr \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:34,398\u001b[0m] \u001b[38;2;255;160;0m WARNING\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m data/kband_beamcut_small.point.zarr will be overwritten. \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:35,423\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Consolidating data/kband_beamcut_small.point.zarr... \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:35,528\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Module path: \u001b[38;2;50;50;205m/export/home/arya/work/Holography-1022/astrohack/src/astrohack\u001b[0m \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:35,532\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Creating output file name: data/kband_beamcut_small.holog.zarr \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:35,553\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Pre-processing ddi: 0, scans: [8 ... 13] \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:35,554\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Pre-processing ddi: 1, scans: [8 ... 13] \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:35,555\u001b[0m] \u001b[38;2;255;160;0m WARNING\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m data/kband_beamcut_small.holog.zarr will be overwritten. \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:37,002\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m EA15: DDI 0: Suggested cell size 1.64 amin, FOV: (19.72 amin, 19.76 amin) \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:37,003\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m EA17: DDI 0: Suggested cell size 1.64 amin, FOV: (19.73 amin, 19.76 amin) \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:37,784\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Finished extracting holography chunk for DDI 0, map_0. \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:38,108\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m EA15: DDI 1: Suggested cell size 1.63 amin, FOV: (19.72 amin, 19.76 amin) \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:38,109\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m EA17: DDI 1: Suggested cell size 1.63 amin, FOV: (19.73 amin, 19.76 amin) \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:38,165\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Finished extracting holography chunk for DDI 1, map_0. \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:38,166\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Consolidating data/kband_beamcut_small.holog.zarr... \n" + "[\u001b[38;2;128;05;128m2026-02-27 16:13:52,983\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Module path: \u001b[38;2;50;50;205m/home/victor/work/Holography-1022/astrohack/src/astrohack\u001b[0m \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:13:52,988\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Creating output file name: data/kband_beamcut_small.point.zarr \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:13:52,990\u001b[0m] \u001b[38;2;255;160;0m WARNING\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m data/kband_beamcut_small.point.zarr will be overwritten. \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:13:54,775\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Consolidating data/kband_beamcut_small.point.zarr... \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:13:54,995\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Module path: \u001b[38;2;50;50;205m/home/victor/work/Holography-1022/astrohack/src/astrohack\u001b[0m \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:13:55,001\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Creating output file name: data/kband_beamcut_small.holog.zarr \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:13:55,040\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Pre-processing ddi: 0, scans: [8 ... 13] \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:13:55,042\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Pre-processing ddi: 1, scans: [8 ... 13] \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:13:55,043\u001b[0m] \u001b[38;2;255;160;0m WARNING\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m data/kband_beamcut_small.holog.zarr will be overwritten. \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:13:57,251\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m EA15: DDI 0: Suggested cell size 1.64 amin, FOV: (19.72 amin, 19.76 amin) \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:13:57,254\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m EA17: DDI 0: Suggested cell size 1.64 amin, FOV: (19.73 amin, 19.76 amin) \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:13:58,789\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Finished extracting holography chunk for DDI 0, map_0. \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:13:59,279\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m EA15: DDI 1: Suggested cell size 1.63 amin, FOV: (19.72 amin, 19.76 amin) \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:13:59,281\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m EA17: DDI 1: Suggested cell size 1.63 amin, FOV: (19.73 amin, 19.76 amin) \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:13:59,398\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Finished extracting holography chunk for DDI 1, map_0. \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:13:59,399\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Consolidating data/kband_beamcut_small.holog.zarr... \n" ] } ], @@ -351,14 +335,14 @@ "name": "stdout", "output_type": "stream", "text": [ - "[\u001b[38;2;128;05;128m2026-02-25 17:12:38,220\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Module path: \u001b[38;2;50;50;205m/export/home/arya/work/Holography-1022/astrohack/src/astrohack\u001b[0m \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:38,224\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Creating output file name: data/kband_beamcut_small.beamcut.zarr \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:38,224\u001b[0m] \u001b[38;2;255;160;0m WARNING\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m data/kband_beamcut_small.beamcut.zarr will be overwritten. \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:39,849\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m worker_0: \u001b[0m processing EA15: DDI 1 \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:40,283\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m worker_3: \u001b[0m processing EA17: DDI 1 \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:40,284\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m worker_1: \u001b[0m processing EA17: DDI 0 \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:40,303\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m worker_2: \u001b[0m processing EA15: DDI 0 \n", - "[\u001b[38;2;128;05;128m2026-02-25 17:12:40,803\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Consolidating data/kband_beamcut_small.beamcut.zarr... \n" + "[\u001b[38;2;128;05;128m2026-02-27 16:13:59,519\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Module path: \u001b[38;2;50;50;205m/home/victor/work/Holography-1022/astrohack/src/astrohack\u001b[0m \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:13:59,531\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Creating output file name: data/kband_beamcut_small.beamcut.zarr \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:13:59,532\u001b[0m] \u001b[38;2;255;160;0m WARNING\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m data/kband_beamcut_small.beamcut.zarr will be overwritten. \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:14:01,917\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m worker_3: \u001b[0m processing EA15: DDI 1 \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:14:03,039\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m worker_1: \u001b[0m processing EA17: DDI 1 \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:14:03,630\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m worker_0: \u001b[0m processing EA15: DDI 0 \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:14:04,072\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m worker_2: \u001b[0m processing EA17: DDI 0 \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:14:05,358\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Consolidating data/kband_beamcut_small.beamcut.zarr... \n" ] } ], @@ -408,7 +392,7 @@ "################################################################################\n", "\n", "Data origin:\n", - "creation_time: 2026-02-25 17:12:38 MST\n", + "creation_time: 2026-02-27 16:13:59 MST\n", "creator_function: beamcut\n", "origin: astrohack\n", "version: 0.10.1\n", @@ -428,6 +412,8 @@ "| lm_unit | amin |\n", "| overwrite | True |\n", "| parallel | True |\n", + "| phase_scale | None |\n", + "| phase_unit | deg |\n", "| y_scale | None |\n", "+--------------+---------------------------------------+\n", "\n", @@ -435,6 +421,15 @@ "+------------------------------+-----------------------------------------------+\n", "| Methods | Description |\n", "+------------------------------+-----------------------------------------------+\n", + "| add_node | Add a node to the data tree file structure, |\n", + "| | however this node is not yet consolidated |\n", + "| | into the data tree structure, |\n", + "| | consolidate must be called to integrate all |\n", + "| | nodes writen by add_node onto the tree |\n", + "| | structure. |\n", + "| consolidate | Traverse own file structure on disk |\n", + "| | consolidating metadata to create a unified |\n", + "| | data tree entity. |\n", "| create_beam_fit_report | Create reports on the parameters of the |\n", "| | gaussians fitted to the beamcut. |\n", "| create_from_input_parameters | Create an AstrohackBaseFile object from a |\n", @@ -452,6 +447,8 @@ "| | amplitude |\n", "| plot_beamcut_in_attenuation | Plot beamcuts contained in the beamcut_mds in |\n", "| | attenuation |\n", + "| plot_beamcut_in_phase | Plot beamcuts contained in the beamcut_mds in |\n", + "| | phase |\n", "| summary | Prints summary of this Astrohack File object, |\n", "| | with available data, attributes and methods |\n", "| values | Get children values |\n", @@ -504,7 +501,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "[\u001b[38;2;128;05;128m2026-02-25 17:12:40,946\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Module path: \u001b[38;2;50;50;205m/export/home/arya/work/Holography-1022/astrohack/src/astrohack\u001b[0m \n", + "[\u001b[38;2;128;05;128m2026-02-27 16:14:05,699\u001b[0m] \u001b[38;2;50;50;205m INFO\u001b[0m\u001b[38;2;112;128;144m astrohack: \u001b[0m Module path: \u001b[38;2;50;50;205m/home/victor/work/Holography-1022/astrohack/src/astrohack\u001b[0m \n", "############################################################\n", "### ant_ea15, ddi_0 ###\n", "############################################################\n", @@ -692,87 +689,39 @@ "\n", "\n", "\n", - "
<xarray.DataTree 'cut_0'>\n",
-       "Group: /ant_ea17/ddi_0/cut_0\n",
-       "    Dimensions:       (lm_dist: 487, time: 487, lm: 2)\n",
-       "    Coordinates:\n",
-       "      * lm_dist       (lm_dist) float64 4kB -0.002873 -0.002863 ... 0.002871\n",
-       "      * time          (time) float64 4kB 5.271e+09 5.271e+09 ... 5.271e+09 5.271e+09\n",
-       "    Dimensions without coordinates: lm\n",
-       "    Data variables:\n",
-       "        LL_amp_fit    (lm_dist) float64 4kB dask.array<chunksize=(487,), meta=np.ndarray>\n",
-       "        LL_amplitude  (lm_dist) float64 4kB dask.array<chunksize=(487,), meta=np.ndarray>\n",
-       "        LL_phase      (lm_dist) float64 4kB dask.array<chunksize=(487,), meta=np.ndarray>\n",
-       "        LL_weight     (lm_dist) float64 4kB dask.array<chunksize=(487,), meta=np.ndarray>\n",
-       "        RR_amp_fit    (lm_dist) float64 4kB dask.array<chunksize=(487,), meta=np.ndarray>\n",
-       "        RR_amplitude  (lm_dist) float64 4kB dask.array<chunksize=(487,), meta=np.ndarray>\n",
-       "        RR_phase      (lm_dist) float64 4kB dask.array<chunksize=(487,), meta=np.ndarray>\n",
-       "        RR_weight     (lm_dist) float64 4kB dask.array<chunksize=(487,), meta=np.ndarray>\n",
-       "        lm_offsets    (time, lm) float64 8kB dask.array<chunksize=(487, 2), meta=np.ndarray>\n",
-       "    Attributes: (12/19)\n",
-       "        LL_amp_fit_pars:           [-0.0020771884159861693, 0.16536998921100482, ...\n",
-       "        LL_first_side_lobe_ratio:  0.9506975351868078\n",
-       "        LL_fit_succeeded:          True\n",
-       "        LL_n_peaks:                5\n",
-       "        LL_pb_center:              2.0066879975923337e-05\n",
-       "        LL_pb_fwhm:                0.0007089940968873998\n",
-       "        ...                        ...\n",
-       "        available_corrs:           ['RR', 'LL']\n",
-       "        direction:                 El. cut (S -> N)\n",
-       "        lm_angle:                  8.043802534404685e-06\n",
-       "        scan_number:               8\n",
-       "        time_string:               2025-11-25 23:16\n",
-       "        xlabel:                    Elevation offset