Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
csst-sims
csst_cpic_sim
Commits
72c1f3f5
Commit
72c1f3f5
authored
May 08, 2025
by
GZhao
Browse files
toml data model; add dataset keyword; update fits header
parent
66d8b23f
Pipeline
#8266
failed with stage
in 0 seconds
Changes
8
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
csst_cpic_sim/camera.py
View file @
72c1f3f5
...
@@ -474,7 +474,6 @@ class CpicVisEmccd(object):
...
@@ -474,7 +474,6 @@ class CpicVisEmccd(object):
np.ndarray
np.ndarray
bias frame
bias frame
"""
"""
shape
=
self
.
bias_shape
shape
=
self
.
bias_shape
TPI
=
np
.
pi
*
2
TPI
=
np
.
pi
*
2
...
@@ -681,15 +680,17 @@ class CpicVisEmccd(object):
...
@@ -681,15 +680,17 @@ class CpicVisEmccd(object):
self
.
volt
=
volt_func
(
em_set
)
self
.
volt
=
volt_func
(
em_set
)
volt_3ff
=
volt_func
(
int
(
'3ff'
,
16
))
#
volt_3ff = volt_func(int('3ff', 16))
volt_190
=
volt_func
(
int
(
'190'
,
16
))
#
volt_190 = volt_func(int('190', 16))
em_coe_c
=
0.24
em_coe_c
=
0.24
65
# using the expression of em_b = ln(g199) / constant to make fitting easier
# using the expression of em_b = ln(g199) / constant to make fitting easier
constant
=
(
np
.
exp
(
em_coe_c
*
volt_190
)
-
np
.
exp
(
em_coe_c
*
volt_3ff
))
# constant = (np.exp(em_coe_c * volt_190) - np.exp(em_coe_c * volt_3ff))
# fitting from the ccd test result
# # fitting from the ccd test result
ln_g190
=
(
-
ccd_temp
-
7
)
*
0.0325
# ln_g190 = (-ccd_temp - 7) * 0.0325
em_coe_b
=
ln_g190
/
constant
# em_coe_b = ln_g190 / constant
em_coe_b
=
-
0.31041118
*
ccd_temp
+
8.61774308
em_coe_b
=
em_coe_b
*
1e-5
emgain
=
np
.
exp
(
em_coe_b
*
np
.
exp
(
em_coe_c
*
self
.
volt
))
emgain
=
np
.
exp
(
em_coe_b
*
np
.
exp
(
em_coe_c
*
self
.
volt
))
emgain
=
np
.
maximum
(
1
,
emgain
)
emgain
=
np
.
maximum
(
1
,
emgain
)
...
@@ -759,7 +760,7 @@ class CpicVisEmccd(object):
...
@@ -759,7 +760,7 @@ class CpicVisEmccd(object):
# img_line = np.convolve(image.flatten(), self.cti_trail, mode='full')
# img_line = np.convolve(image.flatten(), self.cti_trail, mode='full')
# return img_line[:shape[0]*shape[1]].reshape(shape)
# return img_line[:shape[0]*shape[1]].reshape(shape)
def
readout
(
self
,
image_focal
,
em_set
,
expt_set
,
image_cosmic_ray
=
False
,
emgain
=
None
):
def
readout
(
self
,
image_focal
,
em_set
,
expt_set
,
image_cosmic_ray
=
False
,
emgain
=
None
,
seed
=-
1
):
"""From focal planet image to ccd output.
"""From focal planet image to ccd output.
Interface function for emccd. Simulate the readout process.
Interface function for emccd. Simulate the readout process.
...
@@ -775,13 +776,17 @@ class CpicVisEmccd(object):
...
@@ -775,13 +776,17 @@ class CpicVisEmccd(object):
cosmic ray image. Unit: photon-electron/pixel
cosmic ray image. Unit: photon-electron/pixel
emgain: float, optional
emgain: float, optional
if not None, use the given emgain. Else, calculate the emgain using em_set
if not None, use the given emgain. Else, calculate the emgain using em_set
seed: int, optional
random seed. Default is -1, which means no random seed.
Returns
Returns
-------
-------
np.ndarray
np.ndarray
ccd output image. Unit: ADU
ccd output image. Unit: ADU
"""
"""
if
seed
!=
-
1
:
np
.
random
.
seed
(
seed
)
expt
=
expt_set
expt
=
expt_set
if
expt_set
==
0
:
if
expt_set
==
0
:
expt
=
0.001
expt
=
0.001
...
@@ -844,6 +849,7 @@ class CpicVisEmccd(object):
...
@@ -844,6 +849,7 @@ class CpicVisEmccd(object):
image_shutter
=
np
.
random
.
poisson
(
image_shutter
)
image_shutter
=
np
.
random
.
poisson
(
image_shutter
)
image
[:,
self
.
pscan1
+
self
.
ldark
:
-
self
.
oscan1
-
self
.
rdark
]
+=
image_shutter
image
[:,
self
.
pscan1
+
self
.
ldark
:
-
self
.
oscan1
-
self
.
rdark
]
+=
image_shutter
if
self
.
switch
[
'cic'
]:
if
self
.
switch
[
'cic'
]:
cic_frame
=
np
.
zeros
((
self
.
dark_shape
[
0
],
self
.
bias_shape
[
1
]))
+
self
.
cic
cic_frame
=
np
.
zeros
((
self
.
dark_shape
[
0
],
self
.
bias_shape
[
1
]))
+
self
.
cic
image
[
self
.
pscan2
:
-
self
.
oscan2
,
:]
+=
np
.
random
.
poisson
(
cic_frame
)
image
[
self
.
pscan2
:
-
self
.
oscan2
,
:]
+=
np
.
random
.
poisson
(
cic_frame
)
...
@@ -855,8 +861,11 @@ class CpicVisEmccd(object):
...
@@ -855,8 +861,11 @@ class CpicVisEmccd(object):
# >>> image += np.random.binomial(image, pEM)
# >>> image += np.random.binomial(image, pEM)
# This code is too slow, so we used a modified gamma
# This code is too slow, so we used a modified gamma
em_fix
=
self
.
em_fix_fuc_fit
(
emgain
)
*
emgain
em_fix
=
self
.
em_fix_fuc_fit
(
emgain
)
*
emgain
image
=
np
.
random
.
gamma
(
image
,
em_fix
)
+
image
*
(
emgain
-
em_fix
)
image
=
np
.
random
.
gamma
(
image
,
em_fix
)
+
image
*
(
emgain
-
em_fix
)
if
self
.
switch
[
'em_blooming'
]:
if
self
.
switch
[
'em_blooming'
]:
image
=
self
.
emregester_blooming
(
image
)
image
=
self
.
emregester_blooming
(
image
)
...
@@ -870,6 +879,7 @@ class CpicVisEmccd(object):
...
@@ -870,6 +879,7 @@ class CpicVisEmccd(object):
residual
=
np
.
random
.
binomial
(
image
,
1
-
big_cte
)
residual
=
np
.
random
.
binomial
(
image
,
1
-
big_cte
)
image
[:,
1
:]
+=
residual
[:,
:
-
1
]
-
residual
[:,
1
:]
image
[:,
1
:]
+=
residual
[:,
:
-
1
]
-
residual
[:,
1
:]
bias
=
self
.
bias_frame
()
bias
=
self
.
bias_frame
()
image
=
image
/
self
.
ph_per_adu
+
bias
image
=
image
/
self
.
ph_per_adu
+
bias
...
...
csst_cpic_sim/config.py
View file @
72c1f3f5
...
@@ -81,7 +81,7 @@ config['bands'] = {
...
@@ -81,7 +81,7 @@ config['bands'] = {
}
}
config
[
'diameter'
]
=
2
# in meters
config
[
'diameter'
]
=
2
# in meters
config
[
'platescale'
]
=
0.016153
config
[
'platescale'
]
=
0.016153
config
[
'datamodel'
]
=
f
'
{
cpism_refdata
}
/io/csst-cpic-l0.
ya
ml'
config
[
'datamodel'
]
=
f
'
{
cpism_refdata
}
/io/csst-cpic-l0.
to
ml'
config
[
'log_dir'
]
=
f
'
{
cpism_refdata
}
/log'
config
[
'log_dir'
]
=
f
'
{
cpism_refdata
}
/log'
config
[
'log_level'
]
=
'info'
config
[
'log_level'
]
=
'info'
...
@@ -91,7 +91,7 @@ config['dm_pickle'] = f'{cpism_refdata}/optics/dm_model.pkl'
...
@@ -91,7 +91,7 @@ config['dm_pickle'] = f'{cpism_refdata}/optics/dm_model.pkl'
config
[
'pysyn_refdata'
]
=
f
'
{
cpism_refdata
}
/starmodel/grp/redcat/trds'
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'
]
=
5
config
[
'nsample'
]
=
1
update_able_keys
=
[
update_able_keys
=
[
'apm_file'
,
'actuator_file'
,
'aberration'
,
'apm_file'
,
'actuator_file'
,
'aberration'
,
...
@@ -99,7 +99,6 @@ update_able_keys = [
...
@@ -99,7 +99,6 @@ update_able_keys = [
'nsample'
,
'csst_format'
,
'output'
,
'check_fits_header'
'nsample'
,
'csst_format'
,
'output'
,
'check_fits_header'
]
]
def
replace_cpism_refdata
(
def
replace_cpism_refdata
(
config
:
dict
,
config
:
dict
,
output
:
str
=
'$'
)
->
None
:
output
:
str
=
'$'
)
->
None
:
...
...
csst_cpic_sim/io.py
View file @
72c1f3f5
import
yaml
import
os
import
os
from
datetime
import
datetime
from
datetime
import
datetime
import
numpy
as
np
import
numpy
as
np
...
@@ -6,6 +5,7 @@ import pandas as pd
...
@@ -6,6 +5,7 @@ import pandas as pd
from
astropy.io
import
fits
from
astropy.io
import
fits
from
astropy.coordinates
import
SkyCoord
from
astropy.coordinates
import
SkyCoord
import
astropy.units
as
u
import
astropy.units
as
u
import
toml
from
.config
import
__version__
,
which_focalplane
from
.config
import
__version__
,
which_focalplane
from
.utils
import
Logger
from
.utils
import
Logger
...
@@ -44,21 +44,25 @@ def check_and_update_fits_header(header):
...
@@ -44,21 +44,25 @@ def check_and_update_fits_header(header):
# if hdu == 'primary':
# if hdu == 'primary':
# model_file = f"{cpism_refdata}/io/primary_header.json"
# model_file = f"{cpism_refdata}/io/primary_header.json"
model_file
=
config
[
'datamodel'
]
model_file
=
config
[
'datamodel'
]
with
open
(
model_file
,
'r'
,
encoding
=
'utf-8'
)
as
fid
:
data_model
=
toml
.
load
(
model_file
)
data_model
=
yaml
.
load
(
fid
,
Loader
=
yaml
.
FullLoader
)
if
'
FILETYP
E'
in
header
.
keys
():
if
'
SIMPL
E'
in
header
.
keys
():
header_model
=
data_model
[
'HDU0'
]
header_model
=
data_model
[
'HDU0'
]
hdu
=
'hdu0'
hdu
=
'hdu0'
else
:
else
:
header_model
=
data_model
[
'HDU
1
'
]
header_model
=
data_model
[
'HDU
N
'
]
hdu
=
'hdu1'
hdu
=
'hdu1'
dm_comment
=
{}
dm_comment
=
{}
def
print_warning
(
info
):
def
print_warning
(
info
):
if
header_check
:
if
header_check
:
log
.
warning
(
info
)
log
.
warning
(
info
)
has_all_keywords
=
True
has_unexpected_keywords
=
True
has_correct_order
=
True
# check existance and format of keyword in fits header
# check existance and format of keyword in fits header
for
_
,
content
in
header_model
.
items
():
for
_
,
content
in
header_model
.
items
():
comment
=
content
[
'comment'
]
comment
=
content
[
'comment'
]
...
@@ -76,6 +80,7 @@ def check_and_update_fits_header(header):
...
@@ -76,6 +80,7 @@ def check_and_update_fits_header(header):
if
keyword
not
in
header
.
keys
():
if
keyword
not
in
header
.
keys
():
print_warning
(
f
"Keyword
{
keyword
}
not found in header."
)
print_warning
(
f
"Keyword
{
keyword
}
not found in header."
)
has_all_keywords
=
False
elif
not
pd
.
isnull
(
dtype
):
elif
not
pd
.
isnull
(
dtype
):
value
=
header
[
keyword
]
value
=
header
[
keyword
]
...
@@ -108,9 +113,28 @@ def check_and_update_fits_header(header):
...
@@ -108,9 +113,28 @@ def check_and_update_fits_header(header):
if
keyword
not
in
dm_comment
.
keys
():
if
keyword
not
in
dm_comment
.
keys
():
print_warning
(
print_warning
(
f
"Keyword
{
keyword
}
not found in the [
{
hdu
}
] data model."
)
f
"Keyword
{
keyword
}
not found in the [
{
hdu
}
] data model."
)
has_unexpected_keywords
=
False
elif
keyword
!=
'COMMENT'
:
# comment keyword is not allowed to be updated
elif
keyword
!=
'COMMENT'
:
# comment keyword is not allowed to be updated
header
[
keyword
]
=
(
header
[
keyword
],
dm_comment
[
keyword
])
header
[
keyword
]
=
(
header
[
keyword
],
dm_comment
[
keyword
])
if
has_unexpected_keywords
and
has_all_keywords
:
# if there is no other keywords, then use the default header model
for
header_key
,
model_key
in
zip
(
header
.
keys
(),
dm_comment
.
keys
()):
if
header_key
!=
model_key
:
print_warning
(
f
"Keyword
{
header_key
}
not correspond to
{
model_key
}
"
)
has_correct_order
=
False
else
:
has_correct_order
=
False
overview
=
"data model check: [OVERVIEW]
\n
"
if
not
has_correct_order
:
overview
+=
"The header is not in the correct order
\n
"
if
not
has_all_keywords
:
overview
+=
"The header is missing some keywords
\n
"
if
not
has_unexpected_keywords
:
overview
+=
"The header contains some unexpected keywords
\n
"
print_warning
(
overview
)
return
header
return
header
...
@@ -123,7 +147,7 @@ def obsid_parser(
...
@@ -123,7 +147,7 @@ def obsid_parser(
----------
----------
obsid: str
obsid: str
The obsid of the observation.
The obsid of the observation.
Obsid must be 11 digits and start with
5
for CPIC.
Obsid must be 11 digits and start with
4
for CPIC.
Returns
Returns
-------
-------
...
@@ -133,7 +157,7 @@ def obsid_parser(
...
@@ -133,7 +157,7 @@ def obsid_parser(
Raises
Raises
------
------
ValueError
ValueError
If the obsid is not 11 digits or does not start with
5
.
If the obsid is not 11 digits or does not start with
4
.
"""
"""
obsid
=
str
(
obsid
)
obsid
=
str
(
obsid
)
if
len
(
obsid
)
!=
11
:
if
len
(
obsid
)
!=
11
:
...
@@ -261,9 +285,11 @@ def primary_hdu(
...
@@ -261,9 +285,11 @@ def primary_hdu(
if
len
(
heaer_filename
)
>
68
:
if
len
(
heaer_filename
)
>
68
:
heaer_filename
=
heaer_filename
[:
68
]
heaer_filename
=
heaer_filename
[:
68
]
header
[
'FILENAME'
]
=
heaer_filename
header
[
'FILENAME'
]
=
heaer_filename
header
[
'FILETYPE'
]
=
obsid_parser
(
obsid
)
header
[
'TELESCOP'
]
=
'CSST'
header
[
'TELESCOP'
]
=
'CSST'
header
[
'INSTRUME'
]
=
'CPIC'
header
[
'INSTRUME'
]
=
'CPIC'
header
[
'OBSID'
]
=
str
(
obsid
)
header
[
'OBSTYPE'
]
=
obsid_parser
(
obsid
)
header
[
'DATASET'
]
=
obs_info
.
get
(
"dataset"
,
"default"
)
header
[
'RADECSYS'
]
=
'ICRS'
header
[
'RADECSYS'
]
=
'ICRS'
header
[
'EQUINOX'
]
=
2000.0
header
[
'EQUINOX'
]
=
2000.0
header
[
'FITSSWV'
]
=
f
'CPISM V
{
__version__
}
'
header
[
'FITSSWV'
]
=
f
'CPISM V
{
__version__
}
'
...
@@ -280,7 +306,7 @@ def primary_hdu(
...
@@ -280,7 +306,7 @@ def primary_hdu(
header
[
'OBJECT'
]
=
cstar
.
get
(
'name'
,
target_name
)
header
[
'OBJECT'
]
=
cstar
.
get
(
'name'
,
target_name
)
header
[
'TARGET'
]
=
target_name
header
[
'TARGET'
]
=
target_name
header
[
'OBSID'
]
=
str
(
obsid
)
header
[
'RA_OBJ'
]
=
radec
.
ra
.
degree
header
[
'RA_OBJ'
]
=
radec
.
ra
.
degree
header
[
'DEC_OBJ'
]
=
radec
.
dec
.
degree
header
[
'DEC_OBJ'
]
=
radec
.
dec
.
degree
...
@@ -404,9 +430,9 @@ def frame_header(obs_info, index, primary_header, camera_dict):
...
@@ -404,9 +430,9 @@ def frame_header(obs_info, index, primary_header, camera_dict):
header
[
'DETSN'
]
=
'00000000000'
header
[
'DETSN'
]
=
'00000000000'
header
[
'DETNAME'
]
=
camera_config
[
'detector_name'
]
header
[
'DETNAME'
]
=
camera_config
[
'detector_name'
]
header
[
'CHIPLAB'
]
=
camera_config
[
'ccd_label'
]
header
[
'CHIPLAB'
]
=
camera_config
[
'ccd_label'
]
header
[
'DEWTEMP'
]
=
float
(
camera_config
[
'cooler_temp'
])
+
273.15
frame_info
=
obs_info
[
'frame_info'
][
index
]
frame_info
=
obs_info
[
'frame_info'
][
index
]
header
[
'CHIPTEMP'
]
=
float
(
frame_info
[
'chiptemp'
])
+
273.15
header
[
'CHIPTEMP'
]
=
float
(
frame_info
[
'chiptemp'
])
+
273.15
header
[
'DEWTEMP'
]
=
float
(
camera_config
[
'cooler_temp'
])
+
273.15
header
[
'DETSIZE'
]
=
f
"
{
imgszx
}
*
{
imgszy
}
"
header
[
'DETSIZE'
]
=
f
"
{
imgszx
}
*
{
imgszy
}
"
header
[
'IMGINDEX'
]
=
index
+
1
header
[
'IMGINDEX'
]
=
index
+
1
...
...
csst_cpic_sim/main.py
View file @
72c1f3f5
...
@@ -38,7 +38,8 @@ def vis_observation(
...
@@ -38,7 +38,8 @@ def vis_observation(
nsample
:
int
=
1
,
nsample
:
int
=
1
,
emgain
=
None
,
emgain
=
None
,
prograss_bar
=
None
,
prograss_bar
=
None
,
output
=
'./'
output
=
'./'
,
dataset
=
'default'
)
->
np
.
ndarray
:
)
->
np
.
ndarray
:
"""Observation simulation main process on visable band using EMCCD.
"""Observation simulation main process on visable band using EMCCD.
...
@@ -110,6 +111,7 @@ def vis_observation(
...
@@ -110,6 +111,7 @@ def vis_observation(
'obsid'
:
obsid
,
'obsid'
:
obsid
,
'rotation'
:
rotation
,
'rotation'
:
rotation
,
'shift'
:
shift
,
'shift'
:
shift
,
'dataset'
:
dataset
}
}
all_frame_info
=
[]
all_frame_info
=
[]
...
@@ -262,6 +264,7 @@ def quick_run_v2(
...
@@ -262,6 +264,7 @@ def quick_run_v2(
emgain_value
=
None
emgain_value
=
None
camera
=
CpicVisEmccd
()
camera
=
CpicVisEmccd
()
camera
.
switch
[
'bias_ci'
]
=
False
if
not
camera_effect
:
if
not
camera_effect
:
camera
.
switch
[
'bias_vp'
]
=
False
camera
.
switch
[
'bias_vp'
]
=
False
camera
.
switch
[
'bias_hp'
]
=
False
camera
.
switch
[
'bias_hp'
]
=
False
...
@@ -288,7 +291,8 @@ def quick_run_v2(
...
@@ -288,7 +291,8 @@ def quick_run_v2(
rotation
=
rotation
,
rotation
=
rotation
,
camera
=
camera
,
camera
=
camera
,
prograss_bar
=
prograss_bar
,
prograss_bar
=
prograss_bar
,
output
=
output
output
=
output
,
nsample
=
10
)
)
...
...
example/observations/05_sci.yaml
View file @
72c1f3f5
band
:
f66
2
band
:
f66
1
emgain
:
200
emgain
:
200
emset
:
-1
emset
:
-1
expt
:
100
expt
:
100
...
...
example/run_config.yaml
View file @
72c1f3f5
...
@@ -37,7 +37,7 @@ camera:
...
@@ -37,7 +37,7 @@ camera:
nonlinear
:
false
nonlinear
:
false
shutter
:
false
shutter
:
false
csst_format
:
true
csst_format
:
true
nsample
:
1
0
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
modelcompare.png
deleted
100644 → 0
View file @
66d8b23f
38.9 KB
refdata/cpism_config_default.yaml
View file @
72c1f3f5
...
@@ -18,7 +18,7 @@ bands:
...
@@ -18,7 +18,7 @@ bands:
f720
:
${cpism_refdata}/throughtput/f720.fits
f720
:
${cpism_refdata}/throughtput/f720.fits
diameter
:
2
diameter
:
2
platescale
:
0.016153
platescale
:
0.016153
datamodel
:
${cpism_refdata}/io/csst-cpic-l0.
ya
ml
datamodel
:
${cpism_refdata}/io/csst-cpic-l0.
to
ml
log_dir
:
${cpism_refdata}/log
log_dir
:
${cpism_refdata}/log
log_level
:
info
log_level
:
info
output
:
./
output
:
./
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment