Commit 883b7a77 authored by Fang Yuedong's avatar Fang Yuedong
Browse files

bug fixed

parent e82a5dcc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ def ConfigDir(config, work_dir=None, data_dir=None):
    path_dict["cat_dir"] = os.path.join(path_dict["data_dir"], config["input_path"]["cat_dir"])
    # PSF data directory
    path_dict["psf_dir"] = os.path.join(path_dict["data_dir"], config["psf_setting"]["psf_dir"])
    path_dict["fd_path"] = os.path.join(path_dict["data_dir"], config["psf_setting"]["fd_path"])
    # SED catalog directory
    # TODO: SED_dir is deprecated
    path_dict["SED_dir"] = os.path.join(path_dict["data_dir"], "imageSims/Catalog/SEDObject")
+1 −1
Original line number Diff line number Diff line
@@ -65,7 +65,7 @@ class Chip(FocalPlane):
        self._getCRdata()

        # Define the sensor
        if config["ins_effects"]["bright_fatter"] == True:
        if config["ins_effects"]["bright_fatter"] == True and self.survey_type == "photometric":
            self.sensor = galsim.SiliconSensor(strength=config["ins_effects"]["df_strength"], treering_func=treering_func)
        else:
            self.sensor = galsim.Sensor()
+3 −3
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@ class Observation(object):

        # if we want to apply field distortion?
        if self.config["ins_effects"]["field_dist"] == True:
            self.fd_model = FieldDistortion()
            self.fd_model = FieldDistortion(fdModel_path=self.path_dict["fd_path"])
        else:
            self.fd_model = None

@@ -59,7 +59,7 @@ class Observation(object):
        if self.config["psf_setting"]["psf_model"] == "Gauss":
            psf_model = PSFGauss(chip=chip)
        elif self.config["psf_setting"]["psf_model"] == "Interp":
            psf_model = PSFInterp(chip=chip)
            psf_model = PSFInterp(chip=chip, PSF_data_file=self.path_dict["psf_dir"])
        else:
            print("unrecognized PSF model type!!", flush=True)

@@ -78,7 +78,7 @@ class Observation(object):
        if chip.survey_type == "photometric":
            sky_map = None
        elif chip.survey_type == "spectroscopic":
            sky_map = calculateSkyMap_split_g(xLen=chip.npix_x, yLen=chip.npix_y, blueLimit=filt.blue_limit, redLimit=filt.red_limit, skyfn=path_dict["sky_file"], conf=chip.sls_conf, pixelSize=chip.pix_scale, isAlongY=0)
            sky_map = calculateSkyMap_split_g(xLen=chip.npix_x, yLen=chip.npix_y, blueLimit=filt.blue_limit, redLimit=filt.red_limit, skyfn=self.path_dict["sky_file"], conf=chip.sls_conf, pixelSize=chip.pix_scale, isAlongY=0)

        if pointing_type == 'MS':
            # Load catalogues and templates
+0 −263
Original line number Diff line number Diff line
import galsim
import numpy as np

import os
import time
import copy
# import psfConfig as mypy
import PSF.PSFInterp.psfConfig as mypy
npsf = 900  #***# 30*30

LOG_DEBUG = False #***#

class PSFInterp(object):
    # def __init__(self, PSF_data=None, params=None, PSF_data_file=None):
    def __init__(self, chip, PSF_data=None, PSF_data_file=None, sigSpin=0., psfRa=0.15):
        """
        The PSF data matrix is either given by a object parameter or read in from a file.
        Parameters:
            PSF_data: The PSF data matrix object
            params: Other parameters?
            PSF_data_file: The file for PSF data matrix (optional).
        """
        if LOG_DEBUG:
            print('===================================================')
            print('DEBUG: psf module for csstSim ' \
                  +time.strftime("(%Y-%m-%d %H:%M:%S)", time.localtime()), flush=True)
            print('===================================================')

        self.sigSpin = sigSpin
        self.sigGauss = psfRa # 80% light radius

        # iccd = 1 #***#
        # iccd = chip.chipID
        iccd = int(chip.getChipLabel(chipID=chip.chipID))
        if PSF_data_file == None:
            PSF_data_file = '/data/simudata/CSSOSDataProductsSims/data/csstPSFdata/CSSOS_psf_ciomp_30X30'
        
        self.nwave = self._getPSFwave(iccd, PSF_data_file)
        if LOG_DEBUG:
            print('nwave-{:} on ccd-{:}::'.format(self.nwave, iccd), flush=True)
        self.PSF_data = self._loadPSF(iccd, PSF_data_file)
        self.itpPSF_data = self._preprocessPSF()
        
        if LOG_DEBUG:
            print('self.PSF_data & self.itpPSF_data ... ok', flush=True)
        
        if LOG_DEBUG:
            print('Preparing self.[psfMat,cen_col,cen_row] for psfMaker ... ', end='', flush=True)
        
        ngy, ngx    = self.itpPSF_data[0][0]['psfMat'].shape
        self.psfMat = np.zeros([self.nwave, npsf, ngy, ngx])
        self.cen_col= np.zeros([self.nwave, npsf])
        self.cen_row= np.zeros([self.nwave, npsf])
        for iwave in range(self.nwave):
            for ipsf in range(npsf):
                self.psfMat[iwave, ipsf, :, :] = self.itpPSF_data[iwave][ipsf]['psfMat']
                self.cen_col[iwave, ipsf] = self.itpPSF_data[iwave][ipsf]['imgMaxPosx_ccd']
                self.cen_row[iwave, ipsf] = self.itpPSF_data[iwave][ipsf]['imgMaxPosy_ccd']
        
        if LOG_DEBUG:
            print('ok', flush=True)
        

    def _getPSFwave(self, iccd, PSF_data_file):
        """
        Get # of sampling waves on iccd
        Parameters:
            iccd: The chip of i-th ccd
            PSF_data_file: The file for PSF data matrix
        Returns:
            nwave: The number of the sampling waves
        """
        strs = os.listdir(PSF_data_file + '/ccd{:}'.format(iccd))
        nwave = 0
        for _ in strs:
            if 'wave_' in _:
                nwave += 1
        return nwave



    def _loadPSF(self, iccd, PSF_data_file):
        """
        load psf-matrix on iccd
        Parameters:
            iccd: The chip of i-th ccd
            PSF_data_file: The file for PSF data matrix
        Returns:
            psfSet: The matrix of the csst-psf
        """
        psfSet = []
        for ii in range(self.nwave):
            iwave = ii+1
            if LOG_DEBUG:
                print('self._loadPSF: iwave::', iwave, flush=True)
            psfWave = []
            for jj in range(npsf):
                ipsf = jj+1
                psfInfo = mypy.LoadPSF(iccd, iwave, ipsf, PSF_data_file, CalcPSFsize=False, InputMaxPixelPos=True)
                psfWave.append(psfInfo)
            psfSet.append(psfWave)
        if LOG_DEBUG:
            print('psfSet has been loaded:', flush=True)
            print('psfSet[iwave][ipsf][keys]:', psfSet[0][0].keys(), flush=True)
        return psfSet



    def _preprocessPSF(self):
        """
        Preprocessing psf-matrix
        Parameters:
        
        Returns:
            itpPSF_data: The matrix of the preprocessed csst-psf
        """
        itpPSF_data = copy.deepcopy(self.PSF_data)
        for iwave in range(self.nwave):
            for ipsf in range(npsf):
                psfMat = self.PSF_data[iwave][ipsf]['psfMat']
                psfMatX= mypy.psfCentering(psfMat, CenteringMode=1)
                itpPSF_data[iwave][ipsf]['psfMat'] = psfMatX
        return itpPSF_data



    def _findWave(self, bandpass):
        for iwave in range(self.nwave):
            bandwave = self.PSF_data[iwave][0]['wavelength']
            if bandpass.blue_limit < bandwave and bandwave < bandpass.red_limit:
                return iwave
        return -1
 


    def get_PSF(self, chip, pos_img, bandpass, pixSize=0.037, galsimGSObject=True):
        """
        Get the PSF at a given image position

        Parameters:
            chip: A 'Chip' object representing the chip we want to extract PSF from.
            pos_img: A 'galsim.Position' object representing the image position.
            bandpass: A 'galsim.Bandpass' object representing the wavelength range.
            pixSize: The pixels size of psf matrix
        Returns:
            PSF: A 'galsim.GSObject'.
        """
        # iccd  = 1  #***# #chip.chipID
        # iccd = chip.chipID
        iccd = int(chip.getChipLabel(chipID=chip.chipID))
        # iwave = 1  #***# #self.findWave(bandpass)
        iwave = self._findWave(bandpass)
        if iwave == -1:
            print("!!!PSF bandpass does not match.")
            exit()
        PSFMat = self.psfMat[iwave]
        cen_col= self.cen_col[iwave]
        cen_row= self.cen_row[iwave]
        # print('shape:', cen_col.shape)
        # px = pos_img[0]
        # py = pos_img[1]
        px = pos_img.x
        py = pos_img.y
        imPSF = mypy.psfMaker_IDW(px, py, PSFMat, cen_col, cen_row, IDWindex=2, OnlyNeighbors=True)
        if galsimGSObject:
            img = galsim.ImageF(imPSF, scale=pixSize)
            self.psf = galsim.InterpolatedImage(img)
            dx = px - chip.cen_pix_x
            dy = py - chip.cen_pix_y
            return self.PSFspin(x=dx, y=dy)
        return imPSF

    def PSFspin(self, x, y):
        """
        The PSF profile at a given image position relative to the axis center

        Parameters:
        theta : spin angles in a given exposure in unit of [arcsecond]
        dx, dy: relative position to the axis center in unit of [pixels]

        Return:
        Spinned PSF: g1, g2 and axis ratio 'a/b'
        """
        a2Rad = np.pi/(60.0*60.0*180.0)
        
        ff = self.sigGauss * 0.107 * (1000.0/10.0) # in unit of [pixels]
        rc = np.sqrt(x*x + y*y)
        cpix = rc*(self.sigSpin*a2Rad)

        beta = (np.arctan2(y,x) + np.pi/2)
        ell = cpix**2/(2.0*ff**2+cpix**2)
        #ell *= 10.0
        qr = np.sqrt((1.0+ell)/(1.0-ell))

        #psfShape = galsim.Shear(e=ell, beta=beta)
        #g1, g2 = psfShape.g1, psfShape.g2
        #qr = np.sqrt((1.0+ell)/(1.0-ell))

        #return ell, beta, qr
        PSFshear = galsim.Shear(e=ell, beta=beta*galsim.radians)
        return self.psf.shear(PSFshear), PSFshear



if __name__ == '__main__':
    psfPath = '/data/simudata/CSSOSDataProductsSims/data/csstPSFdata/CSSOS_psf_ciomp_30X30'
    #psfPath = '/data/simudata/CSSOSDataProductsSims/data/csstPSFdata/CSSOS_psf_ciomp'
    psfCSST = PSFInterp(PSF_data_file = psfPath)
    iwave= 1
    ipsf = 665
    pos_img = [psfCSST.cen_col[iwave, ipsf], psfCSST.cen_row[iwave, ipsf]]
    img = psfCSST.get_PSF(1, pos_img, iwave, galsimGSObject=False)
    
    #plot check-1
    import matplotlib.pyplot as plt
    fig = plt.figure(figsize=(18,5))
    ax = plt.subplot(1,3,1)
    plt.imshow(img)
    plt.colorbar()
    ax = plt.subplot(1,3,2)
    imgx = psfCSST.itpPSF_data[iwave][ipsf]['psfMat']
    imgx/= np.sum(imgx)
    plt.imshow(imgx)
    plt.colorbar()
    ax = plt.subplot(1,3,3)
    plt.imshow(img - imgx)
    plt.colorbar()
    plt.savefig('test/figs/test.jpg')

    #plot check-2: 注意图像坐标和全局坐标
    fig = plt.figure(figsize=(8,8), dpi = 200)
    img = psfCSST.PSF_data[iwave][ipsf]['psfMat']
    npix = img.shape[0]
    dng  = 105
    imgg = img[dng:-dng, dng:-dng]
    plt.imshow(imgg)
    imgX = psfCSST.PSF_data[iwave][ipsf]['image_x']  #in mm
    imgY = psfCSST.PSF_data[iwave][ipsf]['image_y']  #in mm
    deltX= psfCSST.PSF_data[iwave][ipsf]['centroid_x'] #in mm
    deltY= psfCSST.PSF_data[iwave][ipsf]['centroid_y'] #in mm
    maxX = psfCSST.PSF_data[iwave][ipsf]['max_x']
    maxY = psfCSST.PSF_data[iwave][ipsf]['max_y']
    cenPix_X = npix/2 + deltX/0.005
    cenPix_Y = npix/2 - deltY/0.005
    maxPix_X = npix/2 + maxX/0.005-1
    maxPix_Y = npix/2 - maxY/0.005-1
    plt.plot([cenPix_X-dng],[cenPix_Y-dng], 'rx', ms = 20)
    plt.plot([maxPix_X-dng],[maxPix_Y-dng], 'b+', ms=20)

    from scipy import ndimage
    y, x = ndimage.center_of_mass(img)
    plt.plot([x-dng],[y-dng], 'rx', ms = 10, mew=2)
    x, y = mypy.findMaxPix(img)
    plt.plot([x-dng],[y-dng], 'b+', ms = 10, mew=2)
    plt.savefig('test/figs/test.jpg')







