vcat
  • VCAT Documention

Example Notebooks

  • Tutorial Overview
  • Plotting Images
  • Modifying Images
  • Plotting ImageCubes
  • Modifying ImageCubes
  • Alignment
  • Model Component Analysis
  • Ridgeline Fitting
  • Stacking
  • Turnover Frequency

Code Documentation

  • Code Overview
  • ImageData
  • ImageCube
  • vcat.helpers

About

  • License
  • Release Notes
vcat
  • Example Notebooks
  • Alignment
  • Edit on GitHub

In [1]:
Copied!
from vcat import ImageData, ImageCube

#set important parameters
useDIFMAP=True
from vcat import ImageData, ImageCube #set important parameters useDIFMAP=True
2025-10-08 12:00:38,317 - INFO - vcat - Logging initialized. Log file: Console only.
2025-10-08 12:00:38,318 - INFO - vcat - No environment variable VCAT_CONFIG found, will use defaults.
2025-10-08 12:00:38,319 - INFO - vcat - Using DIFMAP path: /usr/local/difmap/
Thank you for using VCAT. Have fun with VLBI!

If you are using this package please cite VCAT Team et al. 2025 ....

Loading the data¶

In [2]:
Copied!
#This notebook aims to explain the different alignment methods that are possible with the VCAT package

#We will start with two images:
#This is a U-band image which was already shifted by -5,5 manually
data_shifted=ImageData("../dataset_example/3C111_U_shifted/3C111_2014-05-08_15GHz.fits",
        uvf_file="../dataset_example/3C111_U_shifted/3C111_2014-05-08_15GHz.uvf")

#The second dataset is a regular X band image
dataX=ImageData("../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.fits",
        uvf_file="../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.uvf")


#Lets'plot both datasets as an ImageCube to have a look
im_cube=ImageCube([data_shifted,dataX])
im_cube.plot()
#This notebook aims to explain the different alignment methods that are possible with the VCAT package #We will start with two images: #This is a U-band image which was already shifted by -5,5 manually data_shifted=ImageData("../dataset_example/3C111_U_shifted/3C111_2014-05-08_15GHz.fits", uvf_file="../dataset_example/3C111_U_shifted/3C111_2014-05-08_15GHz.uvf") #The second dataset is a regular X band image dataX=ImageData("../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.fits", uvf_file="../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.uvf") #Lets'plot both datasets as an ImageCube to have a look im_cube=ImageCube([data_shifted,dataX]) im_cube.plot()
No description has been provided for this image
Out[2]:
<vcat.plots.multi_fits_image.MultiFitsImage at 0x7229197379d0>

Alignment using cross-correlation¶

In [3]:
Copied!
#We will now try to align the shifted image to the second (unshifted) dataset

#we will use the cross-correlation method
method="cross_correlation" #(default setting)

#And we will also let the code determine a common pixel grid and common beam
auto_regrid=True

#Let's start the alignment, this will align data_shifted -> dataX
data_aligned=data_shifted.align(dataX,method=method,auto_regrid=auto_regrid,useDIFMAP=useDIFMAP)

#And plot the resulting image which is shifted and convolved with the common beam
data_aligned.plot()
#We will now try to align the shifted image to the second (unshifted) dataset #we will use the cross-correlation method method="cross_correlation" #(default setting) #And we will also let the code determine a common pixel grid and common beam auto_regrid=True #Let's start the alignment, this will align data_shifted -> dataX data_aligned=data_shifted.align(dataX,method=method,auto_regrid=auto_regrid,useDIFMAP=useDIFMAP) #And plot the resulting image which is shifted and convolved with the common beam data_aligned.plot()
2025-10-08 12:00:46,305 - INFO - vcat - Automatically regridding image to minimum pixelsize, smallest FOV and common beam
2025-10-08 12:00:47,175 - INFO - vcat - common beam calculated: [1.7770593660568255, 1.1265451854188613, -10.920121192749493]
2025-10-08 12:00:57,875 - INFO - vcat - will apply shift (x,y): [4.28000001011685 : -5.32000001257515] mas
No description has been provided for this image
Out[3]:
<vcat.plots.fits_image.FitsImage at 0x722994f29c40>
In [4]:
Copied!
#We regrid and restore the image cube with the same beam, FoV and pixel size to create the spectral index map
im_cube = ImageCube([data_aligned,dataX])
im_cube = im_cube.regrid(useDIFMAP=useDIFMAP) # automatically determines FoV and pixel size
im_cube = im_cube.restore(bmaj=dataX.beam_maj,bmin=dataX.beam_min,posa=dataX.beam_pa,useDIFMAP=useDIFMAP) # restore with larger beam

