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
  • Model Component Analysis
  • Edit on GitHub

In [1]:
Copied!
from vcat import ImageData, ImageCube
from vcat.plots.kinematic_plot import KinematicPlot
import glob
from IPython.display import Video
from vcat import ImageData, ImageCube from vcat.plots.kinematic_plot import KinematicPlot import glob from IPython.display import Video
2025-10-17 17:41:48,964 - INFO - vcat - Logging initialized. Log file: Console only
2025-10-17 17:41:48,965 - INFO - vcat - Using config file VCAT_CONFIG=/home/flep98/VCAT/config.yaml
2025-10-17 17:41:48,965 - INFO - vcat - Using DIFMAP Path: /usr/local/difmap/uvf_difmap_2.5g/
2025-10-17 17:41:48,966 - INFO - vcat - Using uv-weighting: [0, -1]
2025-10-17 17:41:48,966 - INFO - vcat - Using font: Quicksand
2025-10-17 17:41:48,966 - INFO - vcat - Using noise method: Histogram Fit
2025-10-17 17:41:48,966 - INFO - vcat - Using modelfit error method: Schinzel12
2025-10-17 17:41:48,967 - INFO - vcat - Using resolution limit method: Kovalev05
Thank you for using VCAT. Have fun with VLBI!
If you are using this package please cite VCAT Team et al. 2025 ....
In [2]:
Copied!
#Let's load an image with modelfit first
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") #this can be either .fits or .mod file

#let's print some info and plot it with the modelcomps and automatically associated ids
print(dataU)
dataU.plot(plot_model=True,plot_comp_ids=True,xlim=[10,-5],ylim=[-5,10])
#Let's load an image with modelfit first 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") #this can be either .fits or .mod file #let's print some info and plot it with the modelcomps and automatically associated ids print(dataU) dataU.plot(plot_model=True,plot_comp_ids=True,xlim=[10,-5],ylim=[-5,10])
2025-10-17 17:41:49,643 - WARNING - vcat - No .uvfits file or difmap path provided. Calculating modelfit component SNR based on the clean map only.
Image of the source 3C111 at frequency 15.2 GHz on 2014-05-08 
    Total cleaned flux: 3474.345 mJy 
    Image Noise: 0.252 mJy using method 'Histogram Fit'
No polarization data loaded.
Model information: 
    Model Flux: 3472.798 mJy 
    Number of Components: 11
No description has been provided for this image
Out[2]:
<vcat.plots.fits_image.FitsImage at 0x7b29c91f8490>
In [3]:
Copied!
#Let's modify the component IDs and assign them to our liking.
#Let's first use a list of the old comp_ids
old_ids=[0,1,2,3,4,5,6,7,8,9,10,11]

#and now the new IDs that we want to assign them
new_ids=[11,10,9,8,7,6,5,4,3,2,1,0]

#and finally execute the change
dataU.change_component_ids(old_ids,new_ids)

#we also want to assign the core component to be comp 1
dataU.set_core_component(1)

#let's plot it again
dataU.plot(plot_model=True,plot_comp_ids=True,xlim=[10,-5],ylim=[-5,10])
#Let's modify the component IDs and assign them to our liking. #Let's first use a list of the old comp_ids old_ids=[0,1,2,3,4,5,6,7,8,9,10,11] #and now the new IDs that we want to assign them new_ids=[11,10,9,8,7,6,5,4,3,2,1,0] #and finally execute the change dataU.change_component_ids(old_ids,new_ids) #we also want to assign the core component to be comp 1 dataU.set_core_component(1) #let's plot it again dataU.plot(plot_model=True,plot_comp_ids=True,xlim=[10,-5],ylim=[-5,10])
No description has been provided for this image
Out[3]:
<vcat.plots.fits_image.FitsImage at 0x7b29bc2258b0>
In [4]:
Copied!
#Let's check if the core assignment worked   
print(dataU.get_core_component())
#Let's check if the core assignment worked print(dataU.get_core_component())
Component with ID 1 at frequency 15.2 GHz
x: -0.25 mas, y:-0.15 mas
Maj: 0.06 mas, Min: 0.06 mas, PA: -28.300800323486328 °
Flux: 494.0820038318634 mJy, Distance to Core: 0.00 mas

In [5]:
Copied!
#Similarly we can get info about any other component 
print(dataU.get_component(10))
#Similarly we can get info about any other component print(dataU.get_component(10))
Component with ID 10 at frequency 15.2 GHz
x: 6.32 mas, y:3.58 mas
Maj: 0.71 mas, Min: 0.71 mas, PA: 0.0 °
Flux: 55.47590181231499 mJy, Distance to Core: 7.55 mas

In [6]:
Copied!
#Let's load some more data
dataC=ImageData("../dataset_example/3C111_C_2014_05_08/3C111_C_2014_05_08.fits",
        model="../dataset_example/3C111_C_2014_05_08/3C111_C_2014_05_08.mfit")
dataQ=ImageData("../dataset_example/3C111_Q_2014_05_08/3C111_Q_2014_05_08.fits",
        model="../dataset_example/3C111_Q_2014_05_08/3C111_Q_2014_05_08.mfit")
dataW=ImageData("../dataset_example/3C111_W_2014_05_08/3C111_W_2014_05_08.fits",
        model="../dataset_example/3C111_W_2014_05_08/3C111_W_2014_05_08.mfit")
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")

#Now we have to manually associate the components to the right ID, this is a bit tedious and will soon be replaced with a GUI version
#For now, let's use the following associations:

old_ids=[1,2,3]
new_ids=[2,3,1]
core_id=0

dataQ.change_component_ids(old_ids,new_ids)
dataQ.set_core_component(core_id)

old_ids=[1,2,3]
new_ids=[2,3,1]
core_id=0

dataW.change_component_ids(old_ids,new_ids)
dataW.set_core_component(core_id)

old_ids=[1,2,3]
new_ids=[2,3,1]
core_id=4

dataX.change_component_ids(old_ids,new_ids)
dataX.set_core_component(core_id)

old_ids=[1,2,3]
new_ids=[2,3,1]
core_id=6

dataC.change_component_ids(old_ids,new_ids)
dataC.set_core_component(core_id)
#Let's load some more data dataC=ImageData("../dataset_example/3C111_C_2014_05_08/3C111_C_2014_05_08.fits", model="../dataset_example/3C111_C_2014_05_08/3C111_C_2014_05_08.mfit") dataQ=ImageData("../dataset_example/3C111_Q_2014_05_08/3C111_Q_2014_05_08.fits", model="../dataset_example/3C111_Q_2014_05_08/3C111_Q_2014_05_08.mfit") dataW=ImageData("../dataset_example/3C111_W_2014_05_08/3C111_W_2014_05_08.fits", model="../dataset_example/3C111_W_2014_05_08/3C111_W_2014_05_08.mfit") 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") #Now we have to manually associate the components to the right ID, this is a bit tedious and will soon be replaced with a GUI version #For now, let's use the following associations: old_ids=[1,2,3] new_ids=[2,3,1] core_id=0 dataQ.change_component_ids(old_ids,new_ids) dataQ.set_core_component(core_id) old_ids=[1,2,3] new_ids=[2,3,1] core_id=0 dataW.change_component_ids(old_ids,new_ids) dataW.set_core_component(core_id) old_ids=[1,2,3] new_ids=[2,3,1] core_id=4 dataX.change_component_ids(old_ids,new_ids) dataX.set_core_component(core_id) old_ids=[1,2,3] new_ids=[2,3,1] core_id=6 dataC.change_component_ids(old_ids,new_ids) dataC.set_core_component(core_id)
2025-10-17 17:41:58,569 - WARNING - vcat - No .uvfits file or difmap path provided. Calculating modelfit component SNR based on the clean map only.
2025-10-17 17:42:00,219 - WARNING - vcat - No .uvfits file or difmap path provided. Calculating modelfit component SNR based on the clean map only.
2025-10-17 17:42:01,533 - WARNING - vcat - No .uvfits file or difmap path provided. Calculating modelfit component SNR based on the clean map only.
2025-10-17 17:42:02,779 - WARNING - vcat - No .uvfits file or difmap path provided. Calculating modelfit component SNR based on the clean map only.
In [7]:
Copied!
#Now that all components were correctly identified, we will load the images as an ImageCube for easier handling
im_cube=ImageCube([dataC,dataX,dataU,dataQ,dataW])

#we will load a file which already has all the correct component associations
im_cube.import_component_association("../dataset_example/comp_association_3C111.csv")

#let's double check the associations
im_cube.plot(plot_model=True,plot_comp_ids=True)
#Now that all components were correctly identified, we will load the images as an ImageCube for easier handling im_cube=ImageCube([dataC,dataX,dataU,dataQ,dataW]) #we will load a file which already has all the correct component associations im_cube.import_component_association("../dataset_example/comp_association_3C111.csv") #let's double check the associations im_cube.plot(plot_model=True,plot_comp_ids=True)
2025-10-17 17:42:04,212 - INFO - vcat - Importing component associations from ../dataset_example/comp_association_3C111.csv.
No description has been provided for this image
Out[7]:
<vcat.plots.multi_fits_image.MultiFitsImage at 0x7b29b8f95310>
In [8]:
Copied!
#We can have a look at different jet profiles, based on the modelfits.
#Let's say we want to plot the jet collimation profile, this can be done using:
x,y,y_err=im_cube.get_model_profile("maj",core_position=[0,0]) #other options are 'flux','tb'
#We can have a look at different jet profiles, based on the modelfits. #Let's say we want to plot the jet collimation profile, this can be done using: x,y,y_err=im_cube.get_model_profile("maj",core_position=[0,0]) #other options are 'flux','tb'
In [9]:
Copied!
#So far we have looked at a single-epoch multi-frequency dataset
#Let's also have a look at a single-frequency multi-epoch dataset
from vcat import ImageCube
import glob
#We will load some MOJAVE epochs of 0506+056 where modelfits were performed
uvf_files=glob.glob("../dataset_example/0506+056_kinematic/*.uvf")
model_files=glob.glob("../dataset_example/0506+056_kinematic/*fits")

#additionally, we set fit_comp_polarization to true, 
#since we want VCAT to automatically determine the polarization properties of the modelcomps
#and their errors with fit_comp_pol_errors
#NOTE the polarization calculation takes some time! For quicker processing set those to False!
fit_comp_polarization=True
fit_comp_pol_errors=True

#Let's load them as an ImageCube
im_cube=ImageCube().import_files(uvf_files=uvf_files,model_fits_files=model_files,
                                 fit_comp_polarization=fit_comp_polarization,
                                fit_comp_pol_errors=True)
#So far we have looked at a single-epoch multi-frequency dataset #Let's also have a look at a single-frequency multi-epoch dataset from vcat import ImageCube import glob #We will load some MOJAVE epochs of 0506+056 where modelfits were performed uvf_files=glob.glob("../dataset_example/0506+056_kinematic/*.uvf") model_files=glob.glob("../dataset_example/0506+056_kinematic/*fits") #additionally, we set fit_comp_polarization to true, #since we want VCAT to automatically determine the polarization properties of the modelcomps #and their errors with fit_comp_pol_errors #NOTE the polarization calculation takes some time! For quicker processing set those to False! fit_comp_polarization=True fit_comp_pol_errors=True #Let's load them as an ImageCube im_cube=ImageCube().import_files(uvf_files=uvf_files,model_fits_files=model_files, fit_comp_polarization=fit_comp_polarization, fit_comp_pol_errors=True)
2025-10-17 17:42:17,028 - INFO - vcat - Importing images:
Processing: 100%|████████████████████████████████████████████████████████████████████████████████████████████| 11/11 [05:07<00:00, 27.98s/it]
2025-10-17 17:47:24,851 - INFO - vcat - Imported 11 images successfully.
In [10]:
Copied!
#We have already used the VCATNIP GUI to assign the component numbers, so we can load a component_info.csv file
import numpy as np
im_cube.import_component_association("../dataset_example/0506+056_kinematic/component_info.csv")
#We have already used the VCATNIP GUI to assign the component numbers, so we can load a component_info.csv file import numpy as np im_cube.import_component_association("../dataset_example/0506+056_kinematic/component_info.csv")
2025-10-17 17:47:24,861 - INFO - vcat - Importing component associations from ../dataset_example/0506+056_kinematic/component_info.csv.
In [11]:
Copied!
#We now have an ImageCube with correctly labeled components, that means we can call the kinematic fit functions

#Let's do a simple 1d linear fit of the core distance vs time
fit=im_cube.get_speed(order=1,show_plot=True,plot_errors=True)

#The returned fit parameter includes useful information about the apparent speed, critical Doppler_factor etc. of each component
print(fit)
#We now have an ImageCube with correctly labeled components, that means we can call the kinematic fit functions #Let's do a simple 1d linear fit of the core distance vs time fit=im_cube.get_speed(order=1,show_plot=True,plot_errors=True) #The returned fit parameter includes useful information about the apparent speed, critical Doppler_factor etc. of each component print(fit)
/home/flep98/anaconda3/lib/python3.9/site-packages/scipy/optimize/_minpack_py.py:803: RuntimeWarning: divide by zero encountered in divide
  transform = 1.0 / sigma
/home/flep98/anaconda3/lib/python3.9/site-packages/scipy/optimize/_minpack_py.py:488: RuntimeWarning: invalid value encountered in multiply
  return transform * (func(xdata, *params) - ydata)
/home/flep98/anaconda3/lib/python3.9/site-packages/scipy/optimize/_minpack_py.py:881: OptimizeWarning: Covariance of the parameters could not be estimated
  warnings.warn('Covariance of the parameters could not be estimated',
/home/flep98/anaconda3/lib/python3.9/site-packages/astropy/units/quantity.py:611: RuntimeWarning: invalid value encountered in multiply
  result = super().__array_ufunc__(function, method, *arrays, **kwargs)
/home/flep98/VCAT/vcat/kinematics.py:554: RuntimeWarning: invalid value encountered in divide
  chi2 = np.sum(((dist - y_model) / dist_err) ** 2)
No description has been provided for this image
[{'name': 'Component 0', 'speed': 0.0, 'speed_err': inf, 'y0': -0.0, 'y0_err': -0.0, 'beta_app': 0.0, 'beta_app_err': nan, 'd_crit': 1.0, 'd_crit_err': nan, 'dist_0_est': -0.0, 't_0': 2010.5260273972603, 't_0_err': inf, 'red_chi_sqr': nan, 't_mid': 2013.7029044090127, 'linear_fit': array([   0.       , 2010.5260274]), 'cov_matrix': array([[inf, inf],
       [inf, inf]])}, {'name': 'Component 1', 'speed': 1.321797671308369e-07, 'speed_err': 0.010148179131005082, 'y0': 0.38026096751506233, 'y0_err': -1.2924763312956372e-08, 'beta_app': 0.0, 'beta_app_err': 0.0, 'd_crit': 1.0, 'd_crit_err': 0.0, 'dist_0_est': 0.38026096751506233, 't_0': -2876847.007444525, 't_0_err': 220296742758.01096, 'red_chi_sqr': 0.6251664841425155, 't_mid': 2013.7029044090127, 'linear_fit': array([ 1.32179767e-07, -2.87684701e+06]), 'cov_matrix': array([[1.02985540e-04, 2.23561081e+09],
       [2.23561081e+09, 4.85306549e+22]])}, {'name': 'Component 2', 'speed': 0.006861381386113264, 'speed_err': 0.02570771999128605, 'y0': -12.239079816631516, 'y0_err': -28.616075355945885, 'beta_app': 0.0, 'beta_app_err': 0.0, 'd_crit': 1.0, 'd_crit_err': 0.0, 'dist_0_est': -12.239079816631516, 't_0': 1783.763228990909, 't_0_err': 861.2259411150854, 'red_chi_sqr': 0.9979808322853297, 't_mid': 2013.7029044090127, 'linear_fit': array([6.86138139e-03, 1.78376323e+03]), 'cov_matrix': array([[6.60886867e-04, 2.21390224e+01],
       [2.21390224e+01, 7.41710122e+05]])}, {'name': 'Component 3', 'speed': 0.11574003432859001, 'speed_err': 0.06469392163627156, 'y0': -229.99210686219223, 'y0_err': -31435.86594512278, 'beta_app': 0.0, 'beta_app_err': 0.0, 'd_crit': 1.0, 'd_crit_err': 0.0, 'dist_0_est': -229.99210686219223, 't_0': 1987.1439316255653, 't_0_err': 14.731224706983241, 'red_chi_sqr': 0.5777004996741018, 't_mid': 2013.7029044090127, 'linear_fit': array([1.15740034e-01, 1.98714393e+03]), 'cov_matrix': array([[4.18530350e-03, 9.49253095e-01],
       [9.49253095e-01, 2.17008981e+02]])}]
In [12]:
Copied!
#Alternatively, we can fit x- and y-coordinates separately, and we can choose a n-th order polynom to fit
order=2

#additionally, we can adjust the plot colors
colors=["green","purple","black","gray"]
fit=im_cube.get_speed2d(order=order,colors=colors,show_plot=True,plot_errors=True)

#Again, the returned fit dictionaries include important information about the performed fit, this time, for x- and y
print(fit)
#Alternatively, we can fit x- and y-coordinates separately, and we can choose a n-th order polynom to fit order=2 #additionally, we can adjust the plot colors colors=["green","purple","black","gray"] fit=im_cube.get_speed2d(order=order,colors=colors,show_plot=True,plot_errors=True) #Again, the returned fit dictionaries include important information about the performed fit, this time, for x- and y print(fit)
/home/flep98/VCAT/vcat/kinematics.py:480: RuntimeWarning: divide by zero encountered in divide
  linear_fit, cov_matrix = np.polyfit(time, dist, order, cov='scaled', w=1./dist_err)
/home/flep98/anaconda3/lib/python3.9/site-packages/numpy/lib/polynomial.py:663: RuntimeWarning: invalid value encountered in multiply
  rhs *= w
/home/flep98/anaconda3/lib/python3.9/site-packages/numpy/lib/polynomial.py:667: RuntimeWarning: invalid value encountered in divide
  lhs /= scale
2025-10-17 17:47:25,130 - WARNING - vcat - Could not perform weighted fit for Component Component 0, will do unweighted.
/home/flep98/VCAT/vcat/kinematics.py:499: RuntimeWarning: invalid value encountered in double_scalars
  t_0 = - linear_fit[-1] / speed + t_mid
/home/flep98/VCAT/vcat/kinematics.py:501: RuntimeWarning: invalid value encountered in double_scalars
  t_0_err = np.sqrt((cov_matrix[-1, -1] / speed ** 2) + (linear_fit[-1] ** 2 * cov_matrix[0, 0] / speed ** 4))
/home/flep98/VCAT/vcat/kinematics.py:468: RuntimeWarning: invalid value encountered in divide
  return 1. / (N - n) * np.sum(((y - fit) / yerr) ** 2.)
2025-10-17 17:47:25,132 - WARNING - vcat - Could not perform weighted fit for Component Component 0, will do unweighted.
No description has been provided for this image
[[{'name': 'Component 0', 'speed': 0.0, 'speed_err': 0.0, 'y0': 0.0, 'y0_err': 0.0, 'beta_app': 0.0, 'beta_app_err': 0.0, 'd_crit': 1.0, 'd_crit_err': 0.0, 'dist_0_est': 0.0, 't_0': nan, 't_0_err': nan, 'red_chi_sqr': nan, 't_mid': 2013.7029044090127, 'linear_fit': array([0., 0., 0.]), 'cov_matrix': array([[ 0.,  0., -0.],
       [ 0.,  0., -0.],
       [-0., -0.,  0.]])}, {'name': 'Component 0', 'speed': 0.0, 'speed_err': 0.0, 'y0': 0.0, 'y0_err': 0.0, 'beta_app': 0.0, 'beta_app_err': 0.0, 'd_crit': 1.0, 'd_crit_err': 0.0, 'dist_0_est': 0.0, 't_0': nan, 't_0_err': nan, 'red_chi_sqr': nan, 't_mid': 2013.7029044090127, 'linear_fit': array([0., 0., 0.]), 'cov_matrix': array([[ 0.,  0., -0.],
       [ 0.,  0., -0.],
       [-0., -0.,  0.]])}], [{'name': 'Component 1', 'speed': 0.0037212411379664956, 'speed_err': 0.0022799306775130586, 'y0': -7.576724018814405, 'y0_err': 0.015188659061617083, 'beta_app': 0.0, 'beta_app_err': 0.0, 'd_crit': 1.0, 'd_crit_err': 0.0, 'dist_0_est': -7.576724018814405, 't_0': 2036.0744541684744, 't_0_err': 14.301418503119157, 'red_chi_sqr': 0.8748843972575779, 't_mid': 2013.7029044090127, 'linear_fit': array([ 0.00372124,  0.02084391, -0.08324993]), 'cov_matrix': array([[ 5.19808389e-06, -8.05726863e-07, -2.83622647e-05],
       [-8.05726863e-07,  1.36944129e-05, -7.88261786e-06],
       [-2.83622647e-05, -7.88261786e-06,  2.30695364e-04]])}, {'name': 'Component 1', 'speed': -0.0033142537236125896, 'speed_err': 0.004246882192822962, 'y0': 6.3082560223528485, 'y0_err': 0.028292283768909136, 'beta_app': -0.0, 'beta_app_err': 0.0, 'd_crit': 1.0, 'd_crit_err': -0.0, 'dist_0_est': 6.3082560223528485, 't_0': 1903.3714822161378, 't_0_err': 141.63608735268608, 'red_chi_sqr': 0.702210796805707, 't_mid': 2013.7029044090127, 'linear_fit': array([-0.00331425,  0.01047125, -0.36566633]), 'cov_matrix': array([[ 1.80360084e-05, -2.79566408e-06, -9.84097320e-05],
       [-2.79566408e-06,  4.75160752e-05, -2.73506478e-05],
       [-9.84097320e-05, -2.73506478e-05,  8.00453321e-04]])}], [{'name': 'Component 2', 'speed': -0.005362155916196214, 'speed_err': 0.005598421855083155, 'y0': 10.439547726922981, 'y0_err': 0.03543727342078503, 'beta_app': -0.0, 'beta_app_err': 0.0, 'd_crit': 1.0, 'd_crit_err': -0.0, 'dist_0_est': 10.439547726922981, 't_0': 1946.893728955302, 't_0_err': 70.06528050063571, 'red_chi_sqr': 0.21391652912306416, 't_mid': 2013.7029044090127, 'linear_fit': array([-0.00536216,  0.01331445, -0.35824122]), 'cov_matrix': array([[ 3.13423273e-05,  6.53351305e-06, -1.69143576e-04],
       [ 6.53351305e-06,  6.46997394e-05, -2.95995871e-05],
       [-1.69143576e-04, -2.95995871e-05,  1.25580035e-03]])}, {'name': 'Component 2', 'speed': 0.016831481597218985, 'speed_err': 0.02049796389362729, 'y0': -35.50994744401432, 'y0_err': 0.12974941329373266, 'beta_app': 0.0, 'beta_app_err': 0.0, 'd_crit': 1.0, 'd_crit_err': 0.0, 'dist_0_est': -35.50994744401432, 't_0': 2109.7339077910715, 't_0_err': 117.20368167778805, 'red_chi_sqr': 1.858521020371372, 't_mid': 2013.7029044090127, 'linear_fit': array([ 0.01683148, -0.00875483, -1.61634407]), 'cov_matrix': array([[ 4.20166524e-04,  8.75864591e-05, -2.26749175e-03],
       [ 8.75864591e-05,  8.67346715e-04, -3.96803833e-04],
       [-2.26749175e-03, -3.96803833e-04,  1.68349103e-02]])}], [{'name': 'Component 3', 'speed': 0.005922818305122917, 'speed_err': 0.014778022320587562, 'y0': -11.727214235018577, 'y0_err': 0.09588228035057708, 'beta_app': 0.0, 'beta_app_err': 0.0, 'd_crit': 1.0, 'd_crit_err': 0.0, 'dist_0_est': -11.727214235018577, 't_0': 1980.005738969769, 't_0_err': 85.622111777827, 'red_chi_sqr': 0.13512681964160972, 't_mid': 2013.7029044090127, 'linear_fit': array([0.00592282, 0.02663508, 0.19958219]), 'cov_matrix': array([[ 0.00021839,  0.00011442, -0.00118246],
       [ 0.00011442,  0.0005605 , -0.00046514],
       [-0.00118246, -0.00046514,  0.00919341]])}, {'name': 'Component 3', 'speed': 0.005575512648345999, 'speed_err': 0.033616445316767676, 'y0': -14.319809557295454, 'y0_err': 0.21810911936178545, 'beta_app': 0.0, 'beta_app_err': 0.0, 'd_crit': 1.0, 'd_crit_err': 0.0, 'dist_0_est': -14.319809557295454, 't_0': 2568.3395340415, 't_0_err': 3344.3001189033616, 'red_chi_sqr': 1.076374538704596, 't_mid': 2013.7029044090127, 'linear_fit': array([ 0.00557551, -0.11159826, -3.09238354]), 'cov_matrix': array([[ 0.00113007,  0.00059207, -0.00611866],
       [ 0.00059207,  0.00290033, -0.00240689],
       [-0.00611866, -0.00240689,  0.04757159]])}]]
In [13]:
Copied!
#In addition to the component kinematics, different parameters can be plotted as well
value="tb" #choose value to plot, also "flux", or "flux+evpa" possible

#the plot method also returns the values with error, in case you want to use them for other tasks.
times, values, err = im_cube.plot_component_evolution(value)
#In addition to the component kinematics, different parameters can be plotted as well value="tb" #choose value to plot, also "flux", or "flux+evpa" possible #the plot method also returns the values with error, in case you want to use them for other tasks. times, values, err = im_cube.plot_component_evolution(value)
No description has been provided for this image
In [14]:
Copied!
#Since VCAT automatically calculates component polarization, when a .uvf file is loaded
#it is also possible to plot polarization information for the components
value="lin_pol" 

#it is possible to select only a subset of components
id=[0,3]

#This plot now shows the linearly polarized flux density with EVPAs overplotted as tilted lines for every component
times, values, err = im_cube.plot_component_evolution(value,id=id,plot_errors=True)
#Since VCAT automatically calculates component polarization, when a .uvf file is loaded #it is also possible to plot polarization information for the components value="lin_pol" #it is possible to select only a subset of components id=[0,3] #This plot now shows the linearly polarized flux density with EVPAs overplotted as tilted lines for every component times, values, err = im_cube.plot_component_evolution(value,id=id,plot_errors=True)
No description has been provided for this image
In [15]:
Copied!
#It is also possible to fit a collimation profile based on the model components

#We can introduce an snr_cut to only consider significant components
snr_cut=1

#additionally it is useful to filter out unresolved components
filter_unresolved=True

#the fit_type can be selected between "Powerlaw" and "brokenPowerlaw", and it is possible to fit r0 (fit_r0)
fit_r0=False
fit_type="brokenPowerlaw"

im_cube.fit_collimation_profile(snr_cut=snr_cut,
                                filter_unresolved=filter_unresolved,
                                fit_r0=fit_r0,
                               fit_type=fit_type)
#It is also possible to fit a collimation profile based on the model components #We can introduce an snr_cut to only consider significant components snr_cut=1 #additionally it is useful to filter out unresolved components filter_unresolved=True #the fit_type can be selected between "Powerlaw" and "brokenPowerlaw", and it is possible to fit r0 (fit_r0) fit_r0=False fit_type="brokenPowerlaw" im_cube.fit_collimation_profile(snr_cut=snr_cut, filter_unresolved=filter_unresolved, fit_r0=fit_r0, fit_type=fit_type)
only use y-error
fit_type=2
Beta: [0.29309679 0.03895191 0.89207751 0.42156644]
Beta Std Error: [0.01470947 0.085594   0.04805838 0.04105441]
Beta Covariance: [[0.00029898 0.00154242 0.0001296  0.00057916]
 [0.00154242 0.01012366 0.00038394 0.00279647]
 [0.0001296  0.00038394 0.00319146 0.00192952]
 [0.00057916 0.00279647 0.00192952 0.00232901]]
Residual Variance: 0.7236839580803294
Inverse Condition #: 0.0009250520871253146
Reason(s) for Halting:
  Sum of squares convergence
/home/flep98/VCAT/vcat/fit_functions.py:61: RuntimeWarning: invalid value encountered in power
  return w0*2**((au-ad)/s)*(x/xb)**au*(1+(x/xb)**s)**((ad-au)/s)
Out[15]:
<vcat.plots.jet_profile_plot.JetProfilePlot at 0x7b29b3e81940>
No description has been provided for this image
In [16]:
Copied!
#Moreover other component profiles can be plotted, e.g., the flux profile
value="flux" #for flux profile

#the method also returns the values with errors
dists,values,errs=im_cube.get_model_profile(value,plot=True)
#Moreover other component profiles can be plotted, e.g., the flux profile value="flux" #for flux profile #the method also returns the values with errors dists,values,errs=im_cube.get_model_profile(value,plot=True)
No description has been provided for this image
In [17]:
Copied!
#If you are feeling very fancy, you can also create a movie of the moving components (useful for talks!)
plot_components=True
n_frames=200 #number of frames
interval=50 #milliseconds per frame
save="kinematic_movie.mp4" #output file name

#usual plot parameters can be used here as well
xlim=[5,-5]
ylim=[-7,3]

#Let's create the movie (NOTE: This may take some time!)
im_cube.movie(plot_components=plot_components,n_frames=n_frames,interval=interval,xlim=xlim,ylim=ylim,save=save)

#Let's display the movie
Video(save, embed=True)
#If you are feeling very fancy, you can also create a movie of the moving components (useful for talks!) plot_components=True n_frames=200 #number of frames interval=50 #milliseconds per frame save="kinematic_movie.mp4" #output file name #usual plot parameters can be used here as well xlim=[5,-5] ylim=[-7,3] #Let's create the movie (NOTE: This may take some time!) im_cube.movie(plot_components=plot_components,n_frames=n_frames,interval=interval,xlim=xlim,ylim=ylim,save=save) #Let's display the movie Video(save, embed=True)
2025-10-17 17:47:39,691 - INFO - vcat - Creating movie
Processing:   0%|                                                                                                    | 0/200 [00:00<?, ?it/s]2025-10-17 17:47:39,692 - INFO - matplotlib.animation - Animation.save using <class 'matplotlib.animation.FFMpegWriter'>
2025-10-17 17:47:39,693 - INFO - matplotlib.animation - MovieWriter._run: running command: ffmpeg -f rawvideo -vcodec rawvideo -s 1920x1440 -pix_fmt rgba -r 20 -loglevel error -i pipe: -vcodec h264 -pix_fmt yuv420p -y kinematic_movie.mp4
/home/flep98/VCAT/vcat/kinematics.py:111: RuntimeWarning: divide by zero encountered in double_scalars
  self.tb = 1.22e12/(self.freq*1e-9)**2 * self.flux * (1 + self.redshift) / (maj_for_tb*self.scale) / (min_for_tb*self.scale)   #Kovalev et al. 2005
/home/flep98/VCAT/vcat/kinematics.py:165: RuntimeWarning: divide by zero encountered in double_scalars
  SNR_p = S_p/sigma_p
Processing: 201it [08:16,  2.49s/it]                                                                                                         2025-10-17 17:55:58,719 - INFO - vcat - Movie for 15GHz exported as 'kinematic_movie.mp4'
Processing: 201it [08:19,  2.48s/it]
Out[17]:
Your browser does not support the video tag.
No description has been provided for this image
In [18]:
Copied!
#Optionally, we can also display the components with a colormap, according to their flux density
fill_components=True
component_cmap="inferno"
save="kinematic_movie2.mp4"

#Let's create another movie
im_cube.movie(plot_components=True,fill_components=fill_components,component_cmap=component_cmap,
              n_frames=n_frames,interval=interval,xlim=xlim,ylim=ylim,save=save)

#And display the movie
Video(save, embed=True)
#Optionally, we can also display the components with a colormap, according to their flux density fill_components=True component_cmap="inferno" save="kinematic_movie2.mp4" #Let's create another movie im_cube.movie(plot_components=True,fill_components=fill_components,component_cmap=component_cmap, n_frames=n_frames,interval=interval,xlim=xlim,ylim=ylim,save=save) #And display the movie Video(save, embed=True)
2025-10-17 17:56:09,228 - INFO - vcat - Creating movie
Processing:   0%|                                                                                                    | 0/200 [00:00<?, ?it/s]2025-10-17 17:56:09,230 - INFO - matplotlib.animation - Animation.save using <class 'matplotlib.animation.FFMpegWriter'>
2025-10-17 17:56:09,230 - INFO - matplotlib.animation - MovieWriter._run: running command: ffmpeg -f rawvideo -vcodec rawvideo -s 1920x1440 -pix_fmt rgba -r 20 -loglevel error -i pipe: -vcodec h264 -pix_fmt yuv420p -y kinematic_movie2.mp4
/home/flep98/VCAT/vcat/kinematics.py:111: RuntimeWarning: divide by zero encountered in double_scalars
  self.tb = 1.22e12/(self.freq*1e-9)**2 * self.flux * (1 + self.redshift) / (maj_for_tb*self.scale) / (min_for_tb*self.scale)   #Kovalev et al. 2005
/home/flep98/VCAT/vcat/kinematics.py:165: RuntimeWarning: divide by zero encountered in double_scalars
  SNR_p = S_p/sigma_p
Processing: 201it [08:33,  2.55s/it]                                                                                                         2025-10-17 18:04:45,692 - INFO - vcat - Movie for 15GHz exported as 'kinematic_movie2.mp4'
Processing: 201it [08:36,  2.57s/it]
Out[18]:
Your browser does not support the video tag.
No description has been provided for this image
In [ ]:
Copied!

In [ ]:
Copied!

Previous Next

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