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.

Pointmass Demo

The simplest lens model in CosmoSim is the pointmass, where all the mass is compressed in a singular point. This model is implemented many times. Currently, there is a PointMass lens which can be used with the standard models, RouletteModel and RaytraceModel. The original implementations PointMassRoulette and PointMassExact should be equivalent, but used a closed form specific to the point mass lens, and thus cannot be modularised.

Preparation

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
import toml

import CosmoSim as cs
from CosmoSim import CosmoSim, Parameters
from CosmoSim.datagen import SimImage
import CosmoSim.Image as csimg

print( "CosmoSim version:", cs.__version__ )
CosmoSim version: 3.1.2

The exact models

We can define the configuration as a dict using the nested (TOML) structure.

cfg = { 'simulator' : { "model" : "Raytrace", "cropsize" : 256 }
      , 'lens': { 
            'mode' : "PM",
            'einsteinR': 46,
            'ellipseratio': 0.34,
            'orientation': 107,
            'chi': 50}
      , 'source': {
            'mode': 'Spherical',
            'sigma': 7,
            'position': 'cartesian'}
      , 'position': {'x': 35, 'y': 15}
      }
param = Parameters( cfg )
imsim01 = SimImage( param, verbose=0 )
im01 = imsim01.getImage()

To run the same simulation with the legacy, exact model, we simply change the simulator setting and rerun.

param["simulator"]["model"] = "Point Mass (exact)" 
imsim02 = SimImage( param, verbose=0 )
im02 = imsim02.getImage()
csimg.imageCompare( im01, im02, "Modular Raytrace", 'Exact Point Mass')
<Figure size 1500x500 with 3 Axes>

There is a visual discrepancy, but it is hard to tell if this is significant. Quite likely, it is due to numeric errors.

The original roulette

The roulette formalism is also implemented in a closed form.

param["simulator"]["model"] = "Point Mass (roulettes)"
param["simulator"]["nterms"] = 8
imsim03 = SimImage( param, verbose=0 )
im03 = imsim03.getImage()
csimg.imageCompare( im02, im03, "Exact Point Mass", 'Legacy Roulette')
<Figure size 1500x500 with 3 Axes>

This looks perfect inside the convergence ring, as it should.

Modular roulette

param["simulator"]["model"] = "Roulette"
imsim04 = SimImage( param, verbose=0 )
im04 = imsim04.getImage()
csimg.imageCompare( im01, im04, "Modular Raytrace", 'Modular Roulette')
<Figure size 1500x500 with 3 Axes>

Again, the roulette simulation is perfect within the convergence ring.

If we compare the closed form and modular implementations, we find a discrepancy similar to what we had for the exact model and raytrace.

csimg.imageCompare( im03, im04, "Legacy Roulette", 'Modular Roulette')
<Figure size 1500x500 with 3 Axes>

Sampling

The modular implementation allows for sampling and solution by numeric differentiation. Let us first test raytrace simulation and compare sampled and analytic solutions.

param["simulator"]["model"] = "Raytrace"
raytrace = SimImage( param, verbose=0 ).getImage()
param["simulator"]["sampled"] = True
raytraceS = SimImage( param, verbose=0 ).getImage()
csimg.imageCompare( raytrace, raytraceS, "Modular Raytrace", 'Sampled Raytrace')
<Figure size 1500x500 with 3 Axes>

This looks perfect.

Then we can do the same with roulette.

param["simulator"]["model"] = "Roulette"
rouletteS = SimImage( param, verbose=0 ).getImage()
csimg.imageCompare( im04, rouletteS, "Modular Roulette", 'Sampled Roulette')
<Figure size 1500x500 with 3 Axes>

This gives a minor discrepancy in the spurious images, which may well be due to numeric approximation.

It is also useful to compare to the closed form implementations too.

csimg.imageCompare( im03, rouletteS, "Legacy Roulette", 'Modular Sampled Roulette')
csimg.imageCompare( im02, raytraceS, "Exact Point Mass", 'Modular Sampled Raytrace')
<Figure size 1500x500 with 3 Axes>
<Figure size 1500x500 with 3 Axes>

Here we have discrepancy similar to what we first saw between the closed form and modular implementations.

Rotation

The discrepancy that we have found may be due to rotation in the closed form implementation. We can test this by using a source on the xx-axis.

cfg = { 'simulator' : { "model" : "Raytrace", "cropsize" : 256 }
      , 'lens': { 
            'mode' : "PM",
            'einsteinR': 46,
            'ellipseratio': 0.34,
            'orientation': 107,
            'chi': 50}
      , 'source': {
            'mode': 'Spherical',
            'sigma': 7,
            'position': 'cartesian'}
      , 'position': {'x': 40, 'y': 0}
      }
param = Parameters( cfg )
rotM = SimImage( param, verbose=0 ).getImage()

param["simulator"]["model"] = "Point Mass (exact)" 
rotX = SimImage( param, verbose=0 ).getImage()
csimg.imageCompare( rotM, rotX, "Modular Raytrace", 'Exact Point Mass')
<Figure size 1500x500 with 3 Axes>

This is a perfect match as far as visiual perception goes. We can repeat the experiment with Roulettes.

param["simulator"]["model"] = "Roulette" 
param = Parameters( cfg )
rotMR = SimImage( param, verbose=0 ).getImage()

param["simulator"]["model"] = "Point Mass (roulettes)" 
rotR = SimImage( param, verbose=0 ).getImage()
csimg.imageCompare( rotMR, rotR, "Modular Roulette", 'Legacy Roulette')
<Figure size 1500x500 with 3 Axes>

Again we have a perfect match.

Conclusion

We note that there is a discrepancy between the modular and closed form implementations, which may be due to the rotation of the image employed in the closed form implementations.

We also had a discrepancy in between the sampled and unsampled modular roulette impllementations, but this only affects the spurious images.