#Define the Frequencies to use for spectral index (will automatically pick the images closest to that frequency
freq1=8 #GHz
freq2=15 #GHz

#get the spectral index map
spix_map=im_cube.get_spectral_index_map(freq1,freq2,spix_vmin=-2,spix_vmax=3) # resetting colorbar limits

#The spix_map itself is also an ImageCube object and a copy of the higher frequency image with image.spix set to the spectral index map
spix_map.plot(plot_mode="spix",contour=True,xlim=[15,-5],ylim=[-5,10],do_colorbar=True,figsize=(5,4))
#We regrid and restore the image cube with the same beam, FoV and pixel size to create the spectral index map im_cube = ImageCube([data_aligned,dataX]) im_cube = im_cube.regrid(useDIFMAP=useDIFMAP) # automatically determines FoV and pixel size im_cube = im_cube.restore(bmaj=dataX.beam_maj,bmin=dataX.beam_min,posa=dataX.beam_pa,useDIFMAP=useDIFMAP) # restore with larger beam #Define the Frequencies to use for spectral index (will automatically pick the images closest to that frequency freq1=8 #GHz freq2=15 #GHz #get the spectral index map spix_map=im_cube.get_spectral_index_map(freq1,freq2,spix_vmin=-2,spix_vmax=3) # resetting colorbar limits #The spix_map itself is also an ImageCube object and a copy of the higher frequency image with image.spix set to the spectral index map spix_map.plot(plot_mode="spix",contour=True,xlim=[15,-5],ylim=[-5,10],do_colorbar=True,figsize=(5,4))
2025-10-08 12:01:05,249 - INFO - vcat - Regridding images
2025-10-08 12:01:05,250 - INFO - vcat - Determining smallest pixel size and largest FoV from images for regridding
Processing: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:00<00:00, 33689.19it/s]
Processing: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:14<00:00,  7.01s/it]
2025-10-08 12:01:19,282 - INFO - vcat - Restoring images
Processing: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:14<00:00,  7.45s/it]
2025-10-08 12:01:34,179 - INFO - vcat - Image modifications completed.
2025-10-08 12:01:34,246 - INFO - vcat - Spectral index max(alpha)=4.642858505249023 - min(alpha)=-2.779508113861084
Cutoff -2<alpha<3
No description has been provided for this image
Out[4]:
<vcat.plots.multi_fits_image.MultiFitsImage at 0x722994d9a670>

Alignment using masked cross-correlation¶

In [5]:
Copied!
#Load the data again
#This is a U-band image which was already shifted by -5,5 manually
data_shifted=ImageData("../dataset_example/3C111_U_shifted/3C111_2014-05-08_15GHz.fits",
        uvf_file="../dataset_example/3C111_U_shifted/3C111_2014-05-08_15GHz.uvf")

#The second dataset is a regular X band image
dataX=ImageData("../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.fits",
        uvf_file="../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.uvf")

#We will mask the core region in both images with elliptical masks
e_maj = 4
e_min = 3
e_pa = -10
e_xoffset = -5.32
e_yoffset = 4.28
args_shifted = {
    "e_args":[e_maj,e_min,e_pa],
    "e_xoffset":e_xoffset,
    "e_yoffset":e_yoffset
    }
e_maj = 7
e_min = 5
e_pa = -10
e_xoffset = 0
e_yoffset = 0
args_X = {
    "e_args":[e_maj,e_min,e_pa],
    "e_xoffset":e_xoffset,
    "e_yoffset":e_yoffset
    }

data_shifted.masking(mask_type="ellipse", args=args_shifted)
dataX.masking(mask_type="ellipse", args=args_X)

#And plot the images with the masks applied to check them
im_cube=ImageCube([data_shifted,dataX])
im_cube.plot(plot_mask=True)
#Load the data again #This is a U-band image which was already shifted by -5,5 manually data_shifted=ImageData("../dataset_example/3C111_U_shifted/3C111_2014-05-08_15GHz.fits", uvf_file="../dataset_example/3C111_U_shifted/3C111_2014-05-08_15GHz.uvf") #The second dataset is a regular X band image dataX=ImageData("../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.fits", uvf_file="../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.uvf") #We will mask the core region in both images with elliptical masks e_maj = 4 e_min = 3 e_pa = -10 e_xoffset = -5.32 e_yoffset = 4.28 args_shifted = { "e_args":[e_maj,e_min,e_pa], "e_xoffset":e_xoffset, "e_yoffset":e_yoffset } e_maj = 7 e_min = 5 e_pa = -10 e_xoffset = 0 e_yoffset = 0 args_X = { "e_args":[e_maj,e_min,e_pa], "e_xoffset":e_xoffset, "e_yoffset":e_yoffset } data_shifted.masking(mask_type="ellipse", args=args_shifted) dataX.masking(mask_type="ellipse", args=args_X) #And plot the images with the masks applied to check them im_cube=ImageCube([data_shifted,dataX]) im_cube.plot(plot_mask=True)
No description has been provided for this image
Out[5]:
<vcat.plots.multi_fits_image.MultiFitsImage at 0x722994a70b50>
In [6]:
Copied!
#We will now try to align the shifted image to the second (unshifted) dataset using the masks and the same settings

#Let's start the alignment, this will align data_shifted -> dataX
data_aligned=data_shifted.align(dataX,method=method,auto_regrid=auto_regrid,useDIFMAP=useDIFMAP)

#And plot the resulting image which is shifted and convolved with the common beam
data_aligned.plot()
#We will now try to align the shifted image to the second (unshifted) dataset using the masks and the same settings #Let's start the alignment, this will align data_shifted -> dataX data_aligned=data_shifted.align(dataX,method=method,auto_regrid=auto_regrid,useDIFMAP=useDIFMAP) #And plot the resulting image which is shifted and convolved with the common beam data_aligned.plot()
2025-10-08 12:01:48,512 - INFO - vcat - Automatically regridding image to minimum pixelsize, smallest FOV and common beam
2025-10-08 12:01:49,391 - INFO - vcat - common beam calculated: [1.7770593660568255, 1.1265451854188613, -10.920121192749493]
2025-10-08 12:02:00,801 - INFO - vcat - will apply shift (x,y): [4.68000001106235 : -5.16000001219695] mas
No description has been provided for this image
Out[6]:
<vcat.plots.fits_image.FitsImage at 0x722988be7880>
In [7]:
Copied!
#We regrid and restore the image cube with the same beam, FoV and pixel size to create the spectral index map
im_cube = ImageCube([data_aligned,dataX])
im_cube = im_cube.regrid(useDIFMAP=useDIFMAP) # automatically determines FoV and pixel size
im_cube = im_cube.restore(bmaj=dataX.beam_maj,bmin=dataX.beam_min,posa=dataX.beam_pa,useDIFMAP=useDIFMAP) # restore with larger beam

#Define the Frequencies to use for spectral index (will automatically pick the images closest to that frequency
freq1=8 #GHz
freq2=15 #GHz

#get the spectral index map
spix_map=im_cube.get_spectral_index_map(freq1,freq2,spix_vmin=-2,spix_vmax=3) # resetting colorbar limits

#The spix_map itself is also an ImageCube object and a copy of the higher frequency image with image.spix set to the spectral index map
spix_map.plot(plot_mode="spix",contour=True,xlim=[15,-5],ylim=[-5,10],do_colorbar=True,figsize=(5,4))
#We regrid and restore the image cube with the same beam, FoV and pixel size to create the spectral index map im_cube = ImageCube([data_aligned,dataX]) im_cube = im_cube.regrid(useDIFMAP=useDIFMAP) # automatically determines FoV and pixel size im_cube = im_cube.restore(bmaj=dataX.beam_maj,bmin=dataX.beam_min,posa=dataX.beam_pa,useDIFMAP=useDIFMAP) # restore with larger beam #Define the Frequencies to use for spectral index (will automatically pick the images closest to that frequency freq1=8 #GHz freq2=15 #GHz #get the spectral index map spix_map=im_cube.get_spectral_index_map(freq1,freq2,spix_vmin=-2,spix_vmax=3) # resetting colorbar limits #The spix_map itself is also an ImageCube object and a copy of the higher frequency image with image.spix set to the spectral index map spix_map.plot(plot_mode="spix",contour=True,xlim=[15,-5],ylim=[-5,10],do_colorbar=True,figsize=(5,4))
2025-10-08 12:02:08,674 - INFO - vcat - Regridding images
2025-10-08 12:02:08,675 - INFO - vcat - Determining smallest pixel size and largest FoV from images for regridding
Processing: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:00<00:00, 41734.37it/s]
Processing: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:14<00:00,  7.23s/it]
2025-10-08 12:02:23,140 - INFO - vcat - Restoring images
Processing: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:15<00:00,  7.66s/it]
2025-10-08 12:02:38,455 - INFO - vcat - Image modifications completed.
2025-10-08 12:02:38,531 - INFO - vcat - Spectral index max(alpha)=1.495991587638855 - min(alpha)=-2.748716115951538
Cutoff -2<alpha<3
No description has been provided for this image
Out[7]:
<vcat.plots.multi_fits_image.MultiFitsImage at 0x7229891c06d0>

Alignment using the brightest pixel¶

In [8]:
Copied!
#Instead of using a 2d cross correlation, we can also align the images on the brightest pixel
#Let's load the data again from scratch (this is needed because align() also affects the image that it is called on

#This is a U-band image which was already shifted by -5,5 manually
data_shifted=ImageData("../dataset_example/3C111_U_shifted/3C111_2014-05-08_15GHz.fits",
        uvf_file="../dataset_example/3C111_U_shifted/3C111_2014-05-08_15GHz.uvf")

#The second dataset is a regular X band image
dataX=ImageData("../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.fits",
        uvf_file="../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.uvf")

#This time we will use the 'brightest' method
method="brightest" #align on brightest pixel

#And we will also let the code determine a common pixel grid and common beam
auto_regrid=True

#Let's start the alignment
data_aligned=data_shifted.align(dataX,method=method,auto_regrid=auto_regrid,useDIFMAP=useDIFMAP)

#And plot the resulting image which is shifted and convolved with the common beam
data_aligned.plot()
#Instead of using a 2d cross correlation, we can also align the images on the brightest pixel #Let's load the data again from scratch (this is needed because align() also affects the image that it is called on #This is a U-band image which was already shifted by -5,5 manually data_shifted=ImageData("../dataset_example/3C111_U_shifted/3C111_2014-05-08_15GHz.fits", uvf_file="../dataset_example/3C111_U_shifted/3C111_2014-05-08_15GHz.uvf") #The second dataset is a regular X band image dataX=ImageData("../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.fits", uvf_file="../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.uvf") #This time we will use the 'brightest' method method="brightest" #align on brightest pixel #And we will also let the code determine a common pixel grid and common beam auto_regrid=True #Let's start the alignment data_aligned=data_shifted.align(dataX,method=method,auto_regrid=auto_regrid,useDIFMAP=useDIFMAP) #And plot the resulting image which is shifted and convolved with the common beam data_aligned.plot()
2025-10-08 12:02:49,557 - INFO - vcat - Automatically regridding image to minimum pixelsize, smallest FOV and common beam
2025-10-08 12:02:50,486 - INFO - vcat - common beam calculated: [1.7770593660568255, 1.1265451854188613, -10.920121192749493]
2025-10-08 12:03:01,342 - INFO - vcat - will apply shift (x,y): [5.08000001200785 : -4.68000001106235] mas
No description has been provided for this image
Out[8]:
<vcat.plots.fits_image.FitsImage at 0x722994a37c40>
In [9]:
Copied!
#We regrid and restore the image cube with the same beam, FoV and pixel size to create the spectral index map
im_cube = ImageCube([data_aligned,dataX])
im_cube = im_cube.regrid(useDIFMAP=useDIFMAP) # automatically determines FoV and pixel size
im_cube = im_cube.restore(bmaj=dataX.beam_maj,bmin=dataX.beam_min,posa=dataX.beam_pa,useDIFMAP=useDIFMAP) # restore with larger beam

#Define the Frequencies to use for spectral index (will automatically pick the images closest to that frequency
freq1=8 #GHz
freq2=15 #GHz

#get the spectral index map
spix_map=im_cube.get_spectral_index_map(freq1,freq2,spix_vmin=-2,spix_vmax=3) # resetting colorbar limits

#The spix_map itself is also an ImageCube object and a copy of the higher frequency image with image.spix set to the spectral index map
spix_map.plot(plot_mode="spix",contour=True,xlim=[15,-5],ylim=[-5,10],do_colorbar=True,figsize=(5,4))
#We regrid and restore the image cube with the same beam, FoV and pixel size to create the spectral index map im_cube = ImageCube([data_aligned,dataX]) im_cube = im_cube.regrid(useDIFMAP=useDIFMAP) # automatically determines FoV and pixel size im_cube = im_cube.restore(bmaj=dataX.beam_maj,bmin=dataX.beam_min,posa=dataX.beam_pa,useDIFMAP=useDIFMAP) # restore with larger beam #Define the Frequencies to use for spectral index (will automatically pick the images closest to that frequency freq1=8 #GHz freq2=15 #GHz #get the spectral index map spix_map=im_cube.get_spectral_index_map(freq1,freq2,spix_vmin=-2,spix_vmax=3) # resetting colorbar limits #The spix_map itself is also an ImageCube object and a copy of the higher frequency image with image.spix set to the spectral index map spix_map.plot(plot_mode="spix",contour=True,xlim=[15,-5],ylim=[-5,10],do_colorbar=True,figsize=(5,4))
2025-10-08 12:03:08,712 - INFO - vcat - Regridding images
2025-10-08 12:03:08,713 - INFO - vcat - Determining smallest pixel size and largest FoV from images for regridding
Processing: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:00<00:00, 29537.35it/s]
Processing: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:14<00:00,  7.10s/it]
2025-10-08 12:03:22,908 - INFO - vcat - Restoring images
Processing: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:15<00:00,  7.53s/it]
2025-10-08 12:03:37,979 - INFO - vcat - Image modifications completed.
2025-10-08 12:03:38,055 - INFO - vcat - Spectral index max(alpha)=3.6160566806793213 - min(alpha)=-6.260083198547363
Cutoff -2<alpha<3
No description has been provided for this image
Out[9]:
<vcat.plots.multi_fits_image.MultiFitsImage at 0x72297d6e9580>

Alignment using modelfit components¶

In [10]:
Copied!
#The third option is to align the images based on modelfit components
#This requires to identify matching components between images first

#First let's load some new data again, this time including modelcomponents
#This is now the regular U-band data
dataU=ImageData("../dataset_example/3C111_U_2014_05_08/3C111_U_2014_05_08.fits",
        model="../dataset_example/3C111_U_2014_05_08/3C111_U_2014_05_08.mfit", #can be modelfits .fits or .mod file
        stokes_q="../dataset_example/3C111_U_2014_05_08/3C111_U_2014_05_08.qcln", #load polarization as well, we need it later
        stokes_u="../dataset_example/3C111_U_2014_05_08/3C111_U_2014_05_08.ucln", #load polarization as well, we need it later
        uvf_file="../dataset_example/3C111_U_2014_05_08/3C111_U_2014_05_08.uvf")

#The second dataset is a regular X band image
dataX=ImageData("../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.fits",
                model="../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.mfit", #can be modelfits .fits or .mod file
                stokes_q="../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.qcln", #load polarization as well, we need it later
                stokes_u="../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.ucln", #load polarization as well, we need it later
                uvf_file="../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.uvf")

#let's look at the data with modelfits displayed
#Lets'plot both datasets as an ImageCube to have a look
im_cube=ImageCube([dataU,dataX])
im_cube.plot(plot_model=True)
#The third option is to align the images based on modelfit components #This requires to identify matching components between images first #First let's load some new data again, this time including modelcomponents #This is now the regular U-band data dataU=ImageData("../dataset_example/3C111_U_2014_05_08/3C111_U_2014_05_08.fits", model="../dataset_example/3C111_U_2014_05_08/3C111_U_2014_05_08.mfit", #can be modelfits .fits or .mod file stokes_q="../dataset_example/3C111_U_2014_05_08/3C111_U_2014_05_08.qcln", #load polarization as well, we need it later stokes_u="../dataset_example/3C111_U_2014_05_08/3C111_U_2014_05_08.ucln", #load polarization as well, we need it later uvf_file="../dataset_example/3C111_U_2014_05_08/3C111_U_2014_05_08.uvf") #The second dataset is a regular X band image dataX=ImageData("../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.fits", model="../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.mfit", #can be modelfits .fits or .mod file stokes_q="../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.qcln", #load polarization as well, we need it later stokes_u="../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.ucln", #load polarization as well, we need it later uvf_file="../dataset_example/3C111_X_2014_05_08/3C111_X_2014_05_08.uvf") #let's look at the data with modelfits displayed #Lets'plot both datasets as an ImageCube to have a look im_cube=ImageCube([dataU,dataX]) im_cube.plot(plot_model=True)
No description has been provided for this image
Out[10]:
<vcat.plots.multi_fits_image.MultiFitsImage at 0x722994a37370>
In [11]:
Copied!
#At the next stage, we need to identify model components with each other
#Let's say we want to identify the two largest components with id 1
#We can do this as follows:

import numpy as np

#get the components
comp1=dataU.components
comps2=dataX.components


#find largest component in both images
majs1=[]
for comp in comp1:
    majs1.append(comp.maj)

majs2=[]
for comp in comps2:
    majs2.append(comp.maj)

argmax1=np.argmax(majs1)
argmax2=np.argmax(majs2)

#assign the largest component the component number 42
dataU.components[argmax1].component_number=42
dataX.components[argmax2].component_number=42

#Now we can use this component to align both images 
#Let's start the alignment
method="modelcomp"
comp_ids=42 #you can also use a list of comp_ids, if you have assigned multiple components, then the final shift will be the mean from all component shifts


#do the alignment, no regridding or beam convolution is needed, in principle
dataX_aligned=dataX.align(dataU,method=method,comp_ids=comp_ids,useDIFMAP=useDIFMAP)

#Let's plot the images again and zoom in close to the largest component to check the alignment
im_cube=ImageCube([dataU,dataX_aligned])
im_cube.plot(xlim=[10,5],ylim=[0,5],plot_model=True,plot_beam=False,title="")

#the component is now at the same position as the other component, we can also print their coordinates
print(dataU.components[argmax1].x,dataU.components[argmax1].y)
print(dataX_aligned.components[argmax2].x,dataX_aligned.components[argmax2].y)
#At the next stage, we need to identify model components with each other #Let's say we want to identify the two largest components with id 1 #We can do this as follows: import numpy as np #get the components comp1=dataU.components comps2=dataX.components #find largest component in both images majs1=[] for comp in comp1: majs1.append(comp.maj) majs2=[] for comp in comps2: majs2.append(comp.maj) argmax1=np.argmax(majs1) argmax2=np.argmax(majs2) #assign the largest component the component number 42 dataU.components[argmax1].component_number=42 dataX.components[argmax2].component_number=42 #Now we can use this component to align both images #Let's start the alignment method="modelcomp" comp_ids=42 #you can also use a list of comp_ids, if you have assigned multiple components, then the final shift will be the mean from all component shifts #do the alignment, no regridding or beam convolution is needed, in principle dataX_aligned=dataX.align(dataU,method=method,comp_ids=comp_ids,useDIFMAP=useDIFMAP) #Let's plot the images again and zoom in close to the largest component to check the alignment im_cube=ImageCube([dataU,dataX_aligned]) im_cube.plot(xlim=[10,5],ylim=[0,5],plot_model=True,plot_beam=False,title="") #the component is now at the same position as the other component, we can also print their coordinates print(dataU.components[argmax1].x,dataU.components[argmax1].y) print(dataX_aligned.components[argmax2].x,dataX_aligned.components[argmax2].y)
2025-10-08 12:04:52,004 - INFO - vcat - will apply shift (x,y): [-5.002273974241688 : -2.2774519038648577] mas
No description has been provided for this image
2.2011784039932536e-06 1.0505120826564962e-06
2.201172947025043e-06 1.0505244745218079e-06
In [12]:
Copied!
#Now that the alignment has been carried out succesfully, we can also derive spectral index maps and rotation measure maps
#We will do this on the ImageCube object, assuming the maps were aligned correctly

#Let's first convolve them with a common beam
im_cube = im_cube.restore(useDIFMAP=useDIFMAP)

#Define the Frequencies to use for spectral index (will automatically pick the images closest to that frequency
freq1=8 #GHz
freq2=15 #GHz

#get the spectral index map
spix_map=im_cube.get_spectral_index_map(freq1,freq2)

#The spix_map itself is also an ImageCube object and a copy of the higher frequency image with image.spix set to the spectral index map
spix_map.plot(plot_mode="spix",contour=True,xlim=[15,-5],ylim=[-5,10],do_colorbar=True,figsize=(5,4))
#Now that the alignment has been carried out succesfully, we can also derive spectral index maps and rotation measure maps #We will do this on the ImageCube object, assuming the maps were aligned correctly #Let's first convolve them with a common beam im_cube = im_cube.restore(useDIFMAP=useDIFMAP) #Define the Frequencies to use for spectral index (will automatically pick the images closest to that frequency freq1=8 #GHz freq2=15 #GHz #get the spectral index map spix_map=im_cube.get_spectral_index_map(freq1,freq2) #The spix_map itself is also an ImageCube object and a copy of the higher frequency image with image.spix set to the spectral index map spix_map.plot(plot_mode="spix",contour=True,xlim=[15,-5],ylim=[-5,10],do_colorbar=True,figsize=(5,4))
2025-10-08 12:05:34,859 - INFO - vcat - Determining common beam...
2025-10-08 12:05:35,675 - INFO - vcat - common beam calculated: [1.7770593660568261, 1.1265451854188584, -10.920121192749422]
2025-10-08 12:05:35,676 - INFO - vcat - Restoring images
Processing: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [01:18<00:00, 39.45s/it]
2025-10-08 12:06:54,570 - INFO - vcat - Image modifications completed.
2025-10-08 12:06:54,586 - INFO - vcat - Spectral index max(alpha)=6.7717180252075195 - min(alpha)=-12.206295013427734
Cutoff -3<alpha<5
No description has been provided for this image
Out[12]:
<vcat.plots.multi_fits_image.MultiFitsImage at 0x7229716c7160>

Polarization maps and Rotation Measure¶

In [13]:
Copied!
#In a similar fashion we can also derive rotation measure maps, since we loaded polarization information earlier

#Let's look at the polarization again
im_cube.plot(plot_mode="lin_pol",plot_evpa=True,xlim=[15,-5],ylim=[-5,10])

#and now we derive the rotation measure map
rm_map=im_cube.get_rm_map(freq1,freq2,sigma_lim_pol=3,sigma_lim=3)

#plot it:
rm_map.plot(plot_mode="rm",contour=True,xlim=[15,-5],ylim=[-5,10],do_colorbar=True,figsize=(5,4))
#In a similar fashion we can also derive rotation measure maps, since we loaded polarization information earlier #Let's look at the polarization again im_cube.plot(plot_mode="lin_pol",plot_evpa=True,xlim=[15,-5],ylim=[-5,10]) #and now we derive the rotation measure map rm_map=im_cube.get_rm_map(freq1,freq2,sigma_lim_pol=3,sigma_lim=3) #plot it: rm_map.plot(plot_mode="rm",contour=True,xlim=[15,-5],ylim=[-5,10],do_colorbar=True,figsize=(5,4))
No description has been provided for this image
No description has been provided for this image
Out[13]:
<vcat.plots.multi_fits_image.MultiFitsImage at 0x72295a362700>
In [ ]:
Copied!

Previous Next

Built with MkDocs using a theme provided by Read the Docs.
GitHub « Previous Next »