aimfast modules

amifast.aimfast module

aimfast.aimfast.apply_sf_cli_overrides(sf_params, sourcery=None, restored_image=None, threshold=None, ncpu=None)[source]
aimfast.aimfast.compare_models(models, tolerance=1.0, plot=True, all_sources=False, shape_limit=16.0, off_axis=None, closest_only=False, prefix=None, flux_plot='log', flux_sigma_shade=False, fxlabels=None, fylabels=None, ftitles=None, svg=False, title_size='16pt', x_label_size='12pt', y_label_size='12pt', legend_size='10pt', xmajor_size='8pt', ymajor_size='8pt', bar_size='12pt', bar_major_size='8pt', units='milli', restored_image=None, model_mappings=None, phase_centre=None, combined_report=False, hide_large_flux_errors=False)[source]

Plot model1 source properties against that of model2

Parameters

modelsdict

Tigger formatted model files e.g {model1: model2}.

tolerancefloat

Tolerace in detecting source from model 2 (in arcsec).

plotbool

Output html plot from which a png can be obtained.

all_source: bool

Compare all sources in the catalog (else only point-like source)

shape_limit: float

Cross match only sources with maj-axis less than this value

closest_only: bool

Returns the closest source only as the matching source

flux_plot: str

The type of output flux comparison plot (options:log,snr,inout)

prefixstr

Prefix for output htmls

fxlabelsstr[]

X-axis labels for the flux comparison plots

fylabelsstr[]

Y-axis labels for the flux comparison plots

fylabelsstr[]

Title labels for the flux comparison plots

restored_imagestr

Path to restored FITS image to overlay as background in catalog overlay plot

Returns

resultsdict

Dictionary of source properties from each model.

aimfast.aimfast.compare_residuals(residuals, skymodel=None, points=None, inline=False, area_factor=None, prefix=None, fov_factor=None, units='micro', title_size='14pt', xmajor_size='6pt', ymajor_size='6pt', legend_size='10pt', x_label_size='12pt', y_label_size='12pt', svg=False)[source]
aimfast.aimfast.convert_catalog_with_mapping(catalog, mappings)[source]

Convert a generic table/catalog to a Tigger SkyModel using user-provided mappings.

Mappings can use column names or column indices (as strings containing digits). Supported mapping keys: ‘position_xaxis’,’position_yaxis’,’position_err_xaxis’, ‘position_err_yaxis’,’flux_xaxis’,’flux_yaxis’,’flux_err_xaxis’,’flux_err_yaxis’,’name’

RA/DEC values may be in degrees or in HH:MM:SS / DD:MM:SS string formats.

aimfast.aimfast.create_logger()[source]

Create a console logger

aimfast.aimfast.fitsInfo(fitsname=None)[source]

Get fits header info.

Parameters

fitsnamefits file

Restored image (cube)

Returns

fitsinfodict

Dictionary of fits information e.g. {‘wcs’: wcs, ‘ra’: ra, ‘dec’: dec, ‘dra’: dra, ‘ddec’: ddec, ‘raPix’: raPix, ‘decPix’: decPix, ‘b_size’: beam_size, ‘numPix’: numPix, ‘centre’: centre, ‘skyArea’: skyArea}

aimfast.aimfast.fix_wcs_fits(wcs, dropaxis=2)[source]

This removes the degenerated dimensions in APLpy 2.X… The input must be the object returned by aplpy.FITSFigure(). dropaxis is the index where to start dropping the axis (by default it assumes the 3rd,4th place).

aimfast.aimfast.generate_default_config(configfile)[source]

Generate default config file for running source finders.

Parameters

configfilestr

Path where the config file should be written

Returns

None

Copies the default source_finder.yml to the specified path

aimfast.aimfast.get_aimfast_data(filename='fidelity_results.json', dir='.')[source]

Extract data from the json data file.

Parameters

filenamestr, optional

Name of the json file. Default is ‘fidelity_results.json’

