# modeltool — sky model management `modeltool` manages sky models in [LSMTool](https://www.astron.nl/citt/lsmtool/) / BBS format for NenuFAR direction-dependent calibration with DP3. --- ## build — fetch sky model from catalog Downloads sources from a radio catalog within a given radius of the Measurement Set phase centre and writes an intrinsic sky model in LSMTool BBS format. ### Usage ``` modeltool build obs.MS ``` By default this fetches all sources brighter than 0.5 Jy (at 74 MHz) within 20° of the phase centre from the LCS165 catalog and writes `catalog.skymodel`. Adjust the field with `--radius`, `--min_flux`, and `--out_file`. Use `--catalog specfind` for the SPECFIND catalog instead: it covers a wider frequency range and may give better spectral indices for some fields, but has fewer sources than LCS165 at NenuFAR frequencies. ### Reference ```{eval-rst} .. click:: nenucal.tools.modeltool:build :prog: modeltool build :nested: full ``` --- ## attenuate / deattentuate — apply and remove the NenuFAR beam `attenuate` converts an intrinsic sky model to an apparent sky model by multiplying each source flux by the NenuFAR beam response at the source position. It also filters out sources and patches that fall below a flux threshold or that are below the horizon during the observation. `deattentuate` is the inverse: it divides source fluxes by the beam to recover the intrinsic model from an apparent one. This is used after a calibration/subtraction step where the pipeline has modified the apparent model and you need to propagate those changes back to intrinsic fluxes. Both commands read the observation time samples and frequency range from the Measurement Set to compute the beam accurately. ### attenuate ``` modeltool attenuate obs.MS catalog.skymodel ``` Produces `apparent.skymodel` with all sources attenuated by the beam and patches below 20 Jy removed. Multiple input models are concatenated before the beam is applied, so the field and A-Team models can be combined in one pass: ``` modeltool attenuate obs.MS catalog.skymodel ateam.skymodel --out_file apparent.skymodel ``` Filtering is controlled by `--min_flux`, `--min_flux_patch`, and `--min_elevation`; `--keep` and `--remove` force specific patches in or out regardless of flux. ### deattentuate ``` modeltool deattentuate obs.MS residual_apparent.skymodel --out_file residual_intrinsic.skymodel ``` Divides source fluxes back out by the beam to recover the intrinsic model. A floor of `--min_beam 0.01` (1 % of peak beam) prevents division by zero for heavily attenuated sources; raise it if faint-source fluxes come out noisy. ### Reference ```{eval-rst} .. click:: nenucal.tools.modeltool:attenuate :prog: modeltool attenuate :nested: full ``` ```{eval-rst} .. click:: nenucal.tools.modeltool:deattentuate :prog: modeltool deattentuate :nested: full ``` --- ## concatenate — merge multiple sky models Concatenates two or more sky model files into one and then applies flux and elevation filtering. This is useful when the main field model and an A-Team model are kept as separate files and need to be combined before clustering. Unlike `attenuate`, no beam is applied — source fluxes are left as they are in the input files. ### Usage ``` modeltool concatenate obs.MS catalog.skymodel ateam.skymodel --out_file combined.skymodel ``` Sources from all inputs are merged into one model. Faint patches are trimmed with `--min_flux_patch`, and `--keep` forces a named patch to survive regardless of its flux. ### Reference ```{eval-rst} .. click:: nenucal.tools.modeltool:concatenate :prog: modeltool concatenate :nested: full ``` --- ## filter — filter a sky model by flux, patch, or elevation Removes sources and patches from a sky model based on flux thresholds, patch names, and optionally the elevation of each patch during an observation. No beam is applied and no Measurement Set is required unless elevation filtering is needed. ### Usage ``` modeltool filter apparent.skymodel --min-flux 1 --out-file filtered.skymodel ``` Removes sources below the flux threshold. Patch-level cuts use `--min-flux-patch`; `--keep` forces a patch to survive and `--remove` drops a named patch outright. Elevation filtering needs a Measurement Set — without `--ms` it is skipped. With one, patches whose maximum elevation during the observation falls below the threshold are also removed: ``` modeltool filter apparent.skymodel --ms obs.MS --min-elevation 20 --out-file filtered.skymodel ``` ### Reference ```{eval-rst} .. click:: nenucal.tools.modeltool:filter_cmd :prog: modeltool filter :nested: full ``` --- ## cluster — group sources into calibration directions Groups sky model sources into direction patches suitable for DP3 direction-dependent calibration (DDECal). Three algorithms are available, all implemented via [LSMTool's grouping operations](https://www.astron.nl/citt/lsmtool/operations.html#group): | Algorithm | LSMTool operation | When to use | |---|---|---| | `cluster` | `group('cluster', numClusters=N)` | Fixed number of directions; K-means on (RA, Dec) | | `tessellate` | `group('tessellate', targetFlux=F)` | Equal total-flux groups; N determined by the sky model | | `voronoi` | `group('voronoi', targetFlux=F)` | Voronoi facets; sources brighter than F become facet centres | After grouping, a summary table is printed showing the position, component count, total Stokes I flux, and brightest component flux of each direction (`--summary_file` saves it to a text file). ### Usage #### K-means clustering into a fixed number of directions ``` modeltool cluster apparent.skymodel --n-clusters 20 --out_file clustered.skymodel ``` ``` Patch RA Dec N_components Total_I_Jy Max_I_Jy --------- --------------- ------------ ------------ ---------- -------- Patch_03 12:34:56.1 +52:30:00 142 312.45 85.20 Patch_07 13:02:11.4 +55:14:00 98 204.10 62.33 ... ``` Choose `--n-clusters` based on the number of DP3 DDECal directions your calibration setup can handle. K-means minimises the total within-cluster angular distance, so clusters are roughly equal in sky area but not in flux. #### Equal-flux tessellation ``` modeltool cluster apparent.skymodel \ --algorithm tessellate \ --target-flux 100 \ --out_file clustered.skymodel ``` LSMTool's `tessellate` groups sources so that each direction contains approximately `--target-flux` Jy of total Stokes I flux. The number of directions is determined automatically. Good choice when you want roughly equal SNR per direction. #### Voronoi facets around bright sources ``` modeltool cluster apparent.skymodel \ --algorithm voronoi \ --target-flux 50 \ --out_file clustered.skymodel ``` LSMTool's `voronoi` uses all sources brighter than `--target-flux` as facet centres; every remaining source is assigned to its nearest centre. This works well when a small number of strong sources dominate the field. ### Reference ```{eval-rst} .. click:: nenucal.tools.modeltool:cluster :prog: modeltool cluster :nested: full ``` --- ## inspect — inspect a grouped sky model Reads a grouped sky model and outputs one of three things depending on `--mode`: | Mode | Output | |---|---| | `summary` *(default)* | Human-readable table: patch name, position, component count, total flux, brightest component | | `dp3-directions` | DP3 `DDECal.directions` string ready to paste into a parset | | `dp3-solints` | DP3 per-direction solution interval string, flux-scaled | ### Usage #### Print a summary table ``` modeltool inspect clustered.skymodel ``` ``` Patch RA Dec N_components Total_I_Jy Max_I_Jy --------- --------------- ------------ ------------ ---------- -------- Patch_03 12:34:56.1 +52:30:00 142 312.45 85.20 Patch_07 13:02:11.4 +55:14:00 98 204.10 62.33 ... ``` Save the table to a text file with `--summary-file`: ``` modeltool inspect clustered.skymodel --summary-file directions.txt ``` #### Generate the DP3 directions string ``` modeltool inspect clustered.skymodel --mode dp3-directions ``` ``` [['Patch_03'],['Patch_07'],['Patch_01'],...] ``` Paste this directly into your DP3 parset as `DDECal.directions`. Exclude a patch (e.g. an A-Team source handled separately): ``` modeltool inspect clustered.skymodel --mode dp3-directions --exclude CasA ``` #### Generate per-direction solution intervals ``` modeltool inspect clustered.skymodel --mode dp3-solints --solint 30 ``` ``` [1,30,15,10,30,5,...] ``` Each value is a divisor of `--solint` chosen proportionally to the patch flux evaluated at `--target-freq-mhz` (default 66.5 MHz). Brighter patches receive larger solints; the `Main` patch is always assigned 1. Paste this into your DP3 parset as `DDECal.solutions_per_direction`. The flux normalisation is tuned with `--max-flux`, `--min-flux`, and `--target-freq-mhz`. ### Reference ```{eval-rst} .. click:: nenucal.tools.modeltool:inspect :prog: modeltool inspect :nested: full ``` --- ## plot — visualise a sky model Plots source positions on the sky with one colour per patch. Useful for checking cluster assignments after `modeltool cluster` or verifying which sources survive after filtering. ### Usage ``` modeltool plot clustered.skymodel ``` Opens an interactive window with each patch in a distinct colour and marker size scaled by source flux, so the dominant components stand out. Pass `--out-file directions.png` to save instead of showing (any Matplotlib format works — PNG, PDF, SVG). `--no-scale-flux` gives uniform markers, and `--min-flux 5` plots only sources above 5 Jy — useful for checking which sources drive the bright-patch assignments after `tessellate` or `voronoi`. ### Reference ```{eval-rst} .. click:: nenucal.tools.modeltool:plot :prog: modeltool plot :nested: full ``` --- ## set_patch_name — rename all patches to a single name Renames every source in the sky model to the same patch. This is typically used to reset a sky model to a single-patch state before re-clustering, or to set the `Main` patch name expected by downstream tools such as `modeltool inspect --mode dp3-solints`. ### Usage #### Reset a clustered model to a single patch before re-clustering ``` modeltool set_patch_name clustered.skymodel Main --out_file reset.skymodel ``` #### Rename in place When `--out_file` is omitted the input file is overwritten: ``` modeltool set_patch_name catalog.skymodel Main ``` ### Reference ```{eval-rst} .. click:: nenucal.tools.modeltool:set_patch_name :prog: modeltool set_patch_name :nested: full ```