+0 −236
Original line number Diff line number Diff line
import sys
from itertools import islice

import numpy as np
import matplotlib.pyplot as plt

import scipy.io
#from scipy.io import loadmat

from scipy import ndimage

import ctypes
import galsim

from PSF.PSFInterp.PSFUtil import *


###加载PSF信息###
def LoadPSF(iccd, iwave, ipsf, psfPath, psfSampleSize=5, InputMaxPixelPos=False, PSFCentroidWgt=False):
    """
    load psf informations from psf matrix.

    Parameters:
        iccd (int): ccd number [1,30].
        iwave(int): wave-index [1,4].
        ipsf (int): psf number [1, 100].
        psfPath (int): path to psf matrix
        psfSampleSize (float-optional): psf size in microns.
        InputMaxPixelPos(bool-optional): only True for 30*30 psf-matrix 
    Returns:
        psfInfo (dirctionary)
    """
    if iccd not in np.linspace(1, 30, 30, dtype='int'):
        print('Error - iccd should be in [1, 30].')
        sys.exit()
    if iwave not in np.linspace(1, 4, 4, dtype='int'):
        print('Error - iwave should be in [1, 4].')
        sys.exit()
    if ipsf not in np.linspace(1, 900, 900, dtype='int'):
        print('Error - ipsf should be in [1, 900].')
        sys.exit()

    psfInfo = {}
    fpath = psfPath +'/' +'ccd{:}'.format(iccd) +'/' + 'wave_{:}'.format(iwave)

    #获取ipsf矩阵
    if not PSFCentroidWgt:
        ##读取PSF原数据
        fpathMat = fpath +'/' +'5_psf_array' +'/' +'psf_{:}.mat'.format(ipsf)
        data = scipy.io.loadmat(fpathMat)
        psfInfo['psfMat'] = data['psf']
    if PSFCentroidWgt:
        ##读取PSFCentroidWgt
        ffpath = psfPath +'_proc/' +'ccd{:}'.format(iccd) +'/' + 'wave_{:}'.format(iwave)
        ffpathMat = ffpath +'/' +'5_psf_array' +'/' +'psf_{:}_centroidWgt.mat'.format(ipsf)
        data = scipy.io.loadmat(ffpathMat)
        psfInfo['psfMat'] = data['psf']


    #获取ipsf波长
    fpathWave = fpath +'/' +'1_wavelength.txt'
    f = open(fpathWave, 'r')
    wavelength = np.float(f.readline())
    f.close()
    psfInfo['wavelength'] = wavelength

    #获取ipsf位置
    fpathCoordinate = fpath +'/' +'4_PSF_coordinate.txt'
    f = open(fpathCoordinate, 'r')
    header = f.readline()
    for line in islice(f, ipsf-1, ipsf):
        line = line.strip()
        columns = line.split()
    f.close()
    icol = 0
    psfInfo['field_x'] = float(columns[icol])    #deg, 视场采样位置
    icol+= 1
    psfInfo['field_y'] = float(columns[icol])    #deg
    icol+= 1
    psfInfo['centroid_x'] = float(columns[icol]) #mm, psf质心相对主光线的偏移量
    icol+= 1
    psfInfo['centroid_y'] = float(columns[icol]) #mm
    icol+= 1
    if InputMaxPixelPos == True:
        psfInfo['max_x'] = float(columns[icol])  #mm, max pixel postion
        icol+= 1
        psfInfo['max_y'] = float(columns[icol])  #mm
        icol+= 1
    psfInfo['image_x'] = float(columns[icol])    #mm, 主光线位置
    icol+= 1
    psfInfo['image_y'] = float(columns[icol])    #mm

    nrows, ncols = psfInfo['psfMat'].shape
    psfPos   = psfPixelLayout(nrows, ncols, psfInfo['image_y'], psfInfo['image_x'], pixSizeInMicrons=5.0)
    imgMaxPix_x, imgMaxPix_y = findMaxPix(psfInfo['psfMat'])
    psfInfo['imgMaxPosx_ccd'] = psfPos[0, imgMaxPix_y, imgMaxPix_x] #cx, psf最大值位置, in mm
    psfInfo['imgMaxPosy_ccd'] = psfPos[1, imgMaxPix_y, imgMaxPix_x] #cy

    
    if PSFCentroidWgt:
        #if ipsf == 1:
            #print('Check:', psfInfo['centroid_x'], psfInfo['centroid_y'], data['cx'][0][0], data['cy'][0][0])
        psfInfo['centroid_x'] = data['cx'][0][0] #mm, psfCentroidWgt质心相对主光线的偏移量
        psfInfo['centroid_y'] = data['cy'][0][0] #mm
    return psfInfo


###加载PSF矩阵信息###
def LoadPSFset(iccd, iwave, npsf, psfPath, psfSampleSize=5, InputMaxPixelPos=False, PSFCentroidWgt=False):
    """
    load psfSet for interpolation

    Parameters:
        iccd, iwave, psfPath: # of ccd/wave and path for psfs
        npsf: 100 or 900 for different psf matrixes

    Returns:
        PSFMat (numpy.array): images
        cen_col, cen_row (numpy.array, numpy.array): position of psf center in the view field
    """
    psfSet = []
    for ipsf in range(1, npsf+1):
        psfInfo = LoadPSF(iccd, iwave, ipsf, psfPath, InputMaxPixelPos=InputMaxPixelPos, PSFCentroidWgt=PSFCentroidWgt)
        psfSet.append(psfInfo)

    ngy, ngx = psfSet[0]['psfMat'].shape
    PSFMat = np.zeros([npsf, ngy, ngx])
    cen_col= np.zeros(npsf)
    cen_row= np.zeros(npsf)
    FieldPos = False
    for ipsf in range(npsf):
        iPSFMat = psfSet[ipsf]['psfMat']
        PSFMat[ipsf, :, :] = psfTailor(iPSFMat, apSizeInArcsec=2.5)

        if FieldPos == True:
            cen_col[ipsf] = psfSet[ipsf]['field_x'] #cx
            cen_row[ipsf] = psfSet[ipsf]['field_y'] #cy
        if FieldPos == False:
            cen_col[ipsf] = psfSet[ipsf]['image_x'] + psfSet[ipsf]['centroid_x'] #cx 
            cen_row[ipsf] = psfSet[ipsf]['image_y'] + psfSet[ipsf]['centroid_y'] #cy
            #cen_col[ipsf] = psfSet[ipsf]['imgMaxPosx_ccd'] #cx --- to be updated
            #cen_row[ipsf] = psfSet[ipsf]['imgMaxPosy_ccd'] #cy
            #cen_col[ipsf] = psfSet[ipsf]['image_x']
            #cen_row[ipsf] = psfSet[ipsf]['image_y']
    return psfSet, PSFMat, cen_col, cen_row


###插值PSF图像-IDW方法###
def psfMaker_IDW(px, py, PSFMat, cen_col, cen_row, IDWindex=2, OnlyNeighbors=True, hoc=None, hoclist=None, PSFCentroidWgt=False):
    """
    psf interpolation by IDW

    Parameters:
        px, py (float, float): position of the target
        PSFMat (numpy.array): image
        cen_col, cen_row (numpy.array, numpy.array): potions of the psf centers
        IDWindex (int-optional): the power index of IDW
        OnlyNeighbors (bool-optional): only neighbors are used for psf interpolation

    Returns:
        psfMaker (numpy.array)
    """
    minimum_psf_weight = 1e-8
    ref_col = px
    ref_row = py

    ngy, ngx = PSFMat[0, :, :].shape
    npsf = PSFMat[:, :, :].shape[0]
    psfWeight = np.zeros([npsf])

    if OnlyNeighbors == True:
        if hoc is None:
            neigh = findNeighbors(px, py, cen_col, cen_row, dr=5., dn=4, OnlyDistance=False)
        if hoc is not None:
            #hoc,hoclist = findNeighbors_hoclist(cen_col, cen_row)
            neigh = findNeighbors_hoclist(cen_col, cen_row, tx=px,ty=py, dn=4, hoc=hoc, hoclist=hoclist)

        #print("neigh:", neigh)
        neighFlag = np.zeros(npsf)
        neighFlag[neigh] = 1

    for ipsf in range(npsf):
        if OnlyNeighbors == True:
            if neighFlag[ipsf] != 1:
                continue

        dist = np.sqrt((ref_col - cen_col[ipsf])**2 + (ref_row - cen_row[ipsf])**2)
        if IDWindex == 1:
            psfWeight[ipsf] = dist
        if IDWindex == 2:
            psfWeight[ipsf] = dist**2
        if IDWindex == 3:
            psfWeight[ipsf] = dist**3
        if IDWindex == 4:
            psfWeight[ipsf] = dist**4
        psfWeight[ipsf] = max(psfWeight[ipsf], minimum_psf_weight)
        psfWeight[ipsf] = 1./psfWeight[ipsf]
    psfWeight /= np.sum(psfWeight)

    psfMaker  = np.zeros((ngy, ngx), dtype='float64')
    for ipsf in range(npsf):
        if OnlyNeighbors == True:
            if neighFlag[ipsf] != 1:
                continue

        iPSFMat = PSFMat[ipsf, :, :].copy()
        #if not PSFCentroidWgt:
        #    iPSFMat = psfCentering(iPSFMat, CenteringMode=2)
            #iPSFMat = psfCentering_FFT(iPSFMat)
        #if PSFCentroidWgt:
            
        ipsfWeight = psfWeight[ipsf]
        psfMaker += iPSFMat * ipsfWeight
        #print("ipsf, ipsfWeight:", ipsf, ipsfWeight)
    psfMaker /= np.nansum(psfMaker)

    return psfMaker



###TEST###
if __name__ == '__main__':
    iccd = 1
    iwave= 1
    ipsf = 1 
    npsf = 100
    psfPath = '/data/simudata/CSSOSDataProductsSims/data/csstPSFdata/CSSOS_psf_ciomp'

    a, b, c, d = LoadPSFset(iccd, iwave, npsf, psfPath, InputMaxPixelPos=False)
    psfSet = a

    print('psfSet has been loaded.')
    print('Usage: psfSet[i][keys]')
    print('psfSet.keys:', psfSet[0].keys())
    print(c[0:10])
    print(d[0:10])
Loading