dirstr, optional

Directory containing the json file. Default is current directory

Returns

dict

Dictionary containing the data from the json file

Raises

FileNotFoundError

If the json file does not exist

json.JSONDecodeError

If the file is not valid JSON

aimfast.aimfast.get_argparser()[source]

Get argument parser.

aimfast.aimfast.get_box(wcs, radec, w)[source]

Get box of width w around source coordinates radec.

Parameters

radectuple

RA and DEC in degrees.

wint

Width of box.

wcsatropy.wcs instance

World Coordinate System.

Returns

boxtuple

A box centred at radec.

aimfast.aimfast.get_detected_sources_properties(model_1, model_2, tolerance=1.0, shape_limit=16.0, all_sources=False, closest_only=False, off_axis=None, flux_units='milli', model_1_mappings=None, model_2_mappings=None, phase_centre=None)[source]

Extracts the output simulation sources properties.

Parameters

models_1file

Tigger formatted or txt model 1 file

models_2file

Compare all sources in the catalog (else only sources with maj<shape_limit)

tolerancefloat

Tolerace to cross-match sources

shape_limit: float

Cross match only sources with maj-axis less than this value

closest_only: bool

Returns the closest source only as the matching source

off_axis: float

Cross-match only sources within this distance from the centre

Returns

(targets_flux, targets_scale, targets_position)tuple

Tuple of target flux, morphology and astrometry information

aimfast.aimfast.get_image_products(images, mask)[source]

Get a product of images with a mask

Parameters

images: list

List of fits images to get product

mask: str

Mask to multiply the images

Returns

prod_images: list

List of resulting fits images

aimfast.aimfast.get_model(catalog, mappings=None)[source]

Get model object from file catalog.

If mappings is provided (dict of column mappings), unsupported catalog formats will be converted using those mappings and a Tigger SkyModel will be saved as <catalog>*.lsm.html. If a phase centre cannot be determined it will be left unset and a warning is emitted (plots will skip colorbar).

aimfast.aimfast.get_region_stats(fitsname, regions_file)[source]

Extract flux densities measurements within the provided region

aimfast.aimfast.get_sf_params(configfile)[source]
aimfast.aimfast.get_source_overlay(sources1, sources2)[source]

Get source from models compare for overlay

aimfast.aimfast.get_source_properties_from_catalog(catalog_file)[source]
aimfast.aimfast.get_src_scale(source_shape)[source]

Get scale measure of the source in arcsec.

Parameters

source_shapelsm object

Source shape object from model

Returns

(scale_out_arc_sec, scale_out_err_arc_sec)tuple

Output source scale with error value

aimfast.aimfast.image_dynamic_range(fitsname, residual, area_factor=6)[source]

Gets the dynamic range in a restored image.

Parameters

fitsnamefits file

Restored image (cube).

residualfits file

Residual image (cube).

area_factor: int

Factor to multiply the beam area.

Returns

DRdict

DRs - dynamic range values.

aimfast.aimfast.image_stats(image_data, test_normality=None, data_range=None)[source]
aimfast.aimfast.json_dump(data_dict, filename='fidelity_results.json')[source]

Dumps the computed dictionary results into a json file.

Parameters

data_dictdict

Dictionary with output results to save.

filenamestr

Name of file json file where fidelity results will be dumped. Default is ‘fidelity_results.json’ in the current directory.

Note1

If the fidelity_results.json file exists, it will be append, and only repeated image assessments will be replaced.

aimfast.aimfast.main()[source]

Main function.

aimfast.aimfast.measure_psf(psffile, arcsec_size=20)[source]

Measure point spread function after deconvolution.

Parameters

psfilefits file

Point spread function file.

arcsec_sizefloat

Cross section size

Returns

r0float

Average psf size.

aimfast.aimfast.model_dynamic_range(lsmname, fitsname, beam_size=5, area_factor=2)[source]

Gets the dynamic range using model lsm and residual fits.

Parameters

fitsnamefits file

Residual image (cube).

lsmnamelsm.html or .txt file

Model .lsm.html from pybdsm (or .txt converted tigger file).

beam_sizefloat

Average beam size in arcsec.

area_factorfloat

Factor to multiply the beam area.

Returns

DRdict

DRs - dynamic range values.

aimfast.aimfast.noise_sigma(noise_image)[source]

Determines the noise sigma level in a dirty image with no source

Parameters

noise_imagefile

Noise image (cube).

Returns

noise_stdfloat

Noise image standard deviation

aimfast.aimfast.normality_testing(data, test_normality='normaltest', data_range=None)[source]

Performs a normality test on the image data.

Parameters

datanumpy.array

Residual residual array. i.e. fitsio.open(fitsname)[0].data

test_normalitystr

Perform normality testing using either shapiro or normaltest.

data_rangeint

Range of data to perform normality testing.

Returns

normalitydict

dictionary of stats props. e.g. {‘NORM’: (123.3, 0.012)} whereby the first element is the statistics (or average if data_range specified) of the datasets and second element is the p-value.

aimfast.aimfast.plot_aimfast_stats(fidelity_results_file, units='micro', prefix='')[source]

Plot stats results if more that one residual images where assessed

aimfast.aimfast.plot_astrometry(models, label=None, tolerance=1.0, phase_centre=None, all_sources=False, off_axis=None, restored_image=None)[source]

Plot model-model positions from lsm.html/txt models

Parameters

modelsdict

Tigger/text formatted model files e.g {model1: model2}.

labelstr

Use this label instead of the FITS image path when saving data.

tolerance: float

Radius around the source to be cross matched.

phase_centrestr

Phase centre of catalog (if not already embeded)

all_source: bool

Compare all sources in the catalog (else only point-like source)

restored_imagestr

Path to restored FITS image to overlay as background in catalog overlay plot

aimfast.aimfast.plot_model_columns(catalog_file, x, y, x_err=None, y_err=None, svg=False, x_label=None, y_label=None, title=None, html_prefix=None, title_size='16pt', x_label_size='12pt', y_label_size='12pt', legend_size='10pt', xmajor_size='6pt', ymajor_size='6pt', units='micro')[source]

Plot catalog columns including their uncertainties

aimfast.aimfast.plot_model_data(catalog_file, html_prefix='')[source]

Plotting catalog table

aimfast.aimfast.plot_photometry(models, label=None, tolerance=1.0, phase_centre=None, all_sources=False, flux_plot='log', off_axis=None, shape_limit=16.0)[source]

Plot model-model fluxes from lsm.html/txt models

Parameters

modelsdict

Tigger/text formatted model files e.g {model1: model2}.

labelstr

Use this label instead of the FITS image path when saving data.

tolerance: float

Radius around the source to be cross matched (in arcsec).

phase_centrestr

Phase centre of catalog (if not already embeded)

all_source: bool

Compare all sources in the catalog (else only point-like source)

aimfast.aimfast.plot_residuals_noise(res_noise_images, skymodel=None, label=None, area_factor=2.0, points=100)[source]

Plot residual-residual or noise data

Parameters

res_noise_images: dict

Dictionary of residual images to plot {res1.fits: res2.fits}.

skymodel: file

Skymodel file to locate on source residuals (lsm.html/txt)

labelstr

Use this label instead of the FITS image path when saving data.

area_factorfloat

Factor to multiply the beam area.

points: int

Number of data point to generate in case of random residuals.

aimfast.aimfast.plot_subimage_stats(fitsnames, centre_coords, sizes, htmlprefix='default', title_size='12pt', x_label_size='10pt', y_label_size='10pt', bar_label_size='15pt', units='micro', svg=False)[source]

Plot subimages and stats

aimfast.aimfast.residual_image_stats(fitsname, test_normality=None, data_range=None, threshold=None, chans=None, mask=None)[source]

Gets statistcal properties of a residual image.

Parameters

fitsnamefile

Residual image (cube).

test_normalitystr

Perform normality testing using either shapiro or normaltest.

data_rangeint, optional

Range of data to perform normality testing.

thresholdfloat, optional

Cut-off threshold to select channels in a cube

chansstr, optional

Channels to compute stats (e.g. 1;0~50;100~200)

maskfile

Fits mask to get stats in image

Returns

propsdict

Dictionary of stats properties. e.g. {‘MEAN’: 0.0, ‘STDDev’: 0.1, ‘RMS’: 0.1,

‘SKEW’: 0.2, ‘KURT’: 0.3, ‘MAD’: 0.4, ‘MAX’: 0.7, ‘SUM_NEG’: -0.1}

Notes

If normality_test=True, dictionary of stats props becomes e.g. {‘MEAN’: 0.0, ‘STDDev’: 0.1, ‘SKEW’: 0.2, ‘KURT’: 0.3, ‘MAD’: 0.4, ‘RMS’: 0.5, ‘SUM_NEG’: -0.1, ‘MAX’: 0.7, ‘NORM’: (123.3,0.012)} whereby the first element is the statistics (or average if data_range specified) of the datasets and second element is the p-value.

aimfast.aimfast.source_finding(sf_params, sf=None, mappings=None, outdir=None)[source]

Run configured source finder and ensure a Tigger .lsm.html is produced.

Parameters

sf_params: dict

Source finder parameters from config

sf: str

Optional selected source finder key

mappings: dict

Optional column mappings for conversion (flux/position)

outdir: str

Optional directory to write output catalogs to (default: next to the input image). Ignored for a finder if its config already sets an explicit output path (pybdsf’s outfile, breizorro’s outcatalog, aegean’s table).

aimfast.aimfast.targets_not_matching(sources1, sources2, matched_names, flux_units='milli')[source]

Plot model-model fluxes from lsm.html/txt models

Parameters

sources1: list

List of sources from model 1

sources2: list

List of sources Sources from model 2

matched_names: dict

Dict of names from model 2 that matched that of model 1

flux_units: str

Units of flux density for tabulated values

Returns

target_no_match1: dict

Sources from model 1 that have no match in model 2

target_no_match2: dict

Sources from model 2 that have no match in model 1

amifast.tests.test_aimfast module

class aimfast.tests.test_aimfast.TestClass[source]

Bases: object

aimfast Test klass

test_catalog_default_extension()[source]

Test default filename extension selection for catalog formats

test_catalog_display_name_handles_decimal_in_tilename()[source]

Regression test: _catalog_display_name must not truncate at the first ‘.’ in a path, naive basename.split(“.”)[0] (the previous approach) collapses any two catalogues sharing a tile name with a literal decimal point (e.g. ‘G312.5’, common in this project’s naming) to the same string, e.g. both ‘cosmetic_G312.5_full_breizorro_catalog.txt’ and ‘cosmetic_G312.5_full_aegean_icrs.lsm.html’ truncated to ‘cosmetic_G312’, which made aimfast’s flux-plot axis labels and position-overlay legend indistinguishable between the two catalogues (Bokeh merges glyphs sharing an identical legend_label into a single legend entry).

test_catalogs_overlay_ra_axis_flipped_without_background_image(tmp_path, monkeypatch)[source]

Regression test: the ‘Catalogs Overlay’ panel’s RA axis must increase leftward (standard astronomical convention, viewing the sky from inside looking out, not a ground map from above), even when no –restored-image background is supplied. Bokeh’s Range1d has no working ‘flipped’ toggle (a previous attempt at x_range.flipped = True here was dead code, commented out); the correct approach, already used correctly in the with-background- image branch, is swapping start/end. Verified by intercepting the actual Bokeh figure object passed to save() (monkeypatched), rather than parsing the serialized HTML/JSON output.

test_combined_report_produces_single_tabbed_html(tmp_path)[source]

–combined-report / combined_report=True should produce one <prefix>-Report.html with both Flux and Position tabs, instead of separate FluxOffset.html/PositionOffset.html files.

test_compare_images_forwards_sf_threshold(tmp_path, monkeypatch)[source]

–compare-images should let –sf-threshold override the selected finder’s detection threshold, matching what the source-finder subcommand’s –threshold already does (previously –compare-images had no way to override this at all).

test_compare_models_forwards_shape_limit(tmp_path)[source]

Regression test: compare_models() must actually forward its shape_limit argument to get_detected_sources_properties(), it previously silently dropped it, so the CLI’s -sl/–shape-limit flag had zero effect regardless of value (the underlying function always used its own default, 6.0”).

test_compare_models_with_per_catalog_mappings(tmp_path)[source]

Test compare_models accepts independent column mappings per catalog

test_compare_residuals_on_galactic_2d_image(tmp_path, monkeypatch)[source]

–compare-residuals on a Galactic-frame, plain-2D (no freq/ Stokes axes) image used to crash three different ways in a row: (1) fits_info[“centre”] is raw CRVAL, (l, b) for a Galactic image, not RA/Dec, so get_box()’s ICRS SkyCoord landed random sample points nowhere near the image, producing NaN pixel coords; (2) res_data[0, 0, :, :] assumed a 4D cube, crashing on a plain 2D array; (3) figure(plot_width=…, plot_height=…) is removed in Bokeh 3.x. All three are fixed now, this exercises the full compare_residuals() -> _random_residual_results() -> _residual_plotter() path end to end and checks a real html report is produced.

test_convert_catalog_with_error_metadata(tmp_path)[source]

Test mapped error columns are preserved in source metadata

test_convert_catalog_with_index_columns(tmp_path)[source]

Test conversion of a simple CSV using column indices as mappings

test_convert_catalog_with_sexagesimal(tmp_path)[source]

Test conversion of sexagesimal RA/DEC strings using mappings by name

test_cross_matching_logs_periodic_progress(tmp_path, monkeypatch, caplog)[source]

Cross-matching large catalogues can take minutes with zero other output (confirmed directly: the full-tile grid test took ~30min for a single pair), indistinguishable from a hang while it’s running. A periodic progress log should fire without needing to actually wait, simulate elapsed time via a monkeypatched time.time() rather than a real multi-minute test.

test_cross_matching_stats_table_not_double_converted(tmp_path)[source]

Regression test: the ‘Cross Matching Statistics’ table’s (RA, DEC) mean/sigma offset values must not be double-converted. RA_mean/DEC_mean/r1/r2 are computed from RA_offset/DEC_offset, which get_detected_sources_properties already returns in arcsec (via rad2arcsec()), the table code previously ran them through deg2arcsec() again (x3600), producing implausible thousands-of- arcsec values for genuinely sub-arcsec matches. Checks the actual rendered PositionOffset.html output, not just the underlying data, since the bug was specifically in the table-formatting code.

test_dec2deg_negative()[source]

Test dec2deg with negative declination

test_dec2deg_positive()[source]

Test dec2deg with positive declination

test_default_tolerance_and_shape_limit_widened()[source]

Defaults were 0.2” tolerance / 6.0” shape_limit, too tight for this project’s ~8” beam data (real matches sit 0.07-0.5” apart, real breizorro island shapes commonly exceed 6” and up to ~15”).

test_deg2arcsec()[source]

Test deg2arcsec method

test_deg2ra_large_value()[source]

Test deg2ra handles RA values > 360

test_deg2ra_negative_value()[source]

Test deg2ra handles negative RA values

test_fitsInfo()[source]

Test fitsInfo method

test_flux_plot_large_error_gets_own_legend_entry(tmp_path, monkeypatch)[source]

A source whose flux error exceeds its own flux value used to stretch its error-bar segment across the whole visible log-axis range (clamped near-zero lower bound), distorting the plot. Fixed by routing it into its own, separately click-to-hide legend entry (‘Errors (>100%)’) rather than dropping it or leaving it in the normal ‘Errors’ group.

test_flux_plot_no_large_error_legend_when_all_errors_normal(tmp_path, monkeypatch)[source]

The ‘Errors (>100%)’ legend entry must not appear at all when no source actually has one, Bokeh adds a legend item even for an empty-data glyph, so this needs an explicit guard.

test_flux_plot_stats_table_counts_large_flux_errors(tmp_path, monkeypatch)[source]

The Cross Matching Statistics table should report how many matched sources had a flux error exceeding their own value, so a reader can tell at a glance without inspecting the plot itself.

test_flux_sigma_shade_argparser_flag()[source]

-fss/–flux-sigma-shade must parse as a boolean flag, defaulting to False (band off unless explicitly requested).

test_get_argparser_compare_images_ncpu_and_sourcery_list()[source]

Test general compare-images CLI options parse as expected

test_get_detected_sources_properties()[source]

Test get detected sources properties

test_get_detected_sources_properties_delta_pos_angle_is_physically_sane(tmp_path)[source]

Regression test: delta_pos_angle_arc_sec (the true angular separation between a matched pair) must be a small, physically sane value for a close match, previously this was computed by passing arcsec-scaled values into angular_dist_pos_angle (which expects radians for its internal sin/cos calls), producing an essentially meaningless angle roughly 206265x too large.

test_get_detected_sources_properties_handles_sources_without_shape_errors(tmp_path)[source]

Regression test: matching two catalogues whose sources have a real shape but no shape-error info must not crash get_detected_sources_properties, previously crashed in three places (model1_source’s shape_in_err, model2_source’s shape_out_err, and get_src_scale) whenever getShapeErr() returned None, which is the common case for real Aegean .lsm.html output.

test_get_detected_sources_properties_ra_offset_uses_cos_dec(tmp_path)[source]

Regression test: the RA offset stored per matched source must be scaled by cos(dec), a fixed RA difference subtends a smaller true angle away from the equator. Without it, the RA offset is overstated by 1/cos(dec) (about 2x at this project’s ~-61 deg declination).

test_get_model_reads_aegean_tab(tmp_path, monkeypatch)[source]

Test Aegean-style tab catalogs produce a populated model

test_get_model_sanitizes_aegean_nan_errors(tmp_path, monkeypatch)[source]

Test Aegean nan uncertainty values do not propagate into model attributes

test_get_online_catalog_maps_friendly_names_to_vizier_ids(tmp_path, monkeypatch)[source]

–compare-online has never actually worked: bare ‘SUMSS’/’NVSS’ (the CLI’s own -oc choices) aren’t valid Vizier catalog identifiers and silently resolve to zero results regardless of sky position. Fixed by mapping the short, familiar CLI name to the real Vizier catalog ID internally.

test_get_online_catalog_racs_picks_source_level_table(tmp_path, monkeypatch)[source]

RACS queries return multiple tables (source-level + Gaussian-component-level), must pick the source-level one by name, not just blindly use whichever came first.

test_get_src_scale_handles_none_shape_error()[source]

Regression test: get_src_scale must not crash when shape.getShapeErr() returns None (aimfast.py line ~897 used to do shape_out_err[0]/[1] unconditionally).

test_healthy_match_count_does_not_warn(tmp_path, caplog)[source]

The low-match-count hint must not fire when matching is healthy , it should only appear when genuinely few/no sources matched.

test_image_dynamic_range()[source]

Test dynamic range from image

test_json_dump_appends_json_extension(tmp_path)[source]

Regression test: json_dump() must append .json if the caller’s filename doesn’t already have it, –outfile’s own docstring says the convention is a .json-suffixed name (default ‘fidelity_results.json’), but a user-supplied prefix without the extension was previously written completely literally, producing an extensionless file containing JSON content.

test_json_dump_handles_numpy_float32(tmp_path)[source]

json_dump() crashed with ‘Object of type float32 is not JSON serializable’ whenever a results dict (as produced by the residual/flux comparison pipelines, which compute with numpy) contained a raw numpy scalar rather than a plain Python float.

Test table selection wiring registers a selection callback

test_low_match_count_logs_helpful_warning(tmp_path, caplog)[source]

When very few/no sources match, get_detected_sources_properties should hint at the two most common silent causes, tolerance and shape_limit, rather than leave the user to rediscover this the hard way (as happened repeatedly this session).

test_model_dynamic_range()[source]

Test dynamic range from model

test_noise_sigma()[source]

Test noise sigma metho

test_plot_model_columns_with_plain_catalog(tmp_path)[source]

Test basic catalog plotting works for a plain CSV catalog

test_plot_model_columns_with_sexagesimal_positions(tmp_path)[source]

Test basic catalog plotting accepts sexagesimal RA/Dec strings

test_plot_model_columns_with_txt_catalog(tmp_path)[source]

Test basic catalog plotting works for a commented-header TXT catalog

test_ra2deg_conversion()[source]

Test ra2deg method with standard input

test_rad2arcsec()[source]

Test rad2arcsec method

test_rad2deg()[source]

Test rad2deg method

test_random_residual_results()[source]

Test comparison of random residuals in images

test_residual_stats()[source]

Test the residuals stats method

test_resolve_compare_source_finders()[source]

Test compare-image source finder list resolution

test_resolve_phase_centre_falls_back_on_bad_fits_file(tmp_path, monkeypatch)[source]

Regression test: _resolve_phase_centre must fall back to the model’s own computed centre for any failure reading fits_file, missing file, wrong/corrupt file, or (as happened in practice) a filename heuristic elsewhere in get_model() that guessed a fits_file path equal to the catalogue itself.

test_shape_limit_argparser_type()[source]

Regression test: -sl/–shape-limit must parse as a float, not a bare string, it previously had no type=float (unlike the neighbouring -tol/–tolerance argument), so any CLI-provided value crashed downstream with a float-vs-str TypeError the first time it reached a numeric comparison.

test_source_finder_subcommand_forwards_outdir(tmp_path, monkeypatch)[source]

source-finder –outdir DIR should be threaded through to source_finding() so output catalogs land in DIR instead of always next to the input image (previously no such override existed).

test_source_finder_subcommand_runs_without_dash_c(tmp_path, monkeypatch, caplog)[source]

The source-finder subcommand used to silently do nothing unless –config was explicitly passed, even though -sf/-r/–threshold are documented as standalone overrides. It should instead fall back to an auto-generated default config, matching –compare-images’ existing behaviour.

test_source_residual_results()[source]

Test comparison of source residuals in images

test_tigger_src_racs_handles_missing_error_columns()[source]

RACS-mid/high’s source table has no per-source error columns at all (unlike racs-low); tigger_src_racs must not crash, just default those to 0.0.

test_tigger_src_vlass_round_trip()[source]

VLASS has real per-source errors (unlike racs-mid/high) and different column names (DCMaj/DCMin/DCPA), exercised through the same get_model() ascii-catalog path.

test_weighted_linregress_downweights_noisy_outlier()[source]

Regression test: the flux comparison fit must be weighted by measurement error, not plain OLS (scipy.stats.linregress), so that the many faint/noisy points, which also tend to include the outliers, don’t pull the fit away from where the few precise, bright points actually sit.

test_weighted_linregress_falls_back_without_errors()[source]

No usable error info (all zero) -> falls back to an unweighted fit rather than dividing by zero or dropping points.

test_weighted_linregress_sigma_attribute()[source]

_weighted_linregress must expose .sigma (the error-weighted RMS of the residuals around the fit), used by –flux-sigma-shade to draw a +/-1 sigma data-scatter band around the flux comparison fit line. A perfect y=x fit with zero scatter should report sigma~=0; adding real scatter should increase it.