Commit 5c15aae8 authored by GZhao's avatar GZhao
Browse files

update csst/msc cosmic ray model

parent c2287032
Pipeline #8571 passed with stage
in 0 seconds
import os
import math import math
import numpy as np import numpy as np
import scipy.ndimage as nd import scipy.ndimage as nd
...@@ -7,6 +8,7 @@ from .config import config, S ...@@ -7,6 +8,7 @@ from .config import config, S
from .utils import region_replace, random_seed_select from .utils import region_replace, random_seed_select
from .io import log from .io import log
from .optics import filter_throughput from .optics import filter_throughput
from .msc_cr import produceCR_Map
cpism_refdata = config['cpism_refdata'] cpism_refdata = config['cpism_refdata']
MAG_SYSTEM = config['mag_system'] MAG_SYSTEM = config['mag_system']
...@@ -76,16 +78,19 @@ class CosmicRayFrameMaker(object): ...@@ -76,16 +78,19 @@ class CosmicRayFrameMaker(object):
The pitch of the camera pixel in um. The pitch of the camera pixel in um.
cr_rate : float cr_rate : float
The cosmic ray rate per second per cm2. The cosmic ray rate per second per cm2.
""" """
def __init__(self) -> None: def __init__(self, msc_model=False) -> None:
self.tmp_size = [7, 101] self.tmp_size = [7, 101]
self.freq_power = -0.9 self.freq_power = -0.9
self.trail_std = 0.1 self.trail_std = 0.1
self.depth = 10 # um self.depth = 10 # um
self.pitch = 13 # um self.pitch = 13 # um
self.cr_rate = 1 # particle per s per cm2 from Miles et al. 2021 self.cr_rate = 1 # particle per s per cm2 from Miles et al. 2021
data_folder = os.path.dirname(__file__)
cr_path = os.path.join(data_folder, 'data/cr_path.txt')
self.attachedSize = np.loadtxt(cr_path)
self.msc_model = msc_model
def make_CR(self, length, sigma, seed=-1): def make_CR(self, length, sigma, seed=-1):
""" """
...@@ -249,6 +254,15 @@ class CosmicRayFrameMaker(object): ...@@ -249,6 +254,15 @@ class CosmicRayFrameMaker(object):
seed = random_seed_select(seed=seed) seed = random_seed_select(seed=seed)
log.debug(f"cr position seed: {seed}") log.debug(f"cr position seed: {seed}")
if self.msc_model:
cr_map, cr_event_num = produceCR_Map(
xLen=shape[1], yLen=shape[0],
exTime=expt,
cr_pixelRatio=0.003*expt/600., # 5e-6/pixel , 1.3e-6 for cpic package
gain=1, # gain = 1, means the unit of output image is electron
attachedSizes=self.attachedSizes)
return cr_map
for i in range(len(cr_array)): for i in range(len(cr_array)):
cr = cr_array[i] cr = cr_array[i]
x = np.random.rand() * sz[1] x = np.random.rand() * sz[1]
......
...@@ -92,10 +92,11 @@ config['pysyn_refdata'] = f'{cpism_refdata}/starmodel/grp/redcat/trds' ...@@ -92,10 +92,11 @@ config['pysyn_refdata'] = f'{cpism_refdata}/starmodel/grp/redcat/trds'
config['catalog_folder'] = f'{cpism_refdata}/demo_catalog' config['catalog_folder'] = f'{cpism_refdata}/demo_catalog'
config['csst_format'] = True config['csst_format'] = True
config['nsample'] = 1 config['nsample'] = 1
config['msc_cr_model'] = False
update_able_keys = [ update_able_keys = [
'apm_file', 'actuator_file', 'aberration', 'apm_file', 'actuator_file', 'aberration',
'log_dir', 'log_level', 'catalog_folder', 'log_dir', 'log_level', 'catalog_folder', 'msc_cr_model'
'nsample', 'csst_format', 'output', 'check_fits_header' 'nsample', 'csst_format', 'output', 'check_fits_header'
] ]
......
# Graph from wfc-cr-attach, page 1
0.00000 0.004684
0.5031 0.004684
0.5283 0.01873
1.509 0.01873
1.534 0.09327
2.490 0.09327
2.515 0.1034
3.496 0.1034
3.522 0.2440
4.503 0.2440
4.528 0.1107
5.509 0.1107
5.534 0.1013
6.490 0.1013
6.515 0.06090
7.496 0.06090
7.522 0.05834
8.503 0.05834
8.528 0.03875
9.509 0.03875
9.534 0.03066
10.49 0.03066
10.51 0.01788
11.47 0.01788
11.49 0.01831
13.50 0.01831
13.53 0.01235
13.53 0.01235
14.49 0.01235
14.51 0.01064
15.49 0.01064
15.52 0.008091
16.50 0.008091
16.52 0.004684
17.48 0.004684
17.53 0.003833
18.49 0.003833
18.51 0.005536
19.47 0.005536
19.52 0.004684
20.00 0.004684
\ No newline at end of file
...@@ -342,6 +342,11 @@ def observation_simulation_from_config(obs_file, config_file): ...@@ -342,6 +342,11 @@ def observation_simulation_from_config(obs_file, config_file):
csst_format = default_config['csst_format'] csst_format = default_config['csst_format']
nsample = default_config['nsample'] nsample = default_config['nsample']
if default_config['msc_cr_model']:
crmaker = CosmicRayFrameMaker(msc_model=True)
else:
crmaker = CosmicRayFrameMaker()
obs_file = os.path.abspath(obs_file) obs_file = os.path.abspath(obs_file)
file_list = [] file_list = []
...@@ -417,6 +422,7 @@ def observation_simulation_from_config(obs_file, config_file): ...@@ -417,6 +422,7 @@ def observation_simulation_from_config(obs_file, config_file):
output=output, output=output,
nsample=nsample, nsample=nsample,
csst_format=csst_format, csst_format=csst_format,
crmaker=crmaker,
dataset=dataset, dataset=dataset,
prograss_bar=True) prograss_bar=True)
except Exception as e: except Exception as e:
......
import numpy as np
import math
# ---------- For Cosmic-Ray Simulation ------------
# ---------- Zhang Xin ---------------
# ---------- From MSC/CSST simulation package-------------
# ---------- The initial code can be found at
# https://csst-tb.bao.ac.cn/code/liudezi/csst_msc_sim/-/blob/release_v2.0/ObservationSim/Instrument/Chip/Effects.py
def getYValue(collection, x):
index = 0
if (collection.shape[1] == 2):
while (x > collection[index, 0] and index < collection.shape[0]):
index = index + 1
if (index == collection.shape[0] or index == 0):
return 0
deltX = collection[index, 0] - collection[index-1, 0]
deltY = collection[index, 1] - collection[index-1, 1]
if deltX == 0:
return (collection[index, 1] + collection[index-1, 1])/2.0
else:
a = deltY/deltX
return a * (x - collection[index-1, 0]) + collection[index-1, 1]
return 0
def selectCosmicRayCollection(attachedSizes, xLen, yLen, cr_pixelRatio, CR_max_size):
normalRay = 0.90
nnormalRay = 1-normalRay
max_nrayLen = 100
pixelNum = int(xLen * yLen * cr_pixelRatio * normalRay)
pixelNum_n = int(xLen * yLen * cr_pixelRatio * nnormalRay)
CRPixelNum = 0
maxValue = max(attachedSizes[:, 1])
maxValue += 0.1
cr_event_num = 0
CRs = np.zeros(pixelNum)
while (CRPixelNum < pixelNum):
x = CR_max_size * np.random.random()
y = maxValue * np.random.random()
if (y <= getYValue(attachedSizes, x)):
CRs[cr_event_num] = np.ceil(x)
cr_event_num = cr_event_num + 1
CRPixelNum = CRPixelNum + round(x)
while (CRPixelNum < pixelNum + pixelNum_n):
nx = np.random.random()*(max_nrayLen-CR_max_size)+CR_max_size
CRs[cr_event_num] = np.ceil(nx)
cr_event_num = cr_event_num + 1
CRPixelNum = CRPixelNum + np.ceil(nx)
return CRs[0:cr_event_num]
def defineEnergyForCR(cr_event_size, seed=12345):
import random
sigma = 0.6 / 2.355
mean = 3.3
random.seed(seed)
energys = np.zeros(cr_event_size)
for i in np.arange(cr_event_size):
energy_index = random.normalvariate(mean, sigma)
energys[i] = pow(10, energy_index)
return energys
def convCR(CRmap=None, addPSF=None, sp_n=4):
sh = CRmap.shape
# sp_n = 4
subCRmap = np.zeros(np.array(sh)*sp_n)
pix_v0 = 1/(sp_n*sp_n)
for i in np.arange(sh[0]):
i_st = sp_n*i
for j in np.arange(sh[1]):
if CRmap[i, j] == 0:
continue
j_st = sp_n*j
pix_v1 = CRmap[i, j]*pix_v0
for m in np.arange(sp_n):
for n in np.arange(sp_n):
subCRmap[i_st+m, j_st + n] = pix_v1
m_size = addPSF.shape[0]
subCRmap_n = np.zeros(np.array(subCRmap.shape) + m_size - 1)
for i in np.arange(subCRmap.shape[0]):
for j in np.arange(subCRmap.shape[1]):
if subCRmap[i, j] > 0:
convPix = addPSF*subCRmap[i, j]
subCRmap_n[i:i+m_size, j:j+m_size] += convPix
CRmap_n = np.zeros((np.array(subCRmap_n.shape)/sp_n).astype(np.int32))
sh_n = CRmap_n.shape
for i in np.arange(sh_n[0]):
i_st = sp_n*i
for j in np.arange(sh_n[1]):
p_v = 0
j_st = sp_n*j
for m in np.arange(sp_n):
for n in np.arange(sp_n):
p_v += subCRmap_n[i_st+m, j_st + n]
CRmap_n[i, j] = p_v
return CRmap_n
def produceCR_Map(xLen, yLen, exTime, cr_pixelRatio, gain, attachedSizes, seed=20210317):
# Return: an 2-D numpy array
# attachedSizes = np.loadtxt('./wfc-cr-attachpixel.dat');
np.random.seed(seed)
CR_max_size = 20.0
cr_size = selectCosmicRayCollection(attachedSizes, xLen, yLen, cr_pixelRatio, CR_max_size)
cr_event_size = cr_size.shape[0]
cr_energys = defineEnergyForCR(cr_event_size, seed=seed)
CRmap = np.zeros([yLen, xLen])
# produce conv kernel
from astropy.modeling.models import Gaussian2D
o_size = 4
sp_n = 8
m_size = o_size*sp_n+1
m_cen = o_size*sp_n/2
sigma_psf = 0.2*sp_n
addPSF_ = Gaussian2D(1, m_cen, m_cen, sigma_psf, sigma_psf)
yp, xp = np.mgrid[0:m_size, 0:m_size]
addPSF = addPSF_(xp, yp)
convKernel = addPSF/addPSF.sum()
# ---------------------------------
for i in np.arange(cr_event_size):
xPos = round((xLen - 1) * np.random.random())
yPos = round((yLen - 1) * np.random.random())
cr_lens = int(cr_size[i])
if cr_lens == 0:
continue
pix_energy = cr_energys[i]/gain/cr_lens
pos_angle = 1/2*math.pi*np.random.random()
crMatrix = np.zeros([cr_lens+1, cr_lens + 1])
for j in np.arange(cr_lens):
x_n = int(np.cos(pos_angle)*j - np.sin(pos_angle)*0)
if x_n < 0:
x_n = x_n + cr_lens+1
y_n = int(np.sin(pos_angle)*j + np.cos(pos_angle)*0)
if x_n < 0 or x_n > cr_lens or y_n < 0 or y_n > cr_lens:
continue
crMatrix[y_n, x_n] = pix_energy
crMatrix_n = convCR(crMatrix, convKernel, sp_n)
xpix = np.arange(crMatrix_n.shape[0]) + int(xPos)
ypix = np.arange(crMatrix_n.shape[1]) + int(yPos)
sh = CRmap.shape
okx = (xpix >= 0) & (xpix < sh[1])
oky = (ypix >= 0) & (ypix < sh[0])
sly = slice(ypix[oky].min(), ypix[oky].max()+1)
slx = slice(xpix[okx].min(), xpix[okx].max()+1)
CRmap[sly, slx] += crMatrix_n[oky, :][:, okx]
return CRmap.astype(np.int32), cr_event_size
...@@ -41,3 +41,4 @@ nsample: 1 ...@@ -41,3 +41,4 @@ nsample: 1
check_fits_header: true check_fits_header: true
output: ./example_output/ output: ./example_output/
actuator_file: ${cpism_refdata}/optics/dark_zone_0011_volt.fits actuator_file: ${cpism_refdata}/optics/dark_zone_0011_volt.fits
msc_cr_model: true
...@@ -28,7 +28,7 @@ setuptools.setup( ...@@ -28,7 +28,7 @@ setuptools.setup(
package_dir={'csst_cpic_sim': 'csst_cpic_sim'}, package_dir={'csst_cpic_sim': 'csst_cpic_sim'},
include_package_data=True, include_package_data=True,
package_data={ package_data={
'csst_cpic_sim': ['data/*.yaml', 'data/*.toml'] 'csst_cpic_sim': ['data/*.yaml', 'data/*.toml', 'data/*.txt']
}, },
install_requires=requirements, install_requires=requirements,
......
...@@ -54,8 +54,9 @@ class TestMain(unittest.TestCase): ...@@ -54,8 +54,9 @@ class TestMain(unittest.TestCase):
text = fid.read() text = fid.read()
text = text.replace('<output>', output) text = text.replace('<output>', output)
config_text = text.replace('<msc_model>', "True")
with open(output+'/run_config_new.yaml', 'w') as fid: with open(output+'/run_config_new.yaml', 'w') as fid:
fid.write(text) fid.write(config_text)
observation_simulation_from_config( observation_simulation_from_config(
os.path.join(cases, '05_sci.yaml'), os.path.join(cases, '05_sci.yaml'),
...@@ -66,6 +67,7 @@ class TestMain(unittest.TestCase): ...@@ -66,6 +67,7 @@ class TestMain(unittest.TestCase):
self.assertEqual(len(file), 4) self.assertEqual(len(file), 4)
clear_output() clear_output()
observation_simulation_from_config( observation_simulation_from_config(
os.path.join(cases, '05_sci.yaml'), os.path.join(cases, '05_sci.yaml'),
None None
...@@ -74,6 +76,20 @@ class TestMain(unittest.TestCase): ...@@ -74,6 +76,20 @@ class TestMain(unittest.TestCase):
self.assertEqual(len(file), 1) self.assertEqual(len(file), 1)
self.assertEqual(file[0][:5], 'SCI') self.assertEqual(file[0][:5], 'SCI')
clear_output()
config_text = text.replace('<msc_model>', "False")
with open(output+'/run_config_new.yaml', 'w') as fid:
fid.write(config_text)
observation_simulation_from_config(
os.path.join(cases, '05_sci.yaml'),
os.path.join(output, 'run_config_new.yaml')
)
file = os.listdir(output)
self.assertEqual(len(file), 4)
def test_full_run_cmdline(self): def test_full_run_cmdline(self):
clear_output() clear_output()
main(['run', os.path.join(cases, '05_sci.yaml')]) main(['run', os.path.join(cases, '05_sci.yaml')])
......
...@@ -40,3 +40,4 @@ csst_format: true ...@@ -40,3 +40,4 @@ csst_format: true
nsample: 5 nsample: 5
check_fits_header: true check_fits_header: true
output: <output> output: <output>
msc_cr_model: <msc_model>
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment