From 248e7ffe19f9076d15779d22a110f812b050448b Mon Sep 17 00:00:00 2001 From: Jammy2211 Date: Thu, 2 Apr 2026 18:08:24 +0100 Subject: [PATCH] Visualization overhaul: config-driven origin, fits API, output mode - Add _conf_imshow_origin for config-driven imshow origin across all plots - Add _output_mode_save for PYAUTOARRAY_OUTPUT_MODE=1 debug capture - Add fits_imaging and fits_interferometer standalone functions - Remove output_to_fits methods from AbstractNDArray, Mask, Visibilities, Imaging, and Interferometer classes - Remove flip_for_ds9 config and dead flip_hdu_for_ds9 method - Remove FITS handling from save_figure and plot output paths Co-Authored-By: Claude Opus 4.6 (1M context) --- CLAUDE.md | 53 ++++++---- autoarray/abstract_ndarray.py | 25 +---- autoarray/config/general.yaml | 2 - autoarray/dataset/imaging/dataset.py | 35 ------ autoarray/dataset/interferometer/dataset.py | 43 +------- autoarray/dataset/plot/imaging_plots.py | 72 +++++++++++++ .../dataset/plot/interferometer_plots.py | 73 ++++++++++++- autoarray/mask/abstract_mask.py | 35 +----- autoarray/plot/array.py | 8 +- autoarray/plot/inversion.py | 4 +- autoarray/plot/output.py | 6 -- autoarray/plot/utils.py | 100 ++++++++++++------ autoarray/structures/visibilities.py | 17 --- test_autoarray/config/general.yaml | 2 - 14 files changed, 253 insertions(+), 222 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index b9f3d6399..4aa7d7229 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,33 +9,44 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co pip install -e ".[dev]" ``` -### Run Tests -```bash -# All tests -python -m pytest test_autoarray/ +### Run Tests +```bash +# All tests +python -m pytest test_autoarray/ # Single test file python -m pytest test_autoarray/structures/test_arrays.py -# With output -python -m pytest test_autoarray/structures/test_arrays.py -s -``` - -### Codex / sandboxed runs - -When running Python from Codex or any restricted environment, set writable cache directories so `numba` and `matplotlib` do not fail on unwritable home or source-tree paths: - -```bash -NUMBA_CACHE_DIR=/tmp/numba_cache MPLCONFIGDIR=/tmp/matplotlib python -m pytest test_autoarray/ -``` - -This workspace is often imported from `/mnt/c/...` and Codex may not be able to write to module `__pycache__` directories or `/home/jammy/.cache`, which can cause import-time `numba` caching failures without this override. - -### Formatting -```bash -black autoarray/ +# With output +python -m pytest test_autoarray/structures/test_arrays.py -s +``` + +### Codex / sandboxed runs + +When running Python from Codex or any restricted environment, set writable cache directories so `numba` and `matplotlib` do not fail on unwritable home or source-tree paths: + +```bash +NUMBA_CACHE_DIR=/tmp/numba_cache MPLCONFIGDIR=/tmp/matplotlib python -m pytest test_autoarray/ +``` + +This workspace is often imported from `/mnt/c/...` and Codex may not be able to write to module `__pycache__` directories or `/home/jammy/.cache`, which can cause import-time `numba` caching failures without this override. + +### Formatting +```bash +black autoarray/ +``` + +### Plot Output Mode + +Set `PYAUTOARRAY_OUTPUT_MODE=1` to capture every figure produced by a script into numbered PNG files in `./output_mode//`. This is useful for visually inspecting all plots from an integration test without needing a display. + +```bash +PYAUTOARRAY_OUTPUT_MODE=1 python scripts/my_script.py +# -> ./output_mode/my_script/0_fit.png, 1_tracer.png, ... ``` +When this env var is set, all `save_figure`, `subplot_save`, and `_save_subplot` calls are intercepted — the normal output path is bypassed and figures are written sequentially to the output_mode directory instead. + ## Architecture **PyAutoArray** is the low-level data structures and numerical utilities package for the PyAuto ecosystem. It provides: diff --git a/autoarray/abstract_ndarray.py b/autoarray/abstract_ndarray.py index c3b2150bd..53145d386 100644 --- a/autoarray/abstract_ndarray.py +++ b/autoarray/abstract_ndarray.py @@ -7,7 +7,7 @@ import numpy as np -from autoconf.fitsable import output_to_fits + from typing import TYPE_CHECKING @@ -135,11 +135,6 @@ def with_new_array(self, array: np.ndarray) -> "AbstractNDArray": new_array._array = array return new_array - def flip_hdu_for_ds9(self, values): - if conf.instance["general"]["fits"]["flip_for_ds9"]: - return self._xp.flipud(values) - return values - def copy(self): new = copy(self) return new @@ -272,24 +267,6 @@ def native(self) -> Structure: Returns the data structure in its `native` format which contains all unmaksed values to the native dimensions. """ - def output_to_fits(self, file_path: str, overwrite: bool = False): - """ - Output the grid to a .fits file. - - Parameters - ---------- - file_path - The path the file is output to, including the filename and the .fits extension, e.g. '/path/to/filename.fits' - overwrite - If a file already exists at the path, if overwrite=True it is overwritten else an error is raised. - """ - output_to_fits( - values=self.native.array.astype("float"), - file_path=file_path, - overwrite=overwrite, - header_dict=self.mask.header_dict, - ) - @property def shape(self): try: diff --git a/autoarray/config/general.yaml b/autoarray/config/general.yaml index e0b0df0de..41cebe359 100644 --- a/autoarray/config/general.yaml +++ b/autoarray/config/general.yaml @@ -1,5 +1,3 @@ -fits: - flip_for_ds9: false # If True, the image is flipped before output to a .fits file, which is useful for viewing in DS9. psf: use_fft_default: true # If True, PSFs are convolved using FFTs by default, which is faster and uses less memory in all cases except for very small PSFs, False uses direct convolution. inversion: diff --git a/autoarray/dataset/imaging/dataset.py b/autoarray/dataset/imaging/dataset.py index 82e60dfa8..f2b1c20a3 100644 --- a/autoarray/dataset/imaging/dataset.py +++ b/autoarray/dataset/imaging/dataset.py @@ -542,38 +542,3 @@ def apply_sparse_operator_cpu( sparse_operator=sparse_operator, ) - def output_to_fits( - self, - data_path: Union[Path, str], - psf_path: Optional[Union[Path, str]] = None, - noise_map_path: Optional[Union[Path, str]] = None, - overwrite: bool = False, - ): - """ - Output an imaging dataset to multiple .fits file. - - For each attribute of the imaging data (e.g. `data`, `noise_map`) the path to - the .fits can be specified, with `hdu=0` assumed automatically. - - If the `data` has been masked, the masked data is output to .fits files. A mask can be separately output to - a file `mask.fits` via the `Mask` objects `output_to_fits` method. - - Parameters - ---------- - data_path - The path to the data .fits file where the image data is output (e.g. '/path/to/data.fits'). - psf_path - The path to the psf .fits file where the psf is output (e.g. '/path/to/psf.fits'). - noise_map_path - The path to the noise_map .fits where the noise_map is output (e.g. '/path/to/noise_map.fits'). - overwrite - If `True`, the .fits files are overwritten if they already exist, if `False` they are not and an - exception is raised. - """ - self.data.output_to_fits(file_path=data_path, overwrite=overwrite) - - if self.psf is not None and psf_path is not None: - self.psf.kernel.output_to_fits(file_path=psf_path, overwrite=overwrite) - - if self.noise_map is not None and noise_map_path is not None: - self.noise_map.output_to_fits(file_path=noise_map_path, overwrite=overwrite) diff --git a/autoarray/dataset/interferometer/dataset.py b/autoarray/dataset/interferometer/dataset.py index 446f5b72d..0126e13bb 100644 --- a/autoarray/dataset/interferometer/dataset.py +++ b/autoarray/dataset/interferometer/dataset.py @@ -2,7 +2,7 @@ import numpy as np from typing import Optional -from autoconf.fitsable import ndarray_via_fits_from, output_to_fits +from autoconf.fitsable import ndarray_via_fits_from from autoconf import cached_property from autoarray.dataset.abstract.dataset import AbstractDataset @@ -424,47 +424,6 @@ def signal_to_noise_map(self): signal_to_noise_map_real + 1j * signal_to_noise_map_imag ) - def output_to_fits( - self, - data_path=None, - noise_map_path=None, - uv_wavelengths_path=None, - overwrite=False, - ): - """ - Output the interferometer dataset to multiple .fits files. - - Each component (visibilities, noise map, uv_wavelengths) is saved to its own .fits file. - Any path set to `None` means that component is not saved. - - Parameters - ---------- - data_path - The path where the visibility data is saved (e.g. '/path/to/visibilities.fits'). - If `None`, the visibilities are not saved. - noise_map_path - The path where the noise map is saved (e.g. '/path/to/noise_map.fits'). - If `None`, the noise map is not saved. - uv_wavelengths_path - The path where the uv_wavelengths array is saved (e.g. '/path/to/uv_wavelengths.fits'). - If `None`, the uv_wavelengths are not saved. - overwrite - If `True`, existing .fits files are overwritten. If `False`, an exception is raised - if a file already exists at the given path. - """ - if data_path is not None: - self.data.output_to_fits(file_path=data_path, overwrite=overwrite) - - if self.noise_map is not None and noise_map_path is not None: - self.noise_map.output_to_fits(file_path=noise_map_path, overwrite=overwrite) - - if self.uv_wavelengths is not None and uv_wavelengths_path is not None: - output_to_fits( - values=self.uv_wavelengths, - file_path=uv_wavelengths_path, - overwrite=overwrite, - ) - @property def psf(self): """ diff --git a/autoarray/dataset/plot/imaging_plots.py b/autoarray/dataset/plot/imaging_plots.py index ec680ff32..ff9d271f1 100644 --- a/autoarray/dataset/plot/imaging_plots.py +++ b/autoarray/dataset/plot/imaging_plots.py @@ -181,3 +181,75 @@ def subplot_imaging_dataset_list( plot_array(dataset.signal_to_noise_map, ax=axes[i][2], title="Signal-To-Noise Map") plt.tight_layout() subplot_save(fig, output_path, output_filename, output_format) + + +def fits_imaging( + dataset, + file_path=None, + data_path=None, + psf_path=None, + noise_map_path=None, + overwrite=False, +): + """Write an ``Imaging`` dataset to FITS. + + Supports two modes: + + * **Separate files** — pass ``data_path``, ``psf_path``, ``noise_map_path`` + to write each component to its own single-HDU FITS file. + * **Single multi-HDU file** — pass ``file_path`` to write all components + into one FITS file with named extensions (``mask``, ``data``, ``psf``, + ``noise_map``). + + Parameters + ---------- + dataset + The ``Imaging`` dataset to write. + file_path : str or Path, optional + Path for a single multi-HDU FITS file. + data_path, psf_path, noise_map_path : str or Path, optional + Paths for individual component files. + overwrite : bool + If ``True`` existing files are replaced. + """ + from autoconf.fitsable import output_to_fits, hdu_list_for_output_from, write_hdu_list + + header_dict = dataset.data.mask.header_dict if hasattr(dataset.data.mask, "header_dict") else None + + if file_path is not None: + values_list = [dataset.data.mask.astype("float")] + ext_name_list = ["mask"] + + values_list.append(dataset.data.native.array.astype("float")) + ext_name_list.append("data") + + if dataset.psf is not None: + values_list.append(dataset.psf.kernel.native.array.astype("float")) + ext_name_list.append("psf") + + if dataset.noise_map is not None: + values_list.append(dataset.noise_map.native.array.astype("float")) + ext_name_list.append("noise_map") + + hdu_list = hdu_list_for_output_from( + values_list=values_list, + ext_name_list=ext_name_list, + header_dict=header_dict, + ) + write_hdu_list(hdu_list, file_path=file_path, overwrite=overwrite) + else: + if data_path is not None: + output_to_fits( + values=dataset.data.native.array.astype("float"), + file_path=data_path, overwrite=overwrite, header_dict=header_dict, + ) + if dataset.psf is not None and psf_path is not None: + output_to_fits( + values=dataset.psf.kernel.native.array.astype("float"), + file_path=psf_path, overwrite=overwrite, + ) + if dataset.noise_map is not None and noise_map_path is not None: + output_to_fits( + values=dataset.noise_map.native.array.astype("float"), + file_path=noise_map_path, overwrite=overwrite, header_dict=header_dict, + ) diff --git a/autoarray/dataset/plot/interferometer_plots.py b/autoarray/dataset/plot/interferometer_plots.py index d4b20382e..0288c8ed9 100644 --- a/autoarray/dataset/plot/interferometer_plots.py +++ b/autoarray/dataset/plot/interferometer_plots.py @@ -19,7 +19,7 @@ def subplot_interferometer_dataset( use_log10: bool = False, ): """ - 2×3 subplot of interferometer dataset components. + 2x3 subplot of interferometer dataset components. Panels: Visibilities | UV-Wavelengths | Amplitudes vs UV-distances | Phases vs UV-distances | Dirty Image | Dirty S/N Map @@ -100,7 +100,7 @@ def subplot_interferometer_dirty_images( use_log10: bool = False, ): """ - 1×3 subplot of dirty image, dirty noise map, and dirty S/N map. + 1x3 subplot of dirty image, dirty noise map, and dirty S/N map. Parameters ---------- @@ -144,3 +144,72 @@ def subplot_interferometer_dirty_images( hide_unused_axes(axes) plt.tight_layout() subplot_save(fig, output_path, output_filename, output_format) + + +def fits_interferometer( + dataset, + file_path=None, + data_path=None, + noise_map_path=None, + uv_wavelengths_path=None, + overwrite=False, +): + """Write an ``Interferometer`` dataset to FITS. + + Supports two modes: + + * **Separate files** -- pass ``data_path``, ``noise_map_path``, + ``uv_wavelengths_path`` to write each component to its own FITS file. + * **Single multi-HDU file** -- pass ``file_path`` to write all components + into one FITS file with named extensions (``data``, ``noise_map``, + ``uv_wavelengths``). + + Parameters + ---------- + dataset + The ``Interferometer`` dataset to write. + file_path : str or Path, optional + Path for a single multi-HDU FITS file. + data_path, noise_map_path, uv_wavelengths_path : str or Path, optional + Paths for individual component files. + overwrite : bool + If ``True`` existing files are replaced. + """ + from autoconf.fitsable import output_to_fits, hdu_list_for_output_from, write_hdu_list + + if file_path is not None: + values_list = [] + ext_name_list = [] + + values_list.append(np.asarray(dataset.data.in_array)) + ext_name_list.append("data") + + if dataset.noise_map is not None: + values_list.append(np.asarray(dataset.noise_map.in_array)) + ext_name_list.append("noise_map") + + if dataset.uv_wavelengths is not None: + values_list.append(np.asarray(dataset.uv_wavelengths)) + ext_name_list.append("uv_wavelengths") + + hdu_list = hdu_list_for_output_from( + values_list=values_list, + ext_name_list=ext_name_list, + ) + write_hdu_list(hdu_list, file_path=file_path, overwrite=overwrite) + else: + if data_path is not None: + output_to_fits( + values=np.asarray(dataset.data.in_array), + file_path=data_path, overwrite=overwrite, + ) + if dataset.noise_map is not None and noise_map_path is not None: + output_to_fits( + values=np.asarray(dataset.noise_map.in_array), + file_path=noise_map_path, overwrite=overwrite, + ) + if dataset.uv_wavelengths is not None and uv_wavelengths_path is not None: + output_to_fits( + values=dataset.uv_wavelengths, + file_path=uv_wavelengths_path, overwrite=overwrite, + ) diff --git a/autoarray/mask/abstract_mask.py b/autoarray/mask/abstract_mask.py index 95b4ffa7a..ce6282954 100644 --- a/autoarray/mask/abstract_mask.py +++ b/autoarray/mask/abstract_mask.py @@ -5,7 +5,7 @@ import numpy as np from typing import Dict -from autoconf.fitsable import output_to_fits + from autoarray.abstract_ndarray import AbstractNDArray @@ -120,39 +120,6 @@ def dimensions(self) -> int: """ return len(self.shape) - def output_to_fits(self, file_path, overwrite=False): - """ - Write the Mask to a .fits file. - - Before outputting a 2D NumPy array mask, the array may be flipped upside-down using np.flipud depending on - the project config files. This is for Astronomy projects so that structures appear the same orientation - as `.fits` files loaded in DS9. - - Parameters - ---------- - file_path - The full path of the file that is output, including the file name and `.fits` extension. - overwrite - If `True` and a file already exists with the input file_path the .fits file is overwritten. If `False`, an - error is raised. - - Returns - ------- - None - - Examples - -------- - mask = Mask2D(mask=np.full(shape=(5,5), fill_value=False)) - mask.output_to_fits(file_path='/path/to/file/filename.fits', overwrite=True) - """ - output_to_fits( - values=self.astype("float"), - file_path=file_path, - overwrite=overwrite, - header_dict=self.header_dict, - ext_name="mask", - ) - @property def pixels_in_mask(self) -> int: """ diff --git a/autoarray/plot/array.py b/autoarray/plot/array.py index 74f128eef..964da0c10 100644 --- a/autoarray/plot/array.py +++ b/autoarray/plot/array.py @@ -20,6 +20,7 @@ numpy_lines, numpy_positions, _apply_contours, + _conf_imshow_origin, ) _zoom_array_2d = zoom_array @@ -54,7 +55,7 @@ def plot_array( use_log10: bool = False, cb_unit: Optional[str] = None, line_colors: Optional[List] = None, - origin_imshow: str = "upper", + origin_imshow: Optional[str] = None, # --- figure control (used only when ax is None) ----------------------------- figsize: Optional[Tuple[int, int]] = None, output_path: Optional[str] = None, @@ -118,9 +119,11 @@ def plot_array( output_format File format, e.g. ``"png"``. """ + if origin_imshow is None: + origin_imshow = _conf_imshow_origin() + # --- autoarray extraction -------------------------------------------------- array = zoom_array(array) - structure = array try: if extent is None: extent = array.geometry.extent @@ -309,5 +312,4 @@ def plot_array( path=output_path or "", filename=output_filename, format=output_format, - structure=structure, ) diff --git a/autoarray/plot/inversion.py b/autoarray/plot/inversion.py index 3a245d55b..484b446c0 100644 --- a/autoarray/plot/inversion.py +++ b/autoarray/plot/inversion.py @@ -10,7 +10,7 @@ import numpy as np from matplotlib.colors import LogNorm, Normalize -from autoarray.plot.utils import apply_extent, apply_labels, conf_figsize, save_figure +from autoarray.plot.utils import apply_extent, apply_labels, conf_figsize, save_figure, _conf_imshow_origin def plot_inversion_reconstruction( @@ -213,7 +213,7 @@ def _plot_rectangular(ax, pixel_values, mapper, norm, colormap, extent, is_subpl norm=norm, extent=pix_array.geometry.extent, aspect="auto", - origin="upper", + origin=_conf_imshow_origin(), ) _apply_colorbar(im, ax, is_subplot=is_subplot) else: diff --git a/autoarray/plot/output.py b/autoarray/plot/output.py index eea6a63b5..4423ff7cd 100644 --- a/autoarray/plot/output.py +++ b/autoarray/plot/output.py @@ -200,12 +200,6 @@ def to_figure( plt.show() elif format == "png" or format == "pdf": self.savefig(filename, output_path, format) - elif format == "fits": - if structure is not None: - structure.output_to_fits( - file_path=path.join(output_path, f"{filename}.fits"), - overwrite=True, - ) def subplot_to_figure( self, auto_filename: Optional[str] = None, also_show: bool = False diff --git a/autoarray/plot/utils.py b/autoarray/plot/utils.py index b4b3b0798..7190ae7bb 100644 --- a/autoarray/plot/utils.py +++ b/autoarray/plot/utils.py @@ -265,6 +265,39 @@ def set_with_color_values(ax, cmap, color_values, norm=None): return _apply_colorbar(mappable, ax) +def _output_mode_save(fig, filename): + """If ``PYAUTOARRAY_OUTPUT_MODE=1``, save *fig* to a numbered file in + ``./output_mode//`` and return ``True``. Otherwise return + ``False`` so the caller can proceed with normal saving. + + The counter is stored as a function attribute to avoid a global variable. + """ + if os.environ.get("PYAUTOARRAY_OUTPUT_MODE") != "1": + return False + + import sys + + script_name = os.path.splitext(os.path.basename(sys.argv[0]))[0] + output_path = os.path.join(os.getcwd(), "output_mode", script_name) + os.makedirs(output_path, exist_ok=True) + + count = getattr(_output_mode_save, "_count", -1) + 1 + _output_mode_save._count = count + + try: + fig.savefig( + os.path.join(output_path, f"{count}_{filename}.png"), + dpi=150, + bbox_inches="tight", + pad_inches=0.1, + ) + except Exception as exc: + logger.warning(f"output_mode: could not save {count}_{filename}.png: {exc}") + + plt.close(fig) + return True + + def subplot_save(fig, output_path, output_filename, output_format): """Save a subplot figure to disk, or display it, then close it. @@ -286,6 +319,9 @@ def subplot_save(fig, output_path, output_filename, output_format): output_format File format string, e.g. ``"png"`` or ``"pdf"``. """ + if _output_mode_save(fig, output_filename): + return + if output_path: os.makedirs(output_path, exist_ok=True) try: @@ -420,7 +456,6 @@ def save_figure( filename: str, format: str = "png", dpi: Optional[int] = None, - structure=None, ) -> None: """ Save *fig* to ``/.`` then close it. @@ -428,6 +463,8 @@ def save_figure( If *path* is an empty string or ``None``, ``plt.show()`` is called instead. After either action ``plt.close(fig)`` is always called to free memory. + For FITS output use ``fits_array`` (in ``autogalaxy.plot``) instead. + Parameters ---------- fig @@ -442,43 +479,29 @@ def save_figure( to save in multiple formats in one call. dpi Resolution in dots per inch. - structure - Optional autoarray structure (e.g. ``Array2D``). When *format* includes - ``"fits"`` and the structure has ``output_to_fits``, it is used instead - of ``fig.savefig``. Callers do not need to pass this; ``plot_array`` - supplies it automatically from the input array. """ if dpi is None: from autoconf import conf dpi = int(conf.instance["visualize"]["general"]["general"]["dpi"]) + if _output_mode_save(fig, filename): + return + if path: os.makedirs(path, exist_ok=True) formats = format if isinstance(format, (list, tuple)) else [format] for fmt in formats: - if fmt == "fits": - if structure is not None and hasattr(structure, "output_to_fits"): - structure.output_to_fits( - file_path=os.path.join(path, f"{filename}.fits"), - overwrite=True, - ) - else: - logger.warning( - f"save_figure: fits format requested for {filename} but no " - "compatible structure was provided; skipping." - ) - else: - try: - fig.savefig( - os.path.join(path, f"{filename}.{fmt}"), - dpi=dpi, - bbox_inches="tight", - pad_inches=0.1, - ) - except Exception as exc: - logger.warning( - f"save_figure: could not save {filename}.{fmt}: {exc}" - ) + try: + fig.savefig( + os.path.join(path, f"{filename}.{fmt}"), + dpi=dpi, + bbox_inches="tight", + pad_inches=0.1, + ) + except Exception as exc: + logger.warning( + f"save_figure: could not save {filename}.{fmt}: {exc}" + ) else: plt.show() @@ -711,12 +734,16 @@ def _apply_contours( levels = np.linspace(float(np.nanmin(array)), float(np.nanmax(array)), total) # Build explicit coordinate grids so the contours align with imshow. - # imshow with origin="upper" maps row 0 to ymax and last row to ymin, - # so Y must decrease across rows to match. + # With origin="upper" row 0 maps to ymax (Y decreases across rows); + # with origin="lower" row 0 maps to ymin (Y increases across rows). ny, nx = array.shape[:2] if extent is not None: + origin = _conf_imshow_origin() xs = np.linspace(extent[0], extent[1], nx) - ys = np.linspace(extent[3], extent[2], ny) # ymax → ymin + if origin == "upper": + ys = np.linspace(extent[3], extent[2], ny) # ymax → ymin + else: + ys = np.linspace(extent[2], extent[3], ny) # ymin → ymax X, Y = np.meshgrid(xs, ys) cs = ax.contour(X, Y, array, levels=levels, colors="k", alpha=0.5) else: @@ -751,6 +778,15 @@ def _default_colormap() -> str: return name +def _conf_imshow_origin() -> str: + """Return the imshow origin from config (``"upper"`` or ``"lower"``).""" + try: + from autoconf import conf + return conf.instance["visualize"]["general"]["general"]["imshow_origin"] + except Exception: + return "upper" + + def _conf_ticks(key: str, default: float) -> float: try: from autoconf import conf diff --git a/autoarray/structures/visibilities.py b/autoarray/structures/visibilities.py index 52dc7a148..b6700c12c 100644 --- a/autoarray/structures/visibilities.py +++ b/autoarray/structures/visibilities.py @@ -90,23 +90,6 @@ def amplitudes(self) -> np.ndarray: def phases(self) -> np.ndarray: return np.arctan2(self.array.imag, self.array.real) - def output_to_fits(self, file_path: Union[Path, str], overwrite: bool = False): - """ - Output the visibilities to a .fits file. - - The complex values are converted to a 2D NumPy float array of shape [total_visiblities, 2] before being - written to `.fits` format via the `in_array` property. - - Parameters - ---------- - file_path - The path the file is output to, including the filename and the ``.fits`` extension, - e.g. '/path/to/filename.fits' - overwrite - If a file already exists at the path, if overwrite=True it is overwritten else an error is raised. - """ - output_to_fits(values=self.in_array, file_path=file_path, overwrite=overwrite) - @property def scaled_maxima(self) -> Tuple[float, float]: """ diff --git a/test_autoarray/config/general.yaml b/test_autoarray/config/general.yaml index c7b32a751..b07c331e1 100644 --- a/test_autoarray/config/general.yaml +++ b/test_autoarray/config/general.yaml @@ -1,7 +1,5 @@ analysis: n_cores: 1 -fits: - flip_for_ds9: false psf: use_fft_default: false # If True, PSFs are convolved using FFTs by default, which is faster and uses less memory in all cases except for very small PSFs, False uses direct convolution. Real space used for unit tests. grid: