Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Cluster Lenses (Demo n° 1)

This demo will demonstrate the basics of cluster lenses as of CosmoSim v3.1. We follow the pattern from CosmoSim Demo I and Sample Datasets, and we will not take up space to explain constructs known therefrom.

Preparation

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
import json
from CosmoSim.datagen import SimImage
import CosmoSim.Image as csimg
import CosmoSim.dataset as csd
from CosmoSim import Parameters

First test of Cluster Lenses

We choose the following parameters for the first simulation.

cfg = { "simulator" : { "model" : "Raytrace", "cropsize" : 256 }
      , 'lens': { "cluster" : "SIE/5/5/8/0.3/45;SIE/-5/-5/8/0.3/45" }
      , 'source': {
            'mode': 'Spherical',
            'sigma': 5,
            'theta': 45,
            'position': 'cartesian'}
      , 'position': { 'x': 11.01, 'y': 0.31 }
      }
param = Parameters( cfg )

The new element is the lens specification, which is not as user friendly as it was. The cluster attribute gives a list of lenses separated by semicolon. Each constituent lens consists of the lens model ("SIE") and a list of lens parameters separated by slash (/). For SIE, these parameters are xx/yy/θE\theta_E/ff/ϕL\phi_L, i.e. position (x,y)(x,y), Einstein radius, ellipticity, and orientation.

Given the parameters, the simulation is as before.

imsim = SimImage( param, verbose=0 )
im = imsim.getImage()
csimg.imshow( im, title="First example of a cluster lens" )
<Figure size 640x480 with 1 Axes>

Random dataset

We can also generate random datasets.

cfg = csd.readtoml( "cluster.toml" )
display( json.dumps( cfg ) )
'{"simulator": {"model": "Raytrace", "size": 18000, "nterms": 4, "imagesize": 512, "cropsize": 256, "centred": true}, "lens": {"mode": "SIE", "einstein-min": 20, "einstein-max": 75, "orientation-min": 0, "orientation-max": 180, "ellipseratio-min": 0.1, "ellipseratio-max": 0.9}, "cluster": {"count": 2, "maxrelativelocation": 1.2}, "source": {"mode": "SersicSphere", "n_sersic-min": 1, "n_sersic-max": 5, "luminosity-min": 10, "luminosity-max": 20, "luminosity-lambda": 2.0, "sigma-min": 1, "sigma-max": 4, "position": "relative"}, "position": {"phi-min": 0, "phi-max": 360, "r-relativemax": 0.4}}'

Each constituent lens is placed in a random direction from the origin, at a random distance upper bounded as cθEc\theta_E where θE\theta_E is the Einstein radius and cc is the constant given as cluster.maxrelativelocation.

We can draw a random object as before.

ob = csd.getline( cfg, fn="test.png" )
display( ob )
index 0 filename test.png model Raytrace cluster SIE/-6.605119422431851/-21.363376547311095/47.... source SersicSphere R 78.333585 phi 98.566468 sigma 3.772596 sigma2 16.194565 theta 19.394465 n_sersic 2.803967 luminosity 17.139406 x -11.668308 y 77.459675 dtype: object
param = Parameters( )
param.setRow( ob )
imsim = SimImage( param, verbose=2 )
im = imsim.getImage()
csimg.imshow( im )
[GenericSim] init (verbose=2) ...
[SimImage] init (verbose=2) ...
[getSource] src=SersicSphere, ltprf0=None, verbose=2
[getSource] Lightprofile: SersicSphere LightProfileSpec.Sersic
[getSource] mode=SourceSpec.Sphere, ltprf=LightProfileSpec.Sersic
[getSource] Spherical Source - n_sersic=2.8039673447516504, luminosity=17.13940622883135
[SphericalSource] constructor done
getSource() returns
[CosmoSim/py] setCluster(SIE/-6.605119422431851/-21.363376547311095/47.81520262902683/0.6441970301075443/79.37281805353093;SIE/-18.340655772254845/8.614008728989585/21.361129792720348/0.39068158331413194/100.69668496016078)
SIE : [-6.605119422431851, -21.363376547311095, 47.81520262902683, 0.6441970301075443, 79.37281805353093]
[ClusterLens] component lens instantiated
[ClusterLens] [-6.605119422431851, -21.363376547311095, 47.81520262902683, 0.6441970301075443, 79.37281805353093]
[ClusterLens] addLens (-6.605119422431851, -21.363376547311095) <CosmoSim.CosmoSimPy.SIE object at 0x7f96d5a042b0>
[ClusterLens] addLens done
[ClusterLens] Done one component lens
SIE : [-18.340655772254845, 8.614008728989585, 21.361129792720348, 0.39068158331413194, 100.69668496016078]
[ClusterLens] component lens instantiated
[ClusterLens] [-18.340655772254845, 8.614008728989585, 21.361129792720348, 0.39068158331413194, 100.69668496016078]
[ClusterLens] addLens (-18.340655772254845, 8.614008728989585) <CosmoSim.CosmoSimPy.SIE object at 0x7f96d6bb67f0>
[ClusterLens] addLens done
[ClusterLens] Done one component lens
[CosmoSim/py] setCluster calls setLens
[initSim] XY -11.668308253189284 77.45967458792074
ClusterLens::addLens]] 5
ClusterLens::addLens]] -5
[ClusterLens.initAlphasBetas] nosuchfile
[Source] Constructor
[SphericalSource] SERSIC
setFile /home/runner/.local/lib/python3.14/site-packages/CosmoSim/sie05.txt
ClusterLens::addLens]] -21.3634
setFile /home/runner/.local/lib/python3.14/site-packages/CosmoSim/sie05.txt
ClusterLens::addLens]] 8.61401
[ClusterLens.initAlphasBetas] nosuchfile
[PsiFunctionLens.initAlphasBetas] Amplitudes file /home/runner/.local/lib/python3.14/site-packages/CosmoSim/sie05.txt
[initAlphasBetas] opened file /home/runner/.local/lib/python3.14/site-packages/CosmoSim/sie05.txt
[PsiFunctionLens.initAlphasBetas] Amplitudes file /home/runner/.local/lib/python3.14/site-packages/CosmoSim/sie05.txt
[initAlphasBetas] opened file /home/runner/.local/lib/python3.14/site-packages/CosmoSim/sie05.txt
[SimulatorMode::setLens] ClusterLens [SIE;SIE;]
[SimulatorModel::setSource] setting source
[SimulatorModel::setNterms] 10 -> 5
[SimulatorModel::update] Lens: ClusterLens [SIE;SIE;]
[Lens::getXi] [-11.6683, 77.4597]
[Lens] Fix pt it'n 0; xi0=[-11.6683, 77.4597]; Delta eta = -0.24276, 73.1741
[Lens] Fix pt it'n 1; xi0=[-11.9111, 150.634]; Delta eta = -0.154467, 73.2567
[Lens] Fix pt it'n 2; xi0=[-11.8228, 150.716]; Delta eta = -0.125855, 73.257
[Lens] Fix pt it'n 3; xi0=[-11.7942, 150.717]; Delta eta = -0.116652, 73.257
[Lens] Good approximation: xi0=[-11.7942, 150.717]; xi1=[-11.785, 150.717]
[Lens::getXi] [-11.6683, 77.4597] -> [-11.785, 150.717]
[setNu] etaOffset set to zero.
[SimulatorModel::update] Done updateApparentAbs()
[SimulatorModel::update] thread section
[Source::getImage()]
[SimulatorModel::updateInner()] eta=[-11.6683, 77.4597]
[SimulatorModel::updateInner()] xi=[-11.785, 150.717]; eta=[-11.6683, 77.4597]; etaOffset=[0, 0]
[SimulatorModel::updateInner()] nu=[-11.785, 150.717]
[calculateAlphaBeta] [[-11.785, 150.717]] ... 
[ClusterLens->calculateAlphaBeta()] 5; [-11.785, 150.717]
[PsiFunctionLens.calculateAlphaBeta()] 5; 47.8152 - [-11.785, 150.717]
ClusterLens (0, 0) 0/0
ClusterLens (0, 1) 0/0
ClusterLens (1, 0) -0.129525/0
ClusterLens (1, 1) 0/0
ClusterLens (1, 2) -0.127951/-0.0201328
ClusterLens (2, 0) 0/0
ClusterLens (2, 1) 9.61047e-05/0.00129661
ClusterLens (2, 2) 0/0
ClusterLens (2, 3) -0.000234281/0.00126534
ClusterLens (3, 0) -6.78788e-06/0
ClusterLens (3, 1) 0/0
ClusterLens (3, 2) 1.39934e-05/-1.3139e-06
ClusterLens (3, 3) 0/0
ClusterLens (3, 4) 1.99542e-05/4.61424e-06
ClusterLens (4, 0) 0/0
ClusterLens (4, 1) -2.5366e-09/2.24988e-07
ClusterLens (4, 2) 0/0
ClusterLens (4, 3) -2.4172e-08/-2.37668e-07
ClusterLens (4, 4) 0/0
ClusterLens (4, 5) 1.24769e-07/-4.35342e-07
ClusterLens (5, 0) -2.38708e-09/0
ClusterLens (5, 1) 0/0
ClusterLens (5, 2) 5.35736e-09/2.39911e-10
ClusterLens (5, 3) 0/0
ClusterLens (5, 4) -5.48105e-09/6.04774e-10
ClusterLens (5, 5) 0/0
ClusterLens (5, 6) -1.21444e-08/-4.23159e-09
[PsiFunctionLens.calculateAlphaBeta()] 5; 21.3611 - [-11.785, 150.717]
ClusterLens (0, 0) 0/0
ClusterLens (0, 1) 0/0
ClusterLens (1, 0) -0.173906/0
ClusterLens (1, 1) 0/0
ClusterLens (1, 2) -0.171793/-0.0270312
ClusterLens (2, 0) 0/0
ClusterLens (2, 1) 2.12692e-05/0.00173246
ClusterLens (2, 2) 0/0
ClusterLens (2, 3) -0.000349604/0.00169054
ClusterLens (3, 0) -9.49873e-06/0
ClusterLens (3, 1) 0/0
ClusterLens (3, 2) 1.79847e-05/3.96428e-08
ClusterLens (3, 3) 0/0
ClusterLens (3, 4) 2.63765e-05/7.06315e-06
ClusterLens (4, 0) 0/0
ClusterLens (4, 1) -1.63935e-08/3.13837e-07
ClusterLens (4, 2) 0/0
ClusterLens (4, 3) 3.26962e-09/-2.90946e-07
ClusterLens (4, 4) 0/0
ClusterLens (4, 5) 1.90231e-07/-5.68284e-07
ClusterLens (5, 0) -3.49144e-09/0
ClusterLens (5, 1) 0/0
ClusterLens (5, 2) 7.19361e-09/8.05601e-10
ClusterLens (5, 3) 0/0
ClusterLens (5, 4) -6.40921e-09/-5.80483e-11
ClusterLens (5, 5) 0/0
ClusterLens (5, 6) -1.56519e-08/-6.36577e-09
[RaytraceModel] distort() ClusterLens [SIE;SIE;] (Spherical Source)
[RaytraceModel] distort() ClusterLens [SIE;SIE;] (Spherical Source)
[RaytraceModel] distort() ClusterLens [SIE;SIE;] (Spherical Source)
[RaytraceModel] distort() ClusterLens [SIE;SIE;] (Spherical Source)
Time to update(): 65 milliseconds
[Simulator] Centre Point (-11.02,149.89) (Centre of Luminence in Planar Co-ordinates)
[getImage] centring from parameters: None
<Figure size 640x480 with 1 Axes>

A sample

def mkimg(ob):
      p0 = Parameters( )
      p0.setRow( ob )
      sim = SimImage( p0, verbose=0 )
      return sim.getImage()
obs = [ csd.getline( cfg ) for _ in range(8) ]
ims = [ mkimg(ob) for ob in obs ]
ts = [ f"Image {i}" for i in range(8) ]
csimg.showImages( ims, size=(2,4), titles=ts )
[SimulatorModel::getDistorted()]
[Source] Destructor - destructed
[setDebug] 0
<Figure size 2000x1000 with 8 Axes>

If we take a particular interest in one particular image, say no 1, we can easily inspect its parameters.

print( obs[1] )
index                                                         0
filename                                       image-000000.png
model                                                  Raytrace
cluster       SIE/12.455182623584644/-5.64548249790221/56.15...
source                                             SersicSphere
R                                                     61.541993
phi                                                  326.788425
sigma                                                  1.413445
sigma2                                                18.022888
theta                                                   78.3291
n_sersic                                               3.473641
luminosity                                            11.264397
x                                                     51.489335
y                                                    -33.708535
dtype: object

The cluser specification does not show in the row view, but we can single that one out to see properly.

print( obs[1]["cluster"] )
SIE/12.455182623584644/-5.64548249790221/56.15451175475593/0.23186423939783368/85.72910801708368;SIE/4.3546181826464085/-1.3535007479736356/41.88317559875979/0.6362615269818876/30.403443230426795

Closure