|
2 | 2 |
|
3 | 3 | ## ca**S**a pytho**N** self-calibrati**O**n frame**W**ork |
4 | 4 |
|
5 | | -Many radio-astronomers repeat the process of writing different scripts for self-calibration |
6 | | -depending on their datasets. This repository holds an object-oriented Framework for self-calibration |
7 | | -of radio-interferometric datasets that will help radio astronomers to minimize the tedious work of |
8 | | -writing self-calibration scripts once again. The idea is to call just one main Python script that |
9 | | -will run an imager (tclean, wsclean, gpuvmem, rascil, etc.) and one or multiple self-calibration |
10 | | -objects (phase, amplitude, amplitude-phase) having the self-calibrated dataset as a result. |
| 5 | +**SNOW** is an object-oriented Python framework for radio-interferometric self-calibration that simplifies the process of writing self-calibration scripts. Instead of rewriting calibration workflows for each dataset, SNOW provides a unified interface to run imagers (tclean, wsclean, gpuvmem, rascil, etc.) and self-calibration algorithms (phase, amplitude, amplitude-phase) in a single, streamlined workflow. |
| 6 | + |
| 7 | +### Features |
| 8 | + |
| 9 | +- **Object-oriented design**: Clean, modular architecture for easy customization |
| 10 | +- **Multiple imagers supported**: CASA tclean, wsclean, GPUvmem, and more |
| 11 | +- **Flexible self-calibration**: Phase-only, amplitude-only, or combined amplitude-phase calibration |
| 12 | +- **CASA integration**: Built on CASA (Common Astronomy Software Applications) for radio astronomy data processing |
| 13 | +- **Reproducible workflows**: Version-controlled calibration pipelines |
| 14 | +- **Docker support**: Pre-built container images for easy deployment |
11 | 15 |
|
12 | 16 | ## Requirements |
13 | 17 |
|
14 | | -1. `Python == 3.8` |
15 | | -2. Check [CASA pip package requirements](https://casadocs.readthedocs.io/en/stable/notebooks/introduction.html#Modular-Packages) for current version requirements. |
16 | | -3. Check the `requirements.txt` file. |
| 18 | +- **Python**: `>=3.10, <3.11` (Python 3.10 only, due to CASA compatibility requirements) |
| 19 | +- **CASA packages**: See [CASA pip package requirements](https://casadocs.readthedocs.io/en/stable/notebooks/introduction.html#Modular-Packages) for current version requirements |
| 20 | +- **Dependencies**: See `requirements.txt` for a complete list of required packages |
| 21 | + |
| 22 | +### Key Dependencies |
| 23 | + |
| 24 | +- **CASA packages**: casatasks, casatools, casashell, and related CASA modules |
| 25 | +- **Scientific Python**: numpy (1.26.0), scipy (1.15.0), astropy (6.1.0) |
| 26 | +- **Astronomy tools**: reproject (0.14.1), python-casacore (3.7.1) |
17 | 27 |
|
18 | 28 | ## Installation |
19 | 29 |
|
20 | | -### From PYPI repository |
| 30 | +### Option 1: From PyPI (Recommended) |
| 31 | + |
| 32 | +```bash |
| 33 | +pip install snow |
| 34 | +``` |
| 35 | + |
| 36 | +### Option 2: From GitHub |
| 37 | + |
| 38 | +```bash |
| 39 | +pip install -U git+https://github.com/miguelcarcamov/snow.git |
| 40 | +``` |
21 | 41 |
|
22 | | -- `pip install snow` |
| 42 | +### Option 3: Using Conda |
23 | 43 |
|
24 | | -### From Github |
| 44 | +Create a conda environment from the provided environment file: |
| 45 | + |
| 46 | +```bash |
| 47 | +conda env create -f environment.yml |
| 48 | +conda activate snow-env |
| 49 | +``` |
25 | 50 |
|
26 | | -- `pip install -U git+https://github.com/miguelcarcamov/snow` |
| 51 | +The environment file includes all system dependencies and will automatically install Python packages from `requirements.txt`. |
27 | 52 |
|
28 | | -### From source |
| 53 | +### Option 4: From Source |
29 | 54 |
|
30 | 55 | ```bash |
31 | 56 | git clone https://github.com/miguelcarcamov/snow |
32 | 57 | cd snow |
33 | 58 | pip install . |
34 | 59 | ``` |
35 | 60 |
|
36 | | -### From source as developer |
| 61 | +### Option 5: Development Installation |
| 62 | + |
| 63 | +For development work with editable installation: |
37 | 64 |
|
38 | 65 | ```bash |
39 | 66 | git clone https://github.com/miguelcarcamov/snow |
40 | 67 | cd snow |
41 | 68 | pip install -e . |
42 | 69 | ``` |
43 | 70 |
|
44 | | -## Using docker container |
| 71 | +### Option 6: Docker Container |
| 72 | + |
| 73 | +Pull the pre-built Docker image: |
45 | 74 |
|
46 | 75 | ```bash |
47 | 76 | docker pull ghcr.io/miguelcarcamov/snow:latest |
48 | 77 | ``` |
49 | 78 |
|
50 | | -## Run snow |
| 79 | +The Docker image includes all dependencies and is ready to use. See the [Docker documentation](https://docs.docker.com/) for usage instructions. |
| 80 | + |
| 81 | +## Quick Start |
| 82 | + |
| 83 | +### Basic Usage Example |
51 | 84 |
|
52 | 85 | ```python |
53 | | -# Import the modules that you want to use |
54 | 86 | import sys |
55 | 87 | from snow.selfcalibration import Phasecal, AmpPhasecal |
56 | 88 | from snow.imaging import Tclean |
57 | 89 |
|
58 | 90 | if __name__ == '__main__': |
59 | | - # This step is up to you, and option to capture your arguments from terminal is using sys.argv |
60 | | - visfile = sys.argv[3] |
61 | | - output = sys.argv[4] |
62 | | - want_plot = eval(sys.argv[5]) |
63 | | - |
64 | | - # Table for automasking on long or short baselines can be found here: https://casaguides.nrao.edu/index.php/Automasking_Guide |
65 | | - # The default clean object will use automasking values for short baselines |
66 | | - # In this case we will use automasking values for long baselines |
67 | | - # Create different imagers with different thresholds (this is optional, you can create just one) |
68 | | - clean_imager_phs = Tclean(inputvis=visfile, output=output, niter=100, M=1024, N=1024, cell="0.005arcsec", |
69 | | - stokes="I", datacolumn="corrected", robust=0.5, |
70 | | - specmode="mfs", deconvolver="hogbom", gridder="standard", |
71 | | - savemodel=True, usemask='auto-multithresh', threshold="0.1mJy", sidelobethreshold=3.0, |
72 | | - noisethreshold=5.0, |
73 | | - minbeamfrac=0.3, lownoisethreshold=1.5, negativethreshold=0.0, interactive=True) |
74 | | - |
75 | | - clean_imager_ampphs = Tclean(inputvis=visfile, output=output, niter=100, M=1024, N=1024, cell="0.005arcsec", |
76 | | - stokes="I", datacolumn="corrected", robust=0.5, |
77 | | - specmode="mfs", deconvolver="hogbom", gridder="standard", |
78 | | - savemodel=True, usemask='auto-multithresh', threshold="0.025mJy", |
79 | | - sidelobethreshold=3.0, |
80 | | - noisethreshold=5.0, |
81 | | - minbeamfrac=0.3, lownoisethreshold=1.5, negativethreshold=0.0, interactive=True) |
82 | | - |
83 | | - # This is a dictionary with shared variables between self-cal objects |
84 | | - shared_vars_dict = {'visfile': visfile, 'minblperant': 6, 'refant': "DA51", 'spwmap': [ |
85 | | - 0, 0, 0, 0], 'gaintype': 'T', 'want_plot': want_plot} |
86 | | - |
87 | | - # Create your solution intervals |
88 | | - solint_phs = ['inf', '600s'] |
89 | | - solint_ap = ['inf'] |
90 | | - |
91 | | - # Create your phasecal object |
92 | | - phscal = Phasecal(minsnr=3.0, solint=solint_phs, combine="spw", imager=clean_imager_phs, **shared_vars_dict) |
93 | | - # Run it! |
94 | | - phscal.run() |
95 | | - |
96 | | - # If we are happy with the result of the only-phase self-cal we can end the code here, if not... |
97 | | - # Create the amplitude-phase self-cal object |
98 | | - apcal = AmpPhasecal(minsnr=3.0, solint=solint_ap, combine="", previous_selfcal=phscal, imager=clean_imager_ampphs, |
99 | | - **shared_vars_dict) |
100 | | - # Run it |
101 | | - apcal.run() |
102 | | - # Get your splitted final MS |
103 | | - apcal.selfcal_output(overwrite=True) |
| 91 | + # Get input parameters (adjust as needed for your use case) |
| 92 | + visfile = sys.argv[1] # Input measurement set |
| 93 | + output = sys.argv[2] # Output prefix |
| 94 | + want_plot = eval(sys.argv[3]) # Whether to generate plots |
| 95 | + |
| 96 | + # Create imager for phase calibration |
| 97 | + # See CASA automasking guide: https://casaguides.nrao.edu/index.php/Automasking_Guide |
| 98 | + clean_imager_phs = Tclean( |
| 99 | + inputvis=visfile, |
| 100 | + output=output, |
| 101 | + niter=100, |
| 102 | + M=1024, |
| 103 | + N=1024, |
| 104 | + cell="0.005arcsec", |
| 105 | + stokes="I", |
| 106 | + datacolumn="corrected", |
| 107 | + robust=0.5, |
| 108 | + specmode="mfs", |
| 109 | + deconvolver="hogbom", |
| 110 | + gridder="standard", |
| 111 | + savemodel=True, |
| 112 | + usemask='auto-multithresh', |
| 113 | + threshold="0.1mJy", |
| 114 | + sidelobethreshold=3.0, |
| 115 | + noisethreshold=5.0, |
| 116 | + minbeamfrac=0.3, |
| 117 | + lownoisethreshold=1.5, |
| 118 | + negativethreshold=0.0, |
| 119 | + interactive=True |
| 120 | + ) |
| 121 | + |
| 122 | + # Create imager for amplitude-phase calibration (with lower threshold) |
| 123 | + clean_imager_ampphs = Tclean( |
| 124 | + inputvis=visfile, |
| 125 | + output=output, |
| 126 | + niter=100, |
| 127 | + M=1024, |
| 128 | + N=1024, |
| 129 | + cell="0.005arcsec", |
| 130 | + stokes="I", |
| 131 | + datacolumn="corrected", |
| 132 | + robust=0.5, |
| 133 | + specmode="mfs", |
| 134 | + deconvolver="hogbom", |
| 135 | + gridder="standard", |
| 136 | + savemodel=True, |
| 137 | + usemask='auto-multithresh', |
| 138 | + threshold="0.025mJy", |
| 139 | + sidelobethreshold=3.0, |
| 140 | + noisethreshold=5.0, |
| 141 | + minbeamfrac=0.3, |
| 142 | + lownoisethreshold=1.5, |
| 143 | + negativethreshold=0.0, |
| 144 | + interactive=True |
| 145 | + ) |
| 146 | + |
| 147 | + # Shared parameters for self-calibration objects |
| 148 | + shared_vars_dict = { |
| 149 | + 'visfile': visfile, |
| 150 | + 'minblperant': 6, |
| 151 | + 'refant': "DA51", |
| 152 | + 'spwmap': [0, 0, 0, 0], |
| 153 | + 'gaintype': 'T', |
| 154 | + 'want_plot': want_plot |
| 155 | + } |
| 156 | + |
| 157 | + # Solution intervals for phase calibration |
| 158 | + solint_phs = ['inf', '600s'] |
| 159 | + |
| 160 | + # Solution intervals for amplitude-phase calibration |
| 161 | + solint_ap = ['inf'] |
| 162 | + |
| 163 | + # Phase-only self-calibration |
| 164 | + phscal = Phasecal( |
| 165 | + minsnr=3.0, |
| 166 | + solint=solint_phs, |
| 167 | + combine="spw", |
| 168 | + imager=clean_imager_phs, |
| 169 | + **shared_vars_dict |
| 170 | + ) |
| 171 | + phscal.run() |
| 172 | + |
| 173 | + # Amplitude-phase self-calibration (optional, only if phase calibration is successful) |
| 174 | + apcal = AmpPhasecal( |
| 175 | + minsnr=3.0, |
| 176 | + solint=solint_ap, |
| 177 | + combine="", |
| 178 | + previous_selfcal=phscal, |
| 179 | + imager=clean_imager_ampphs, |
| 180 | + **shared_vars_dict |
| 181 | + ) |
| 182 | + apcal.run() |
| 183 | + |
| 184 | + # Output the final calibrated measurement set |
| 185 | + apcal.selfcal_output(overwrite=True) |
104 | 186 | ``` |
105 | 187 |
|
106 | | -Then you can simply run the main script using `python yourscript.py <arguments>` |
| 188 | +Run the script: |
| 189 | + |
| 190 | +```bash |
| 191 | +python yourscript.py <visfile> <output_prefix> True |
| 192 | +``` |
| 193 | + |
| 194 | +## API Overview |
| 195 | + |
| 196 | +### Imaging Classes |
| 197 | + |
| 198 | +SNOW supports multiple imaging backends: |
| 199 | + |
| 200 | +- **`Tclean`**: CASA tclean task wrapper for standard imaging |
| 201 | +- **`WSClean`**: WSClean imager interface |
| 202 | +- **`GPUvmem`**: GPU-accelerated imaging with GPUvmem |
| 203 | +- **`Imager`**: Base class for custom imagers |
| 204 | + |
| 205 | +### Self-Calibration Classes |
| 206 | + |
| 207 | +- **`Phasecal`**: Phase-only self-calibration |
| 208 | +- **`Ampcal`**: Amplitude-only self-calibration |
| 209 | +- **`AmpPhasecal`**: Combined amplitude-phase self-calibration |
| 210 | +- **`Selfcal`**: Base class for self-calibration algorithms |
| 211 | + |
| 212 | +### Utility Modules |
| 213 | + |
| 214 | +- **`snow.utils.image_utils`**: Image processing utilities |
| 215 | +- **`snow.utils.selfcal_utils`**: Self-calibration helper functions |
| 216 | + |
| 217 | +## Project Structure |
| 218 | + |
| 219 | +``` |
| 220 | +snow/ |
| 221 | +├── src/snow/ |
| 222 | +│ ├── imaging/ # Imaging backends (tclean, wsclean, gpuvmem) |
| 223 | +│ ├── selfcalibration/ # Self-calibration algorithms |
| 224 | +│ └── utils/ # Utility functions |
| 225 | +├── main_files/ # Example scripts for different telescopes |
| 226 | +├── requirements.txt # Python dependencies |
| 227 | +├── environment.yml # Conda environment specification |
| 228 | +└── pyproject.toml # Project metadata and build configuration |
| 229 | +``` |
| 230 | + |
| 231 | +## Contributing |
| 232 | + |
| 233 | +Contributions are welcome! Please feel free to submit a Pull Request. |
| 234 | + |
| 235 | +## License |
| 236 | + |
| 237 | +This project is licensed under the terms specified in the `LICENSE` file. |
| 238 | + |
| 239 | +## Citation |
| 240 | + |
| 241 | +If you use SNOW in your research, please cite: |
| 242 | + |
| 243 | +```bibtex |
| 244 | +@software{snow, |
| 245 | + author = {Cárcamo, Miguel}, |
| 246 | + title = {SNOW: CASA Python Self-calibration Framework}, |
| 247 | + url = {https://github.com/miguelcarcamov/snow}, |
| 248 | + version = {<version>}, |
| 249 | + year = {<year>} |
| 250 | +} |
| 251 | +``` |
| 252 | + |
| 253 | +## Support |
| 254 | + |
| 255 | +- **Issues**: Report bugs or request features on [GitHub Issues](https://github.com/miguelcarcamov/snow/issues) |
| 256 | +- **Documentation**: See the [CASA documentation](https://casadocs.readthedocs.io/) for CASA-specific questions |
| 257 | +- **Contact**: <miguel.carcamo@usach.cl> |
| 258 | + |
| 259 | +## Acknowledgments |
| 260 | + |
| 261 | +SNOW is built on top of [CASA](https://casa.nrao.edu/) (Common Astronomy Software Applications), developed by the National Radio Astronomy Observatory (NRAO). |
0 commit comments