fixms.fix_ms_corrs ================== .. py:module:: fixms.fix_ms_corrs .. autoapi-nested-parse:: Fix the correlation rotation of ASKAP MSs. Converts the ASKAP standard correlations to the 'standard' correlations This will make them compatible with most imagers (e.g. wsclean, CASA) The new correlations are placed in a new column called 'CORRECTED_DATA' .. !! processed by numpydoc !! Attributes ---------- .. autoapisummary:: fixms.fix_ms_corrs.TQDM_OUT fixms.fix_ms_corrs.__author__ Functions --------- .. autoapisummary:: fixms.fix_ms_corrs.check_data fixms.fix_ms_corrs.check_data_coro fixms.fix_ms_corrs.cli fixms.fix_ms_corrs.convert_correlations fixms.fix_ms_corrs.fix_ms_corrs fixms.fix_ms_corrs.fix_ms_corrs_coro fixms.fix_ms_corrs.gather_with_limit fixms.fix_ms_corrs.get_data_chunk_generator fixms.fix_ms_corrs.get_nchunks_coro fixms.fix_ms_corrs.get_pol_axis fixms.fix_ms_corrs.get_pol_axis_coro fixms.fix_ms_corrs.process_chunk fixms.fix_ms_corrs.set_pol_axis_coro Module Contents --------------- .. py:function:: check_data(ms: pathlib.Path, data_column: str, corrected_data_column: str) -> bool Check if the data in the `data_column`, with a correction applied, matches the data in the `corrected_data_column`. :Parameters: * **ms** (*Path*) -- MeasurementSet to check * **data_column** (*str*) -- Data column to check * **corrected_data_column** (*str*) -- Corrected data column to check :returns: If the data matches :rtype: bool .. !! processed by numpydoc !! .. py:function:: check_data_coro(ms: pathlib.Path, data_column: str, corrected_data_column: str) -> Awaitable[bool] :async: Check if the data in the `data_column`, with a correction applied, matches the data in the `corrected_data_column`. :Parameters: * **ms** (*Path*) -- MeasurementSet to check * **data_column** (*str*) -- Data column to check * **corrected_data_column** (*str*) -- Corrected data column to check :returns: If the data matches :rtype: bool .. !! processed by numpydoc !! .. py:function:: cli() .. py:function:: convert_correlations(correlations: numpy.ndarray, pol_axis: astropy.units.Quantity, fix_stokes_factor: bool = True) -> numpy.ndarray Convert ASKAP standard correlations to the 'standard' correlations :Parameters: * **correlations** (*np.ndarray*) -- The correlations from the MS. Has shape (NCOR, NCHAN, 4) * **pol_axis** (*astropy.units.Quantity*) -- The polarization axis angle of the MS * **fix_stokes_factor** (*bool, optional*) -- Whether to fix the Stokes factor. Defaults to True. :returns: The correlations in the 'standard' format :rtype: np.ndarray NOTES: In general, ASKAP forms Stokes I, Q, U, V as follows: .. code-block:: ⎡I⎤ ⎡ 1 0 0 1 ⎤ ⎡XXₐ⎤ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎢Q⎥ ⎢sin(2⋅P) cos(2⋅P) cos(2⋅P) -sin(2⋅P)⎥ ⎢XYₐ⎥ ⎢ ⎥ = ⎢ ⎥⋅⎢ ⎥ ⎢U⎥ ⎢-cos(2⋅P) sin(2⋅P) sin(2⋅P) cos(2⋅P) ⎥ ⎢YXₐ⎥ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎣V⎦ ⎣ 0 -1.0⋅ⅈ 1.0⋅ⅈ 0 ⎦ ⎣YYₐ⎦ Where P is the polarization axis angle. In the common case of P=-45deg this becomes: .. code-block:: ⎡I⎤ ⎡1 0 0 1⎤ ⎡XXₐ⎤ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎢Q⎥ ⎢-1 0 0 1⎥ ⎢XYₐ⎥ ⎢ ⎥ = ⎢ ⎥⋅⎢ ⎥ ⎢U⎥ ⎢0 -1 -1 0⎥ ⎢YXₐ⎥ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎣V⎦ ⎣0 -1.0⋅ⅈ 1.0⋅ⅈ 0⎦ ⎣YYₐ⎦ or .. code-block:: ⎡I⎤ ⎡ XXₐ + YYₐ ⎤ ⎢ ⎥ ⎢ ⎥ ⎢Q⎥ ⎢ -XXₐ + YYₐ ⎥ ⎢ ⎥ = ⎢ ⎥ ⎢U⎥ ⎢ -XYₐ - YXₐ ⎥ ⎢ ⎥ ⎢ ⎥ ⎣V⎦ ⎣-ⅈ⋅XYₐ + 1.0⋅ⅈ⋅YXₐ⎦ If instead the P=+45deg then this becomes: .. code-block:: ⎡I⎤ ⎡1 0 0 1 ⎤ ⎡XXₐ⎤ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎢Q⎥ ⎢1 0 0 -1⎥ ⎢XYₐ⎥ ⎢ ⎥ = ⎢ ⎥⋅⎢ ⎥ ⎢U⎥ ⎢0 1 1 0 ⎥ ⎢YXₐ⎥ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎣V⎦ ⎣0 -1.0⋅ⅈ 1.0⋅ⅈ 0 ⎦ ⎣YYₐ⎦ or .. code-block:: ⎡I⎤ ⎡ XXₐ + YYₐ ⎤ ⎢ ⎥ ⎢ ⎥ ⎢Q⎥ ⎢ XXₐ - YYₐ ⎥ ⎢ ⎥ = ⎢ ⎥ ⎢U⎥ ⎢ XYₐ + YXₐ ⎥ ⎢ ⎥ ⎢ ⎥ ⎣V⎦ ⎣-ⅈ⋅XYₐ + 1.0⋅ⅈ⋅YXₐ⎦ However, most imagers (e.g. wsclean, CASA) expect .. code-block:: ⎡I⎤ ⎡0.5 0 0 0.5 ⎤ ⎡XX_w⎤ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎢Q⎥ ⎢0.5 0 0 -0.5⎥ ⎢XY_w⎥ ⎢ ⎥ = ⎢ ⎥⋅⎢ ⎥ ⎢U⎥ ⎢ 0 0.5 0.5 0 ⎥ ⎢YX_w⎥ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎣V⎦ ⎣ 0 -0.5⋅i 0.5⋅i 0 ⎦ ⎣YY_w⎦ or .. code-block:: ⎡I⎤ ⎡ 0.5⋅XX_w + 0.5⋅YY_w ⎤ ⎢ ⎥ ⎢ ⎥ ⎢Q⎥ ⎢ 0.5⋅XX_w - 0.5⋅YY_w ⎥ ⎢ ⎥ = ⎢ ⎥ ⎢U⎥ ⎢ 0.5⋅XY_w + 0.5⋅YX_w ⎥ ⎢ ⎥ ⎢ ⎥ ⎣V⎦ ⎣-0.5⋅i⋅XY_w + 0.5⋅i⋅YX_w⎦ To convert between the two, we can use the following matrix: .. code-block:: ⎡XX_w⎤ ⎡sin(2.0⋅P) + 1 cos(2.0⋅P) cos(2.0⋅P) 1 - sin(2.0⋅P)⎤ ⎡XXₐ⎤ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎢XY_w⎥ ⎢ -cos(2.0⋅P) sin(2.0⋅P) + 1 sin(2.0⋅P) - 1 cos(2.0⋅P) ⎥ ⎢XYₐ⎥ ⎢ ⎥ = ⎢ ⎥⋅⎢ ⎥ ⎢YX_w⎥ ⎢ -cos(2.0⋅P) sin(2.0⋅P) - 1 sin(2.0⋅P) + 1 cos(2.0⋅P) ⎥ ⎢YXₐ⎥ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎣YY_w⎦ ⎣1 - sin(2.0⋅P) -cos(2.0⋅P) -cos(2.0⋅P) sin(2.0⋅P) + 1⎦ ⎣YYₐ⎦ Where `_w` is the 'wsclean' format and _a is the 'ASKAP' format. In the case of P=-45deg this becomes: .. code-block:: ⎡XX_w⎤ ⎡0 0 0 2⎤ ⎡XXₐ⎤ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎢XY_w⎥ ⎢0 0 -2 0⎥ ⎢XYₐ⎥ ⎢ ⎥ = ⎢ ⎥⋅⎢ ⎥ ⎢YX_w⎥ ⎢0 -2 0 0⎥ ⎢YXₐ⎥ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎣YY_w⎦ ⎣2 0 0 0⎦ ⎣YYₐ⎦ or .. code-block:: ⎡XX_w⎤ ⎡2⋅YYₐ ⎤ ⎢ ⎥ ⎢ ⎥ ⎢XY_w⎥ ⎢-2⋅YXₐ⎥ ⎢ ⎥ = ⎢ ⎥ ⎢YX_w⎥ ⎢-2⋅XYₐ⎥ ⎢ ⎥ ⎢ ⎥ ⎣YY_w⎦ ⎣2⋅XXₐ ⎦ And in the case of P=+45deg this becomes: .. code-block:: ⎡XX_w⎤ ⎡2 0 0 0⎤ ⎡XXₐ⎤ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎢XY_w⎥ ⎢0 2 0 0⎥ ⎢XYₐ⎥ ⎢ ⎥ = ⎢ ⎥⋅⎢ ⎥ ⎢YX_w⎥ ⎢0 0 2 0⎥ ⎢YXₐ⎥ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎣YY_w⎦ ⎣0 0 0 2⎦ ⎣YYₐ⎦ or .. code-block:: ⎡XX_w⎤ ⎡2⋅XXₐ⎤ ⎢ ⎥ ⎢ ⎥ ⎢XY_w⎥ ⎢2⋅XYₐ⎥ ⎢ ⎥ = ⎢ ⎥ ⎢YX_w⎥ ⎢2⋅YXₐ⎥ ⎢ ⎥ ⎢ ⎥ ⎣YY_w⎦ ⎣2⋅YYₐ⎦ That is, when P=+45 H and V are perfectly aligned with X and Y, and only the factor of 2 is required. .. !! processed by numpydoc !! .. py:function:: fix_ms_corrs(ms: pathlib.Path, chunksize: int = 1000, max_chunks: int = 1000, data_column: str = 'DATA', corrected_data_column: str = 'CORRECTED_DATA', fix_stokes_factor: bool = True) -> None Apply corrections to the ASKAP visibilities to bring them inline with what is expectede from other imagers, including CASA and WSClean. The original data in `data_column` are copied to `corrected_data_column` before the correction is applied. This is done to ensure that the original data are not lost. If 'corrected_data_column' is detected as an existing column then the correction will not be applied. :Parameters: * **ms** (*Path*) -- Path of the ASKAP measurement set tto correct. * **chunksize** (*int, optional*) -- Size of chunked data to correct. Defaults to 10_000. * **data_column** (*str, optional*) -- The name of the data column to correct. Defaults to "DATA". * **corrected_data_column** (*str, optional*) -- The name of the corrected data column. Defaults to "CORRECTED_DATA". * **fix_stokes_factor** (*bool, optional*) -- Whether to fix the Stokes factor. Defaults to True. .. !! processed by numpydoc !! .. py:function:: fix_ms_corrs_coro(ms: pathlib.Path, chunksize: int = 1000, max_chunks: int = 1000, data_column: str = 'DATA', corrected_data_column: str = 'CORRECTED_DATA', fix_stokes_factor: bool = True) -> Awaitable :async: Apply corrections to the ASKAP visibilities to bring them inline with what is expectede from other imagers, including CASA and WSClean. The original data in `data_column` are copied to `corrected_data_column` before the correction is applied. This is done to ensure that the original data are not lost. If 'corrected_data_column' is detected as an existing column then the correction will not be applied. :Parameters: * **ms** (*Path*) -- Path of the ASKAP measurement set tto correct. * **chunksize** (*int, optional*) -- Size of chunked data to correct. Defaults to 10_000. * **data_column** (*str, optional*) -- The name of the data column to correct. Defaults to "DATA". * **corrected_data_column** (*str, optional*) -- The name of the corrected data column. Defaults to "CORRECTED_DATA". * **fix_stokes_factor** (*bool, optional*) -- Whether to fix the Stokes factor. Defaults to True. .. !! processed by numpydoc !! .. py:function:: gather_with_limit(limit: int, *coros: Awaitable) :async: Gather with a limit on the number of coroutines running at once. :Parameters: * **limit** (*int*) -- The number of coroutines to run at once * **coros** (*Awaitable*) -- The coroutines to run :returns: The result of the coroutines :rtype: Awaitable .. !! processed by numpydoc !! .. py:function:: get_data_chunk_generator(ms: pathlib.Path, chunksize: int, data_column: str = 'DATA') -> AsyncGenerator[numpy.ndarray, None] :async: Generator function that will yield a chunk of data from the `ms` data table. :Parameters: * **ms** (*Path*) -- Measurement set whose data will be iterated over * **chunksize** (*int*) -- The number of rows to process per chunk * **data_column** (*str, optional*) -- The column name of the data to iterate. Defaults to "DATA". :Yields: *Iterator[np.ndarray]* -- Chunk of datta to process .. !! processed by numpydoc !! .. py:function:: get_nchunks_coro(ms: pathlib.Path, chunksize: int, data_column: str = 'DATA') -> Awaitable[int] :async: Returns the number of chunks that are needed to iterator over the datacolumsn using a specified `chunksize`. :Parameters: * **ms** (*Path*) -- Measurement sett thatt will be iterated over * **chunksize** (*int*) -- Size of a single chunk * **data_column** (*str, optional*) -- Name of the datacolumn that will be iterated over. Defaults to "DATA". :returns: Number of chunks in a measurement set :rtype: int .. !! processed by numpydoc !! .. py:function:: get_pol_axis(ms: pathlib.Path, feed_idx: Optional[int] = None, col='RECEPTOR_ANGLE') -> astropy.units.Quantity Get the polarization axis from the ASKAP MS. Checks are performed to ensure this polarisation axis angle is constant throughout the observation. :Parameters: * **ms** (*Path*) -- The path to the measurement set that will be inspected * **feed_idx** (*Optional[int], optional*) -- Specify the entry in the FEED * **table of `ms` to return. This might be required when a subset of a** * **measurement set has been extracted from an observation with a varying** * **orientation.** :returns: The rotation of the PAF throughout the observing. :rtype: astropy.units.Quantity .. !! processed by numpydoc !! .. py:function:: get_pol_axis_coro(ms: pathlib.Path, feed_idx: Optional[int] = None, col='RECEPTOR_ANGLE') -> Awaitable[astropy.units.Quantity] :async: Get the polarization axis from the ASKAP MS. Checks are performed to ensure this polarisation axis angle is constant throughout the observation. :Parameters: * **ms** (*Path*) -- The path to the measurement set that will be inspected * **feed_idx** (*Optional[int], optional*) -- Specify the entry in the FEED * **table of `ms` to return. This might be required when a subset of a** * **measurement set has been extracted from an observation with a varying** * **orientation.** :returns: The rotation of the PAF throughout the observing. :rtype: astropy.units.Quantity .. !! processed by numpydoc !! .. py:function:: process_chunk(tab: casacore.tables.table, data_column: str, corrected_data_column: str, pol_axis: astropy.units.Quantity, fix_stokes_factor: bool, start_row: int, chunksize: int, pbar: tqdm.auto.tqdm, chunk_num: int) :async: Work on a chunk of data and write it back to the MS :Parameters: * **data_chunk** (*np.ndarray*) -- Chunk of MS rows * **pol_axis** (*u.Quantity*) -- Rotation angle of the polarization axis * **fix_stokes_factor** (*bool*) -- Whether to fix the Stokes factor * **tab** (*table*) -- MS table object * **corrected_data_column** (*str*) -- Corrected data column * **start_row** (*int*) -- Starting row of the chunk .. !! processed by numpydoc !! .. py:function:: set_pol_axis_coro(ms: pathlib.Path, pol_ang: astropy.units.Quantity, feed_idx: Optional[int] = None) -> Awaitable :async: .. py:data:: TQDM_OUT .. py:data:: __author__ :value: ['Alec Thomson']