Commit 36189a3e authored by JX's avatar JX 😵
Browse files

Merge remote-tracking branch 'origin/develop'

parents dd26d370 27646bc4
Pipeline #4509 passed with stage
in 0 seconds
......@@ -4,9 +4,9 @@ import os
import numpy as np
import gc
import ObservationSim.Instrument._util as _util
from ObservationSim.Instrument.FilterParam import FilterParam
from ObservationSim.Straylight import Straylight
import observation_sim.instruments._util as _util
from observation_sim.instruments.FilterParam import FilterParam
from observation_sim.sky_background import Straylight
try:
import importlib.resources as pkg_resources
......@@ -14,6 +14,7 @@ except ImportError:
# Try backported to PY<37 'importlib_resources'
import importlib_resources as pkg_resources
class Filter(object):
def __init__(self, filter_id, filter_type, filter_param, ccd_bandpass=None):
self.filter_id = filter_id
......@@ -52,54 +53,64 @@ class Filter(object):
def _get_bandpasses(self, filter_dir=None, unit='A'):
if self.filter_id < 7: # Photometric
try:
with pkg_resources.files('ObservationSim.Instrument.data.filters').joinpath(self.filter_type.lower() + '.txt') as filter_file:
self.filter_bandpass = galsim.Bandpass(str(filter_file), wave_type=unit)
with pkg_resources.files('observation_sim.instruments.data.filters').joinpath(self.filter_type.lower() + '.txt') as filter_file:
self.filter_bandpass = galsim.Bandpass(
str(filter_file), wave_type=unit)
except AttributeError:
with pkg_resources.path('ObservationSim.Instrument.data.filters', self.filter_type.lower() + '.txt') as filter_file:
self.filter_bandpass = galsim.Bandpass(str(filter_file), wave_type=unit)
with pkg_resources.path('observation_sim.instruments.data.filters', self.filter_type.lower() + '.txt') as filter_file:
self.filter_bandpass = galsim.Bandpass(
str(filter_file), wave_type=unit)
try:
with pkg_resources.files('ObservationSim.Instrument.data.throughputs').joinpath(self.filter_type.lower() + '_throughput.txt') as filter_file:
bandpass_full = galsim.Bandpass(str(filter_file), wave_type=unit)
with pkg_resources.files('observation_sim.instruments.data.throughputs').joinpath(self.filter_type.lower() + '_throughput.txt') as filter_file:
bandpass_full = galsim.Bandpass(
str(filter_file), wave_type=unit)
except AttributeError:
with pkg_resources.path('ObservationSim.Instrument.data.throughputs', self.filter_type.lower() + '_throughput.txt') as filter_file:
bandpass_full = galsim.Bandpass(str(filter_file), wave_type=unit)
with pkg_resources.path('observation_sim.instruments.data.throughputs', self.filter_type.lower() + '_throughput.txt') as filter_file:
bandpass_full = galsim.Bandpass(
str(filter_file), wave_type=unit)
# bandpass_full = bandpass_full * self.ccd_bandpass
# Get sub-bandpasses
bandpass_sub_list = []
try:
with pkg_resources.files('ObservationSim.Instrument.data.filters').joinpath(self.filter_type.lower() + "_sub.list") as wave_bin_file:
with pkg_resources.files('observation_sim.instruments.data.filters').joinpath(self.filter_type.lower() + "_sub.list") as wave_bin_file:
wave_points = open(wave_bin_file).read().splitlines()
except AttributeError:
with pkg_resources.path('ObservationSim.Instrument.data.filters', self.filter_type.lower() + "_sub.list") as wave_bin_file:
with pkg_resources.path('observation_sim.instruments.data.filters', self.filter_type.lower() + "_sub.list") as wave_bin_file:
wave_points = open(wave_bin_file).read().splitlines()
for i in range(2, len(wave_points), 2):
blim = max(float(wave_points[i-2])*0.1, bandpass_full.blue_limit)
blim = max(float(wave_points[i-2])
* 0.1, bandpass_full.blue_limit)
rlim = min(float(wave_points[i])*0.1, bandpass_full.red_limit)
if blim >= rlim:
continue
bandpass = bandpass_full.truncate(blue_limit=blim, red_limit=rlim)
bandpass = bandpass_full.truncate(
blue_limit=blim, red_limit=rlim)
bandpass_sub_list.append(bandpass)
# print("num of sub-bandpasses for filter#%d(%s) = "%(self.filter_id, self.filter_type), len(bandpass_sub_list), flush=True)
else: # Spectroscopic
sls_lamb = np.linspace(self.blue_limit, self.red_limit, 100)
sls_flux = np.ones_like(sls_lamb)
con_spec = galsim.LookupTable(sls_lamb, sls_flux, interpolant='nearest')
con_spec = galsim.LookupTable(
sls_lamb, sls_flux, interpolant='nearest')
bandpass_full = galsim.Bandpass(con_spec, wave_type=unit)
bandpass_sub_list = []
try:
with pkg_resources.files('ObservationSim.Instrument.data.filters').joinpath(self.filter_type.lower() + "_sub.list") as wave_bin_file:
with pkg_resources.files('observation_sim.instruments.data.filters').joinpath(self.filter_type.lower() + "_sub.list") as wave_bin_file:
wave_points = open(wave_bin_file).read().splitlines()
except AttributeError:
with pkg_resources.path('ObservationSim.Instrument.data.filters', self.filter_type.lower() + "_sub.list") as wave_bin_file:
with pkg_resources.path('observation_sim.instruments.data.filters', self.filter_type.lower() + "_sub.list") as wave_bin_file:
wave_points = open(wave_bin_file).read().splitlines()
for i in range(2, len(wave_points), 2):
blim = max(float(wave_points[i - 2]) * 0.1, bandpass_full.blue_limit)
rlim = min(float(wave_points[i]) * 0.1, bandpass_full.red_limit)
blim = max(float(wave_points[i - 2])
* 0.1, bandpass_full.blue_limit)
rlim = min(float(wave_points[i])
* 0.1, bandpass_full.red_limit)
if blim >= rlim:
continue
bandpass = bandpass_full.truncate(blue_limit=blim, red_limit=rlim)
bandpass = bandpass_full.truncate(
blue_limit=blim, red_limit=rlim)
bandpass_sub_list.append(bandpass)
# print("num of sub-bandpasses for filter#%d(%s) = " % (self.filter_id, self.filter_type), len(bandpass_sub_list), flush=True)
......@@ -111,17 +122,20 @@ class Filter(object):
def getSkyNoise(self, exptime, gain=1.):
return self.sky_background * exptime / gain
def setFilterStrayLightPixel(self,jtime = 2460843., sat_pos = np.array([0,0,0]), pointing_radec = np.array([0,0]), sun_pos = np.array([0,0,0])):
sl = Straylight(jtime=jtime, sat_pos=sat_pos, pointing_radec=pointing_radec,sun_pos=sun_pos)
def setFilterStrayLightPixel(self, jtime=2460843., sat_pos=np.array([0, 0, 0]), pointing_radec=np.array([0, 0]), sun_pos=np.array([0, 0, 0])):
sl = Straylight(jtime=jtime, sat_pos=sat_pos,
pointing_radec=pointing_radec, sun_pos=sun_pos)
if self.filter_type in _util.SPEC_FILTERS:
s_pix, spec = sl.calculateStrayLightGrating(grating = self.filter_type.upper())
if s_pix>0.8:
s_pix, spec = sl.calculateStrayLightGrating(
grating=self.filter_type.upper())
if s_pix > 0.8:
s_pix = 0.8
self.sky_background = s_pix
self.zodical_spec = spec
elif self.filter_type.lower() in [x.lower for x in _util.PHOT_FILTERS]:
s_pix = sl.calculateStrayLightFilter(filter=self.filter_type.lower())
if s_pix>1:
s_pix = sl.calculateStrayLightFilter(
filter=self.filter_type.lower())
if s_pix > 1:
s_pix = 1
self.sky_background = s_pix
self.zodical_spec = None
......@@ -144,6 +158,8 @@ class Filter(object):
full_well = 90000
throughput_file = self.filter_type.lower() + '_throughput.txt'
self.mag_limiting, self.mag_saturation = _util.calculateLimitMag(psf_fwhm=psf_fwhm, pixelSize=pix_scale, throughputFn=throughput_file, readout=5.0, skyFn=skyFn, darknoise=dark_noise, exTime=exptime, fw=full_well)
self.mag_limiting, self.mag_saturation = _util.calculateLimitMag(
psf_fwhm=psf_fwhm, pixelSize=pix_scale, throughputFn=throughput_file, readout=5.0, skyFn=skyFn, darknoise=dark_noise, exTime=exptime, fw=full_well)
print("for filter %s: mag_limiting: %.3f, mag_saturation: %.3f"%(self.filter_type, self.mag_limiting, self.mag_saturation))
print("for filter %s: mag_limiting: %.3f, mag_saturation: %.3f" %
(self.filter_type, self.mag_limiting, self.mag_saturation))
import galsim
import numpy as np
class FilterParam(object):
def __init__(self, filter_dir=None, filter_param=None):
self.param = self._filtParam(filter_param)
......@@ -33,7 +34,8 @@ class FilterParam(object):
"i": [7653.2, 1588.1, 6760.0, 8550.0, 0.4960, 0.212, 16.7, 25.9],
"z": [9600.6, 2490.5, 8240.0, 11000.0, 0.2000, 0.123, 15.7, 25.2],
"y": [10051.0, 1590.6, 9130.0, 11000.0, 0.0960, 0.037, 14.4, 24.4],
"FGS": [5000.0, 8000.0, 3000.0, 11000.0, 0.6500, 0.164, 0., 30.], # [TODO]
# [TODO]
"FGS": [5000.0, 8000.0, 3000.0, 11000.0, 0.6500, 0.164, 0., 30.],
"GU": [0.0, 0.0, 2550.0, 4200.0, 1.0, 0.037, 14.0, 26.0],
"GV": [0.0, 0.0, 4000.0, 6500.0, 1.0, 0.037, 14.0, 26.0],
......@@ -65,9 +67,10 @@ class FilterParam(object):
ifiltn = filtdir+itype+".dat"
iblim = filtParams[itype][2]
irlim = filtParams[itype][3]
ifilt = galsim.Bandpass(ifiltn,wave_type=unit,blue_limit=iblim,red_limit=irlim)
ifilt = galsim.Bandpass(
ifiltn, wave_type=unit, blue_limit=iblim, red_limit=irlim)
wave = ifilt.wave_list
ifilt = ifilt.func(wave)
filts[itype] = np.transpose(np.array([wave*10.0,ifilt]))
filts[itype] = np.transpose(np.array([wave*10.0, ifilt]))
return filtype, filts
......@@ -40,18 +40,6 @@ class FocalPlane(object):
for i in range(1, 31):
self.ignore_chips.append(i)
# if config is not None:
# self.nchip_x = config["nchip_x"]
# self.nchip_y = config["nchip_y"]
# self.npix_tot_x = config["npix_tot_x"]
# self.npix_tot_y = config["npix_tot_y"]
# self.npix_gap_x = config["npix_gap_x"]
# self.npix_gap_y = config["npix_gap_y"]
# if "chipLabelIDs" in config:
# self.chipLabelIDs = config["chipLabelIDs"]
# if "bad_chips" in config:
# self.bad_chips = config["bad_chips"]
# else:
self.nchip_x = 6
self.nchip_y = 5
self.npix_tot_x = 59516
......@@ -95,10 +83,6 @@ class FocalPlane(object):
if (xcen == None) or (ycen == None):
xcen = self.cen_pix_x
ycen = self.cen_pix_y
# dudx = -np.cos(img_rot.rad) * pix_scale
# dudy = -np.sin(img_rot.rad) * pix_scale
# dvdx = -np.sin(img_rot.rad) * pix_scale
# dvdy = +np.cos(img_rot.rad) * pix_scale
dudx = -np.cos(img_rot.rad) * pix_scale
dudy = +np.sin(img_rot.rad) * pix_scale
......
import numpy as np
try:
import importlib.resources as pkg_resources
except ImportError:
# Try backported to PY<37 'importlib_resources'
import importlib_resources as pkg_resources
class Telescope(object):
def __init__(self, param=None, optEffCurve_path=None):
self.diameter = 2.0 # in unit of meter
if param is not None:
self.diameter = param["diameter"]
self.pupil_area = np.pi * (0.5 * self.diameter)**2
if optEffCurve_path is not None:
self.efficiency = self._get_efficiency(optEffCurve_path)
else:
try:
with pkg_resources.files('observation_sim.instruments.data').joinpath('mirror_ccdnote.txt') as optEffCurve_path:
self.efficiency = self._get_efficiency(optEffCurve_path)
except AttributeError:
with pkg_resources.path('observation_sim.instruments.data', 'mirror_ccdnote.txt') as optEffCurve_path:
self.efficiency = self._get_efficiency(optEffCurve_path)
def _get_efficiency(self, effCurve_path):
""" Read in the efficiency of optics
for each band
Parameters:
effCurve_path: the path for efficiency file
Returns:
opticsEff: a dictionary of efficiency (a scalar) for each band
"""
f = open(effCurve_path, 'r')
for _ in range(2):
header = f.readline()
iline = 0
opticsEff = {}
for line in f:
line = line.strip()
columns = line.split()
opticsEff[str(columns[0])] = float(columns[2])
f.close()
return opticsEff
......@@ -2,4 +2,4 @@ from .Telescope import Telescope
from .Filter import Filter
from .FilterParam import FilterParam
from .FocalPlane import FocalPlane
from .Chip import Chip
\ No newline at end of file
from .chip import Chip
import numpy as np
import os
import math
from pylab import *
from scipy import interpolate
try:
import importlib.resources as pkg_resources
except ImportError:
# Try backported to PY<37 'importlib_resources'
import importlib_resources as pkg_resources
VC_A = 2.99792458e+18 # speed of light: A/s
VC_M = 2.99792458e+8 # speed of light: m/s
H_PLANK = 6.626196e-27 # Plank constant: erg s
ALL_FILTERS = ["NUV", "u", "g", "r", "i", "z", "y", "GU", "GV", "GI", "FGS"]
PHOT_FILTERS = ["NUV", "u", "g", 'r', 'i', 'z', 'y', 'FGS']
SPEC_FILTERS = ["GI", "GV", "GU"]
def rotate_conterclockwise(x0, y0, x, y, angle):
"""
Rotate a point counterclockwise by a given angle around a given origin.
The angle should be given in radians.
"""
angle = np.deg2rad(angle)
qx = x0 + np.cos(angle)*(x - x0) - np.sin(angle) * (y - y0)
qy = y0 + np.sin(angle)*(x - x0) + np.cos(angle) * (y - y0)
return qx, qy
def photonEnergy(lambd):
""" The energy of photon at a given wavelength
Parameter:
lambd: the wavelength in unit of Angstrom
Return:
eph: energy of photon in unit of erg
"""
nu = VC_A / lambd
eph = H_PLANK * nu
return eph
def calculateLimitMag(aperture=2.0, psf_fwhm=0.1969, pixelSize=0.074, pmRation=0.8, throughputFn='i_throughput.txt', readout=5.0, skyFn='sky_emiss_hubble_50_50_A.dat', darknoise=0.02, exTime=150, exNum=1, fw=90000):
'''
description:
param {*} aperture: unit m, default 2 m
param {*} psf_fwhm: psf fwhm, default 0.1969"
param {*} pixelSize: pixel size, default 0.074"
param {*} pmRation: the ratio of souce flux in the limit mag calculation
param {*} throughputFn: throuput file name
param {*} readout: unit, e-/pixel
param {*} skyFn: sky sed file name, average of hst, 'sky_emiss_hubble_50_50_A.dat'
param {*} darknoise: unit, e-/pixel/s
param {*} exTime: exposure time one time, default 150s
param {*} exNum: exposure number, defautl 1
param {*} fw, full well value( or saturation value),default 90000e-/pixel
return {*} limit mag and saturation mag
'''
try:
with pkg_resources.files('observation_sim.instruments.data.throughputs').joinpath(throughputFn) as data_file:
throughput_f = np.loadtxt(data_file)
except AttributeError:
with pkg_resources.path('observation_sim.instruments.data.throughputs', throughputFn) as data_file:
throughput_f = np.loadtxt(data_file)
thr_i = interpolate.interp1d(
throughput_f[:, 0]/10, throughput_f[:, 1]) # wavelength in anstrom
f_s = 200
f_e = 1100
delt_f = 0.5
data_num = int((f_e-f_s)/delt_f+1)
eff = np.zeros([data_num, 2])
eff[:, 0] = np.arange(f_s, f_e+delt_f, delt_f)
eff[:, 1] = thr_i(eff[:, 0])
wave = np.arange(f_s, f_e+delt_f, delt_f)
wavey = np.ones(wave.shape[0])
try:
with pkg_resources.files('observation_sim.instruments.data.throughputs').joinpath(skyFn) as data_file:
skydata = np.loadtxt(data_file)
except AttributeError:
with pkg_resources.path('observation_sim.instruments.data.throughputs', skyFn) as data_file:
skydata = np.loadtxt(data_file)
skydatai = interpolate.interp1d(skydata[:, 0]/10, skydata[:, 1]*10)
sky_data = np.zeros([data_num, 2])
sky_data[:, 0] = np.arange(f_s, f_e+delt_f, delt_f)
sky_data[:, 1] = skydatai(sky_data[:, 0])
flux_sky = trapz((sky_data[:, 1])*eff[:, 1], sky_data[:, 0])
skyPix = flux_sky*pixelSize*pixelSize*pi*(aperture*aperture/4)
# limit mag
r_pix = psf_fwhm*0.7618080243778568/pixelSize # radius RE80, pixel
cnum = math.pi * r_pix * r_pix
sn = 5
d = skyPix*exTime*exNum*cnum + darknoise * \
exTime*exNum*cnum+readout*readout*cnum*exNum
a = 1
b = -sn*sn
c = -sn*sn*d
flux = (-b+sqrt(b*b-4*a*c))/(2*a)/pmRation
limitMag = -2.5*log10(flux/(54799275581.04437 * trapz(wavey *
eff[:, 1]/wave, wave, 0.1)*exTime*exNum*pi*(aperture/2)*(aperture/2)))
# saturation mag
from astropy.modeling.models import Gaussian2D
m_size = int(20 * psf_fwhm/pixelSize)
if m_size % 2 == 0:
m_size + 1
m_cen = m_size//2
psf_sigma = psf_fwhm/2.355/pixelSize
gaussShape = Gaussian2D(1, m_cen, m_cen, psf_sigma, psf_sigma)
yp, xp = np.mgrid[0:m_size, 0:m_size]
psfMap = gaussShape(xp, yp)
maxRatio = np.amax(psfMap)/np.sum(psfMap)
# print(maxRatio)
flux_sat = fw/maxRatio*exNum
satMag = -2.5*log10(flux_sat/(54799275581.04437 * trapz(wavey *
eff[:, 1]/wave, wave, 0.1)*exTime*exNum*pi*(aperture/2)*(aperture/2)))
return limitMag, satMag
import galsim
import os
import numpy as np
import pickle
import json
from astropy.table import Table
from numpy.random import Generator, PCG64
from astropy.io import fits
from datetime import datetime
import observation_sim.instruments._util as _util
from observation_sim.instruments.chip import effects
from observation_sim.instruments.FocalPlane import FocalPlane
from observation_sim.config.header import generatePrimaryHeader, generateExtensionHeader
from observation_sim.instruments._util import rotate_conterclockwise
from observation_sim.instruments.chip import chip_utils
from observation_sim.instruments.chip.libCTI.CTI_modeling import CTI_sim
try:
import importlib.resources as pkg_resources
except ImportError:
# Try backported to PY<37 'importlib_resources'
import importlib_resources as pkg_resources
class Chip(FocalPlane):
def __init__(self, chipID, ccdEffCurve_dir=None, CRdata_dir=None, sls_dir=None, config=None, treering_func=None, logger=None):
# Get focal plane (instance of paraent class) info
super().__init__()
self.nsecy = 2
self.nsecx = 8
self.gain_channel = np.ones(self.nsecy * self.nsecx)
self._set_attributes_from_config(config)
self.logger = logger
# A chip ID must be assigned
self.chipID = int(chipID)
self.chip_name = str(chipID).rjust(2, '0')
# Get corresponding filter info
self.filter_id, self.filter_type = self.getChipFilter()
self.survey_type = self._getSurveyType()
if self.filter_type != "FGS":
self._getChipRowCol()
# Set the relavent specs for detectors
try:
with pkg_resources.files('observation_sim.instruments.data.ccd').joinpath("chip_definition.json") as chip_definition:
with open(chip_definition, "r") as f:
chip_dict = json.load(f)[str(self.chipID)]
except AttributeError:
with pkg_resources.path('observation_sim.instruments.data.ccd', "chip_definition.json") as chip_definition:
with open(chip_definition, "r") as f:
chip_dict = json.load(f)[str(self.chipID)]
for key in chip_dict:
setattr(self, key, chip_dict[key])
self.fdModel = None
if self.filter_type == "FGS":
fgs_name = self.chip_name[0:4]
try:
with pkg_resources.files('observation_sim.instruments.data.field_distortion').joinpath("FieldDistModelGlobal_pr4_%s.pickle" % (fgs_name.lower())) as field_distortion:
with open(field_distortion, "rb") as f:
self.fdModel = pickle.load(f)
except AttributeError:
with pkg_resources.path('observation_sim.instruments.data.field_distortion', "FieldDistModelGlobal_pr4_%s.pickle" % (fgs_name.lower())) as field_distortion:
with open(field_distortion, "rb") as f:
self.fdModel = pickle.load(f)
else:
# Get the corresponding field distortion model
try:
with pkg_resources.files('observation_sim.instruments.data.field_distortion').joinpath("FieldDistModel_v2.0.pickle") as field_distortion:
with open(field_distortion, "rb") as f:
self.fdModel = pickle.load(f)
except AttributeError:
with pkg_resources.path('observation_sim.instruments.data.field_distortion', "FieldDistModelGlobal_mainFP_v1.0.pickle") as field_distortion:
with open(field_distortion, "rb") as f:
self.fdModel = pickle.load(f)
# Get boundary (in pix)
self.bound = self.getChipLim()
self.ccdEffCurve_dir = ccdEffCurve_dir
self.CRdata_dir = CRdata_dir
slsconfs = chip_utils.getChipSLSConf(chipID=self.chipID)
if np.size(slsconfs) == 1:
try:
with pkg_resources.files('observation_sim.instruments.data.sls_conf').joinpath(slsconfs) as conf_path:
self.sls_conf = str(conf_path)
except AttributeError:
with pkg_resources.path('observation_sim.instruments.data.sls_conf', slsconfs) as conf_path:
self.sls_conf = str(conf_path)
else:
# self.sls_conf = [os.path.join(self.sls_dir, slsconfs[0]), os.path.join(self.sls_dir, slsconfs[1])]
self.sls_conf = []
try:
with pkg_resources.files('observation_sim.instruments.data.sls_conf').joinpath(slsconfs[0]) as conf_path:
self.sls_conf.append(str(conf_path))
except AttributeError:
with pkg_resources.path('observation_sim.instruments.data.sls_conf', slsconfs[0]) as conf_path:
self.sls_conf.append(str(conf_path))
try:
with pkg_resources.files('observation_sim.instruments.data.sls_conf').joinpath(slsconfs[1]) as conf_path:
self.sls_conf.append(str(conf_path))
except AttributeError:
with pkg_resources.path('observation_sim.instruments.data.sls_conf', slsconfs[1]) as conf_path:
self.sls_conf.append(str(conf_path))
self.effCurve = self._getChipEffCurve(self.filter_type)
self._getCRdata()
# # Define the sensor model
self.sensor = galsim.Sensor()
self.flat_cube = None # for spectroscopic flat field cube simulation
def _set_attributes_from_config(self, config):
# Default setting
self.read_noise = 5.0 # e/pix
self.dark_noise = 0.02 # e/pix/s
self.rotate_angle = 0.
self.overscan = 1000
# Override default values
# for key in ["gain", "bias_level, dark_exptime", "flat_exptime", "readout_time", "full_well", "read_noise", "dark_noise", "overscan"]:
# if key in config["ins_effects"]:
# setattr(self, key, config["ins_effects"][key])
def _getChipRowCol(self):
self.rowID, self.colID = self.getChipRowCol(self.chipID)
def getChipRowCol(self, chipID):
rowID = ((chipID - 1) % 5) + 1
colID = 6 - ((chipID - 1) // 5)
return rowID, colID
def _getSurveyType(self):
if self.filter_type in _util.SPEC_FILTERS:
return "spectroscopic"
elif self.filter_type in _util.PHOT_FILTERS:
return "photometric"
# elif self.filter_type in ["FGS"]:
# return "FGS"
def _getChipEffCurve(self, filter_type):
# CCD efficiency curves
if filter_type in ['NUV', 'u', 'GU']:
filename = 'UV0.txt'
if filter_type in ['g', 'r', 'GV', 'FGS']:
# TODO, need to switch to the right efficiency curvey for FGS CMOS
filename = 'Astro_MB.txt'
if filter_type in ['i', 'z', 'y', 'GI']:
filename = 'Basic_NIR.txt'
try:
with pkg_resources.files('observation_sim.instruments.data.ccd').joinpath(filename) as ccd_path:
table = Table.read(ccd_path, format='ascii')
except AttributeError:
with pkg_resources.path('observation_sim.instruments.data.ccd', filename) as ccd_path:
table = Table.read(ccd_path, format='ascii')
throughput = galsim.LookupTable(
x=table['col1'], f=table['col2'], interpolant='linear')
bandpass = galsim.Bandpass(throughput, wave_type='nm')
return bandpass
def _getCRdata(self):
try:
with pkg_resources.files('observation_sim.instruments.data').joinpath("wfc-cr-attachpixel.dat") as cr_path:
self.attachedSizes = np.loadtxt(cr_path)
except AttributeError:
with pkg_resources.path('observation_sim.instruments.data', "wfc-cr-attachpixel.dat") as cr_path:
self.attachedSizes = np.loadtxt(cr_path)
# def loadSLSFLATCUBE(self, flat_fn='flat_cube.fits'):
# try:
# with pkg_resources.files('observation_sim.instruments.data').joinpath(flat_fn) as data_path:
# flat_fits = fits.open(data_path, ignore_missing_simple=True)
# except AttributeError:
# with pkg_resources.path('observation_sim.instruments.data', flat_fn) as data_path:
# flat_fits = fits.open(data_path, ignore_missing_simple=True)
# fl = len(flat_fits)
# fl_sh = flat_fits[0].data.shape
# assert fl == 4, 'FLAT Field Cube is Not 4 layess!!!!!!!'
# self.flat_cube = np.zeros([fl, fl_sh[0], fl_sh[1]])
# for i in np.arange(0, fl, 1):
# self.flat_cube[i] = flat_fits[i].data
def getChipFilter(self, chipID=None):
"""Return the filter index and type for a given chip #(chipID)
"""
filter_type_list = _util.ALL_FILTERS
if chipID == None:
chipID = self.chipID
# updated configurations
if chipID > 42 or chipID < 1:
raise ValueError("!!! Chip ID: [1,42]")
if chipID in [6, 15, 16, 25]:
filter_type = "y"
if chipID in [11, 20]:
filter_type = "z"
if chipID in [7, 24]:
filter_type = "i"
if chipID in [14, 17]:
filter_type = "u"
if chipID in [9, 22]:
filter_type = "r"
if chipID in [12, 13, 18, 19]:
filter_type = "NUV"
if chipID in [8, 23]:
filter_type = "g"
if chipID in [1, 10, 21, 30]:
filter_type = "GI"
if chipID in [2, 5, 26, 29]:
filter_type = "GV"
if chipID in [3, 4, 27, 28]:
filter_type = "GU"
if chipID in range(31, 43):
filter_type = 'FGS'
filter_id = filter_type_list.index(filter_type)
return filter_id, filter_type
def getChipLim(self, chipID=None):
"""Calculate the edges in pixel for a given CCD chip on the focal plane
NOTE: There are 5*4 CCD chips in the focus plane for photometric / spectroscopic observation.
Parameters:
chipID: int
the index of the chip
Returns:
A galsim BoundsD object
"""
xmin, xmax, ymin, ymax = 1e10, -1e10, 1e10, -1e10
xcen = self.x_cen / self.pix_size
ycen = self.y_cen / self.pix_size
sign_x = [-1., 1., -1., 1.]
sign_y = [-1., -1., 1., 1.]
for i in range(4):
x = xcen + sign_x[i] * self.npix_x / 2.
y = ycen + sign_y[i] * self.npix_y / 2.
x, y = _util.rotate_conterclockwise(
x0=xcen, y0=ycen, x=x, y=y, angle=self.rotate_angle)
xmin, xmax = min(xmin, x), max(xmax, x)
ymin, ymax = min(ymin, y), max(ymax, y)
return galsim.BoundsD(xmin, xmax, ymin, ymax)
def getSkyCoverage(self, wcs):
# print("In getSkyCoverage: xmin = %.3f, xmax = %.3f, ymin = %.3f, ymax = %.3f"%(self.bound.xmin, self.bound.xmax, self.bound.ymin, self.bound.ymax))
return super().getSkyCoverage(wcs, self.bound.xmin, self.bound.xmax, self.bound.ymin, self.bound.ymax)
def getSkyCoverageEnlarged(self, wcs, margin=0.5):
"""The enlarged sky coverage of the chip
"""
margin /= 60.0
bound = self.getSkyCoverage(wcs)
return galsim.BoundsD(bound.xmin - margin, bound.xmax + margin, bound.ymin - margin, bound.ymax + margin)
def isContainObj(self, ra_obj=None, dec_obj=None, x_image=None, y_image=None, wcs=None, margin=1):
# magin in number of pix
if (ra_obj is not None) and (dec_obj is not None):
if wcs is None:
wcs = self.img.wcs
pos_obj = wcs.toImage(galsim.CelestialCoord(
ra=ra_obj*galsim.degrees, dec=dec_obj*galsim.degrees))
x_image, y_image = pos_obj.x, pos_obj.y
elif (x_image is None) or (y_image is None):
raise ValueError(
"Either (ra_obj, dec_obj) or (x_image, y_image) should be given")
xmin, xmax = self.bound.xmin - margin, self.bound.xmax + margin
ymin, ymax = self.bound.ymin - margin, self.bound.ymax + margin
if (x_image - xmin) * (x_image - xmax) > 0.0 or (y_image - ymin) * (y_image - ymax) > 0.0:
return False
return True
def getChipNoise(self, exptime=150.0):
noise = self.dark_noise * exptime + self.read_noise**2
return noise
......@@ -5,8 +5,8 @@ import numpy as np
from astropy.io import fits
from datetime import datetime
from ObservationSim.Instrument.Chip import Effects as effects
from ObservationSim.Config.Header import generatePrimaryHeader, generateExtensionHeader
from observation_sim.instruments.chip import effects
from observation_sim.config.header import generatePrimaryHeader, generateExtensionHeader
try:
import importlib.resources as pkg_resources
......@@ -21,38 +21,65 @@ def log_info(msg, logger=None):
else:
print(msg, flush=True)
def getChipSLSGratingID(chipID):
gratingID = ['','']
if chipID == 1: gratingID = ['GI2', 'GI1']
if chipID == 2: gratingID = ['GV4', 'GV3']
if chipID == 3: gratingID = ['GU2', 'GU1']
if chipID == 4: gratingID = ['GU4', 'GU3']
if chipID == 5: gratingID = ['GV2', 'GV1']
if chipID == 10: gratingID = ['GI4', 'GI3']
if chipID == 21: gratingID = ['GI6', 'GI5']
if chipID == 26: gratingID = ['GV8', 'GV7']
if chipID == 27: gratingID = ['GU6', 'GU5']
if chipID == 28: gratingID = ['GU8', 'GU7']
if chipID == 29: gratingID = ['GV6', 'GV5']
if chipID == 30: gratingID = ['GI8', 'GI7']
gratingID = ['', '']
if chipID == 1:
gratingID = ['GI2', 'GI1']
if chipID == 2:
gratingID = ['GV4', 'GV3']
if chipID == 3:
gratingID = ['GU2', 'GU1']
if chipID == 4:
gratingID = ['GU4', 'GU3']
if chipID == 5:
gratingID = ['GV2', 'GV1']
if chipID == 10:
gratingID = ['GI4', 'GI3']
if chipID == 21:
gratingID = ['GI6', 'GI5']
if chipID == 26:
gratingID = ['GV8', 'GV7']
if chipID == 27:
gratingID = ['GU6', 'GU5']
if chipID == 28:
gratingID = ['GU8', 'GU7']
if chipID == 29:
gratingID = ['GV6', 'GV5']
if chipID == 30:
gratingID = ['GI8', 'GI7']
return gratingID
def getChipSLSConf(chipID):
confFile = ''
if chipID == 1: confFile = ['CSST_GI2.conf', 'CSST_GI1.conf']
if chipID == 2: confFile = ['CSST_GV4.conf', 'CSST_GV3.conf']
if chipID == 3: confFile = ['CSST_GU2.conf', 'CSST_GU1.conf']
if chipID == 4: confFile = ['CSST_GU4.conf', 'CSST_GU3.conf']
if chipID == 5: confFile = ['CSST_GV2.conf', 'CSST_GV1.conf']
if chipID == 10: confFile = ['CSST_GI4.conf', 'CSST_GI3.conf']
if chipID == 21: confFile = ['CSST_GI6.conf', 'CSST_GI5.conf']
if chipID == 26: confFile = ['CSST_GV8.conf', 'CSST_GV7.conf']
if chipID == 27: confFile = ['CSST_GU6.conf', 'CSST_GU5.conf']
if chipID == 28: confFile = ['CSST_GU8.conf', 'CSST_GU7.conf']
if chipID == 29: confFile = ['CSST_GV6.conf', 'CSST_GV5.conf']
if chipID == 30: confFile = ['CSST_GI8.conf', 'CSST_GI7.conf']
if chipID == 1:
confFile = ['CSST_GI2.conf', 'CSST_GI1.conf']
if chipID == 2:
confFile = ['CSST_GV4.conf', 'CSST_GV3.conf']
if chipID == 3:
confFile = ['CSST_GU2.conf', 'CSST_GU1.conf']
if chipID == 4:
confFile = ['CSST_GU4.conf', 'CSST_GU3.conf']
if chipID == 5:
confFile = ['CSST_GV2.conf', 'CSST_GV1.conf']
if chipID == 10:
confFile = ['CSST_GI4.conf', 'CSST_GI3.conf']
if chipID == 21:
confFile = ['CSST_GI6.conf', 'CSST_GI5.conf']
if chipID == 26:
confFile = ['CSST_GV8.conf', 'CSST_GV7.conf']
if chipID == 27:
confFile = ['CSST_GU6.conf', 'CSST_GU5.conf']
if chipID == 28:
confFile = ['CSST_GU8.conf', 'CSST_GU7.conf']
if chipID == 29:
confFile = ['CSST_GV6.conf', 'CSST_GV5.conf']
if chipID == 30:
confFile = ['CSST_GI8.conf', 'CSST_GI7.conf']
return confFile
def generateHeader(chip, pointing, img_type=None, img_type_code=None, project_cycle='9', run_counter='1'):
if (img_type is None) or (img_type_code is None):
img_type = pointing.pointing_type
......@@ -61,12 +88,12 @@ def generateHeader(chip, pointing, img_type=None, img_type_code=None, project_cy
h_prim = generatePrimaryHeader(
xlen=chip.npix_x,
ylen=chip.npix_y,
pointing_id = pointing.obs_id,
pointing_type_code = img_type_code,
pointing_id=pointing.obs_id,
pointing_type_code=img_type_code,
ra=pointing.ra,
dec=pointing.dec,
pixel_scale=chip.pix_scale,
time_pt = pointing.timestamp,
time_pt=pointing.timestamp,
exptime=pointing.exp_time,
im_type=img_type,
sat_pos=[pointing.sat_x, pointing.sat_y, pointing.sat_z],
......@@ -97,6 +124,7 @@ def generateHeader(chip, pointing, img_type=None, img_type_code=None, project_cy
t_shutter_close=pointing.t_shutter_close)
return h_prim, h_ext
def output_fits_image(chip, pointing, img, output_dir, img_type=None, img_type_code=None, project_cycle='9', run_counter='1'):
h_prim, h_ext = generateHeader(
chip=chip,
......@@ -118,6 +146,7 @@ def output_fits_image(chip, pointing, img, output_dir, img_type=None, img_type_c
fname = os.path.join(output_dir, h_prim['FILENAME']+'.fits')
hdu1.writeto(fname, output_verify='ignore', overwrite=True)
def add_sky_background(img, filt, exptime, sky_map=None, tel=None):
# Add sky background
if sky_map is None:
......@@ -135,6 +164,7 @@ def add_sky_background(img, filt, exptime, sky_map=None, tel=None):
img += sky_map
return img, sky_map
def get_flat(img, seed):
flat_img = effects.MakeFlatSmooth(
GSBounds=img.bounds,
......@@ -142,6 +172,7 @@ def get_flat(img, seed):
flat_normal = flat_img / np.mean(flat_img.array)
return flat_img, flat_normal
def add_cosmic_rays(img, chip, exptime=150, seed=0):
cr_map, cr_event_num = effects.produceCR_Map(
xLen=chip.npix_x, yLen=chip.npix_y,
......@@ -157,6 +188,7 @@ def add_cosmic_rays(img, chip, exptime=150, seed=0):
del cr_map
return img, crmap_gsimg, cr_event_num
def add_PRNU(img, chip, seed=0):
prnu_img = effects.PRNU_Img(
xsize=chip.npix_x,
......@@ -166,15 +198,17 @@ def add_PRNU(img, chip, seed=0):
img *= prnu_img
return img, prnu_img
def get_poisson(seed=0, sky_level=0.):
rng_poisson = galsim.BaseDeviate(seed)
poisson_noise = galsim.PoissonNoise(rng_poisson, sky_level=sky_level)
return rng_poisson, poisson_noise
def get_base_img(img, chip, read_noise, readout_time, dark_noise, exptime=150., InputDark=None):
if InputDark == None:
# base_level = read_noise**2 + dark_noise*(exptime+0.5*readout_time)
## base_level = dark_noise*(exptime+0.5*readout_time)
# base_level = dark_noise*(exptime+0.5*readout_time)
base_level = dark_noise*(exptime)
base_img1 = base_level * np.ones_like(img.array)
else:
......@@ -186,36 +220,41 @@ def get_base_img(img, chip, read_noise, readout_time, dark_noise, exptime=150.,
arr = np.broadcast_to(arr, (ny, nx))
base_img2 = np.zeros_like(img.array)
base_img2[:ny, :] = arr
base_img2[ny:, :] = arr[::-1,:]
base_img2[:,:] = base_img2[:,:]*(readout_time/ny)*dark_noise
base_img2[ny:, :] = arr[::-1, :]
base_img2[:, :] = base_img2[:, :]*(readout_time/ny)*dark_noise
return base_img1+base_img2
def add_poisson(img, chip, exptime=150., seed=0, sky_level=0., poisson_noise=None, dark_noise=None, InputDark=None):
if poisson_noise is None:
_, poisson_noise = get_poisson(seed=seed, sky_level=sky_level)
read_noise = chip.read_noise
if dark_noise is None:
dark_noise = chip.dark_noise
base_img = get_base_img(img=img, chip=chip, read_noise=read_noise, readout_time=chip.readout_time, dark_noise=dark_noise, exptime=exptime, InputDark=InputDark)
base_img = get_base_img(img=img, chip=chip, read_noise=read_noise, readout_time=chip.readout_time,
dark_noise=dark_noise, exptime=exptime, InputDark=InputDark)
img += base_img
img.addNoise(poisson_noise)
# img -= read_noise**2
if InputDark != None:
hdu = fits.open(InputDark) ##"Instrument/data/dark/dark_1000s_example_0.fits"
# "Instrument/data/dark/dark_1000s_example_0.fits"
hdu = fits.open(InputDark)
img += hdu[0].data/hdu[0].header['exptime']*exptime
hdu.close()
return img, base_img
def add_brighter_fatter(img):
#Inital dynamic lib
# Inital dynamic lib
try:
with pkg_resources.files('ObservationSim.Instrument.Chip.libBF').joinpath("libmoduleBF.so") as lib_path:
with pkg_resources.files('observation_sim.instruments.chip.libBF').joinpath("libmoduleBF.so") as lib_path:
lib_bf = ctypes.CDLL(lib_path)
except AttributeError:
with pkg_resources.path('ObservationSim.Instrument.Chip.libBF', "libmoduleBF.so") as lib_path:
with pkg_resources.path('observation_sim.instruments.chip.libBF', "libmoduleBF.so") as lib_path:
lib_bf = ctypes.CDLL(lib_path)
lib_bf.addEffects.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.c_int]
lib_bf.addEffects.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.POINTER(
ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.c_int]
# Set bit flag
bit_flag = 1
......@@ -223,16 +262,18 @@ def add_brighter_fatter(img):
nx, ny = img.array.shape
nn = nx * ny
arr_ima= (ctypes.c_float*nn)()
arr_imc= (ctypes.c_float*nn)()
arr_ima = (ctypes.c_float*nn)()
arr_imc = (ctypes.c_float*nn)()
arr_ima[:]= img.array.reshape(nn)
arr_imc[:]= np.zeros(nn)
arr_ima[:] = img.array.reshape(nn)
arr_imc[:] = np.zeros(nn)
lib_bf.addEffects(nx, ny, arr_ima, arr_imc, bit_flag)
img.array[:, :] = np.reshape(arr_imc, [nx, ny])
del arr_ima, arr_imc
return img
"""
def add_inputdark(img, chip, exptime):
fname = "/share/home/weichengliang/CSST_git/test_new_sim/csst-simulation/ObservationSim/Instrument/data/dark/dark_1000s_example_0.fits"
......@@ -244,13 +285,16 @@ def add_inputdark(img, chip, exptime):
del inputdark
return img
"""
def AddPreScan(GSImage, pre1=27, pre2=4, over1=71, over2=80, nsecy = 2, nsecx=8):
img= GSImage.array
def AddPreScan(GSImage, pre1=27, pre2=4, over1=71, over2=80, nsecy=2, nsecx=8):
img = GSImage.array
ny, nx = img.shape
dx = int(nx/nsecx)
dy = int(ny/nsecy)
imgt=np.zeros([int(nsecy*nsecx), int(ny/nsecy+pre2+over2), int(nx/nsecx+pre1+over1)])
imgt = np.zeros(
[int(nsecy*nsecx), int(ny/nsecy+pre2+over2), int(nx/nsecx+pre1+over1)])
for iy in range(nsecy):
for ix in range(nsecx):
if iy % 2 == 0:
......@@ -258,46 +302,59 @@ def AddPreScan(GSImage, pre1=27, pre2=4, over1=71, over2=80, nsecy = 2, nsecx=8)
else:
tx = (nsecx-1)-ix
ty = iy
chunkidx = int(tx+ty*nsecx) #chunk1-[1,2,3,4], chunk2-[5,6,7,8], chunk3-[9,10,11,12], chunk4-[13,14,15,16]
# chunk1-[1,2,3,4], chunk2-[5,6,7,8], chunk3-[9,10,11,12], chunk4-[13,14,15,16]
chunkidx = int(tx+ty*nsecx)
imgtemp = np.zeros([int(ny/nsecy+pre2+over2), int(nx/nsecx+pre1+over1)])
imgtemp = np.zeros(
[int(ny/nsecy+pre2+over2), int(nx/nsecx+pre1+over1)])
if int(chunkidx/4) == 0:
imgtemp[pre2:pre2+dy, pre1:pre1+dx] = img[iy*dy:(iy+1)*dy, ix*dx:(ix+1)*dx]
imgtemp[pre2:pre2+dy, pre1:pre1 +
dx] = img[iy*dy:(iy+1)*dy, ix*dx:(ix+1)*dx]
imgt[chunkidx, :, :] = imgtemp
if int(chunkidx/4) == 1:
imgtemp[pre2:pre2+dy, over1:over1+dx] = img[iy*dy:(iy+1)*dy, ix*dx:(ix+1)*dx]
imgt[chunkidx, :, :] = imgtemp #[:, ::-1]
imgtemp[pre2:pre2+dy, over1:over1 +
dx] = img[iy*dy:(iy+1)*dy, ix*dx:(ix+1)*dx]
imgt[chunkidx, :, :] = imgtemp # [:, ::-1]
if int(chunkidx/4) == 2:
imgtemp[over2:over2+dy, over1:over1+dx] = img[iy*dy:(iy+1)*dy, ix*dx:(ix+1)*dx]
imgt[chunkidx, :, :] = imgtemp #[::-1, ::-1]
imgtemp[over2:over2+dy, over1:over1 +
dx] = img[iy*dy:(iy+1)*dy, ix*dx:(ix+1)*dx]
imgt[chunkidx, :, :] = imgtemp # [::-1, ::-1]
if int(chunkidx/4) == 3:
imgtemp[over2:over2+dy, pre1:pre1+dx] = img[iy*dy:(iy+1)*dy, ix*dx:(ix+1)*dx]
imgt[chunkidx, :, :] = imgtemp #[::-1, :]
imgtemp[over2:over2+dy, pre1:pre1 +
dx] = img[iy*dy:(iy+1)*dy, ix*dx:(ix+1)*dx]
imgt[chunkidx, :, :] = imgtemp # [::-1, :]
imgtx1 = np.hstack(imgt[:nsecx:, :, :]) #hstack chunk(1,2)-[1,2,3,4,5,6,7,8]
imgtx2 = np.hstack(imgt[:(nsecx-1):-1, :, :]) #hstack chunk(4,3)-[16,15,14,13,12,11,,10,9]
# hstack chunk(1,2)-[1,2,3,4,5,6,7,8]
imgtx1 = np.hstack(imgt[:nsecx:, :, :])
# hstack chunk(4,3)-[16,15,14,13,12,11,,10,9]
imgtx2 = np.hstack(imgt[:(nsecx-1):-1, :, :])
newimg = galsim.Image(int(nx+(pre1+over1)*nsecx), int(ny+(pre2+over2)*nsecy), init_value=0)
newimg.array[:, :] = np.concatenate([imgtx1, imgtx2]) #vstack chunk(1,2) & chunk(4,3)
newimg = galsim.Image(int(nx+(pre1+over1)*nsecx),
int(ny+(pre2+over2)*nsecy), init_value=0)
newimg.array[:, :] = np.concatenate(
[imgtx1, imgtx2]) # vstack chunk(1,2) & chunk(4,3)
newimg.wcs = GSImage.wcs
return newimg
def AddPreScanFO(GSImage, pre1=27, pre2=4, over1=71, over2=80, nsecy = 1, nsecx=16):
img= GSImage.array
def AddPreScanFO(GSImage, pre1=27, pre2=4, over1=71, over2=80, nsecy=1, nsecx=16):
img = GSImage.array
ny, nx = img.shape
dx = int(nx/nsecx)
dy = int(ny/nsecy)
newimg = galsim.Image(int(nx+(pre1+over1)*nsecx), int(ny+(pre2+over2)*nsecy), init_value=0)
newimg = galsim.Image(int(nx+(pre1+over1)*nsecx),
int(ny+(pre2+over2)*nsecy), init_value=0)
for ix in range(nsecx):
newimg.array[pre2:pre2+dy, pre1+ix*(dx+pre1+over1):pre1+dx+ix*(dx+pre1+over1)] = img[0:dy, 0+ix*dx:dx+ix*dx]
newimg.array[pre2:pre2+dy, pre1+ix *
(dx+pre1+over1):pre1+dx+ix*(dx+pre1+over1)] = img[0:dy, 0+ix*dx:dx+ix*dx]
newimg.wcs = GSImage.wcs
return newimg
def formatOutput(GSImage, nsecy = 2, nsecx=8):
def formatOutput(GSImage, nsecy=2, nsecx=8):
img = GSImage.array
ny, nx = img.shape
dx = int(nx/nsecx)
......@@ -321,16 +378,17 @@ def formatOutput(GSImage, nsecy = 2, nsecx=8):
if int(chunkidx/4) == 3:
imgt[chunkidx, :, :] = img[iy*dy:(iy+1)*dy, ix*dx:(ix+1)*dx]
imgttx0 = np.hstack(imgt[ 0:4:, :, :])
imgttx1 = np.hstack(imgt[ 4:8:, :, ::-1])
imgttx0 = np.hstack(imgt[0:4:, :, :])
imgttx1 = np.hstack(imgt[4:8:, :, ::-1])
imgttx2 = np.hstack(imgt[8:12:, ::-1, ::-1])
imgttx3 = np.hstack(imgt[12:16:,::-1, :])
imgttx3 = np.hstack(imgt[12:16:, ::-1, :])
newimg = galsim.Image(int(dx*nsecx*nsecy), dy, init_value=0)
newimg.array[:, :] = np.hstack([imgttx0, imgttx1, imgttx2, imgttx3])
return newimg
def formatRevert(GSImage, nsecy = 1, nsecx=16):
def formatRevert(GSImage, nsecy=1, nsecx=16):
img = GSImage.array
ny, nx = img.shape
dx = int(nx/nsecx)
......@@ -338,17 +396,20 @@ def formatRevert(GSImage, nsecy = 1, nsecx=16):
newimg = galsim.Image(int(dx*8), int(dy*2), init_value=0)
for ix in range(0,4):
for ix in range(0, 4):
tx = ix
newimg.array[0:dy, 0+tx*dx:dx+tx*dx] = img[:, 0+ix*dx:dx+ix*dx]
for ix in range(4,8):
for ix in range(4, 8):
tx = ix
newimg.array[0:dy, 0+tx*dx:dx+tx*dx] = img[:, 0+ix*dx:dx+ix*dx][:, ::-1]
for ix in range(8,12):
newimg.array[0:dy, 0+tx*dx:dx+tx *
dx] = img[:, 0+ix*dx:dx+ix*dx][:, ::-1]
for ix in range(8, 12):
tx = 7-(ix-8)
newimg.array[0+dy:dy+dy, 0+tx*dx:dx+tx*dx] = img[:, 0+ix*dx:dx+ix*dx][::-1, ::-1]
for ix in range(12,16):
newimg.array[0+dy:dy+dy, 0+tx*dx:dx+tx *
dx] = img[:, 0+ix*dx:dx+ix*dx][::-1, ::-1]
for ix in range(12, 16):
tx = 7-(ix-8)
newimg.array[0+dy:dy+dy, 0+tx*dx:dx+tx*dx] = img[:, 0+ix*dx:dx+ix*dx][::-1, :]
newimg.array[0+dy:dy+dy, 0+tx*dx:dx+tx *
dx] = img[:, 0+ix*dx:dx+ix*dx][::-1, :]
return newimg
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