diff --git a/ObservationSim/Config/Header/ImageHeader_1.py b/ObservationSim/Config/Header/ImageHeader_1.py
deleted file mode 100644
index a4fc27088c9815699d58670bf5707dfd763f196d..0000000000000000000000000000000000000000
--- a/ObservationSim/Config/Header/ImageHeader_1.py
+++ /dev/null
@@ -1,434 +0,0 @@
-"""
-generate image header
-"""
-import numpy as np
-
-from astropy.io import fits
-import astropy.wcs as pywcs
-
-from scipy import math
-import random
-
-import os
-import sys
-
-def chara2digit(char):
-    """ Function to judge and convert characters to digitals
-
-    Parameters
-    ----------
-
-    """
-
-    try:
-        float(char) # for int, long and float
-    except ValueError:
-        pass
-        return char
-    else:
-        data = float(char)
-        return data
-
-
-def read_header_parameter(filename='global_header.param'):
-    """ Function to read the header parameters
-
-    Parameters
-    ----------
-
-    """
-
-    name = []
-    value = []
-    description = []
-    for line in open(filename):
-        line = line.strip("\n")
-        arr = line.split('|')
-#        csvReader = csv.reader(csvDataFile)
-#        for arr in csvReader:
-        name.append(arr[0])
-        value.append(chara2digit(arr[1]))
-        description.append(arr[2])
-
-#    print(value)
-    return name, value, description
-
-def rotate_CD_matrix(cd, pa_aper):
-    """Rotate CD matrix
-    
-    Parameters
-    ----------
-    cd: (2,2) array
-        CD matrix
-    
-    pa_aper: float
-        Position angle, in degrees E from N, of y axis of the detector
-    
-    Returns
-    -------
-    cd_rot: (2,2) array
-        Rotated CD matrix
-    
-    Comments
-    --------
-    `astropy.wcs.WCS.rotateCD` doesn't work for non-square pixels in that it
-    doesn't preserve the pixel scale!  The bug seems to come from the fact
-    that `rotateCD` assumes a transposed version of its own CD matrix.
-    
-    """
-    rad = np.deg2rad(-pa_aper)
-    mat = np.zeros((2,2))
-    mat[0,:] = np.array([np.cos(rad),-np.sin(rad)])
-    mat[1,:] = np.array([np.sin(rad),np.cos(rad)])
-    cd_rot = np.dot(mat, cd)
-    return cd_rot
-
-
-def Header_extention(xlen = 9232, ylen = 9216, gain = 1.0, readout = 5.0, dark = 0.02,saturation=90000, row_num = 1, col_num = 1):
-
-    """ Creat an image frame for CCST with multiple extensions
-
-    Parameters
-    ----------
-
-    """
-
-    flag_ltm_x = [0,1,-1,1,-1]
-    flag_ltm_y = [0,1,1,-1,-1]
-    flag_ltv_x = [0,0,1,0,1]
-    flag_ltv_y = [0,0,0,1,1]
-
-    detector_size_x = int(xlen)
-    detector_size_y = int(ylen)
-
-    data_x = str(int(detector_size_x))
-    data_y = str(int(detector_size_y))
-
-    data_sec = '[1:'+data_x+',1:'+data_y+']'
-
-    name = []
-    value = []
-    description = []
-
-    for k in range(1,2):
-        # f = open("extension"+str(k)+"_image.param","w")
-        j = row_num
-        i = col_num
-        ccdnum = str((j-1)*5+i)
-        name = ['EXTNAME',
-                'BSCALE',
-                'BZERO',
-                'OBSID',
-                'CCDNAME',
-                'AMPNAME',
-                'GAIN',
-                'RDNOISE',
-                'DARK',
-                'SATURATE',
-                'RSPEED',
-                'CHIPTEMP',
-                'CCDCHIP',
-                'DATASEC',
-                'CCDSUM',
-                'NSUM',
-                'LTM1_1',
-                'LTM2_2',
-                'LTV1',
-                'LTV2',
-                'ATM1_1',
-                'ATM2_2',
-                'ATV1',
-                'ATV2',
-                'DTV1',
-                'DTV2',
-                'DTM1_1',
-                'DTM2_2']
-
-        value = ['IM'+str(k),
-                 1.0,
-                 0.0,
-                 'CSST.20200101T000000',
-                 'ccd' + ccdnum.rjust(2,'0'),
-                 'ccd' + ccdnum.rjust(2,'0') + ':'+str(k), 
-                 gain, 
-                 readout, 
-                 dark,
-                 saturation, 
-                 10.0, 
-                 -100.0, 
-                 'ccd' + ccdnum.rjust(2,'0'), 
-                 data_sec, 
-                 '1 1', 
-                 '1 1', 
-                 flag_ltm_x[k], 
-                 flag_ltm_y[k], 
-                 flag_ltv_x[k]*(detector_size_x-20*2+1), 
-                 flag_ltv_y[k]*(detector_size_y+1), 
-                 flag_ltm_x[k], 
-                 flag_ltm_y[k], 
-                 flag_ltv_x[k]*(detector_size_x-20*2+1), 
-                 flag_ltv_y[k]*(detector_size_y+1), 
-                 0, 
-                 0, 
-                 1, 
-                 1]
-        
-        description = ['Extension name',
-                       ' ',
-                       ' ',
-                       'Observation ID',
-                       'CCD name',
-                       'Amplifier name',
-                       'Gain (e-/ADU)',
-                       'Readout noise (e-/pixel)',
-                       'Dark noise (e-/pixel/s)',
-                       'Saturation (e-)',
-                       'Read speed',
-                       'Chip temperature',
-                       'CCD chip ID',
-                       'Data section',
-                       'CCD pixel summing',
-                       'CCD pixel summing',
-                       'CCD to image transformation',
-                       'CCD to image transformation',
-                       'CCD to image transformation',
-                       'CCD to image transformation',
-                       'CCD to amplifier transformation',
-                       'CCD to amplifier transformation',
-                       'CCD to amplifier transformation',
-                       'CCD to amplifier transformation',
-                       'CCD to detector transformatio',
-                       'CCD to detector transformatio',
-                       'CCD to detector transformatio',
-                       'CCD to detector transformatio']
-    return name, value, description
-
-
-##9232 9216  898 534 1309 60 -40  -23.4333
-def WCS_def(xlen = 9232, ylen = 9216, gapx = 898.0, gapy1 = 534, gapy2 = 1309, ra = 60, dec = -40, pa = -23.433,psize = 0.074, row_num = 1, col_num = 1):
-
-    """ Creat a wcs frame for CCST with multiple extensions
-
-    Parameters
-    ----------
-
-    """
-
-    flag_x = [0, 1, -1, 1, -1]
-    flag_y = [0, 1, 1, -1, -1]
-    flag_ext_x = [0,-1,1,-1,1]
-    flag_ext_y = [0,-1,-1,1,1]
-    x_num = 5
-    y_num = 6
-    detector_num = x_num*y_num
-
-
-    detector_size_x = xlen
-    detector_size_y = ylen
-    gap_x = gapx
-    gap_y = [gapy1,gapy2]
-    ra_ref = ra
-    dec_ref = dec
-
-    pa_aper = pa
-
-    pixel_size = psize
-
-    gap_y1_num = 3
-    gap_y2_num = 2
-
-    x_center = (detector_size_x*x_num+gap_x*(x_num-1))/2
-    y_center = (detector_size_y*y_num+gap_y[0]*gap_y1_num+gap_y[1]*gap_y2_num)/2
-
-    gap_y_map = np.array([[0,0,0,0,0],[gap_y[0],gap_y[1],gap_y[1],gap_y[1],gap_y[1]],[gap_y[1],gap_y[0],gap_y[0],gap_y[0],gap_y[0]],[gap_y[0],gap_y[0],gap_y[0],gap_y[0],gap_y[0]],[gap_y[0],gap_y[0],gap_y[0],gap_y[0],gap_y[1]],[gap_y[1],gap_y[1],gap_y[1],gap_y[1],gap_y[0]]])
-
-
-    frame_array = np.empty((5,6),dtype=np.float64)
-    # print(x_center,y_center)
-    
-    j = row_num
-    i = col_num
-    ccdnum = str((j-1)*5+i)
-
-    x_ref, y_ref = (detector_size_x+gap_x)*i-gap_x-detector_size_x/2, detector_size_y*j + sum(gap_y_map[0:j,i-1]) - detector_size_y/2
-
-    # print(i,j,x_ref,y_ref,ra_ref,dec_ref)
-
-    name = []
-    value = []
-    description = []
-    
-    for k in range(1,2):
-        
-        cd = np.array([[ pixel_size,  0], [0, pixel_size]])/3600.*flag_x[k]
-        cd_rot = rotate_CD_matrix(cd, pa_aper)
-
-        # f = open("CCD"+ccdnum.rjust(2,'0')+"_extension"+str(k)+"_wcs.param","w")
-
-        name = ['EQUINOX',
-                'WCSDIM',
-                'CTYPE1',
-                'CTYPE2',
-                'CRVAL1',
-                'CRVAL2',
-                'CRPIX1',
-                'CRPIX2',
-                'CD1_1',
-                'CD1_2',
-                'CD2_1',
-                'CD2_2']
-        value = [2000.0,
-                 2.0,
-                 'RA---TAN',
-                 'DEC--TAN',
-                 ra_ref,
-                 dec_ref,
-                 flag_ext_x[k]*((x_ref+flag_ext_x[k]*detector_size_x/2)-x_center),
-                 flag_ext_y[k]*((y_ref+flag_ext_y[k]*detector_size_y/2)-y_center),
-                 cd_rot[0,0],
-                 cd_rot[0,1],
-                 cd_rot[1,0],
-                 cd_rot[1,1]]
-        description = ['Equinox of WCS',
-                       'WCS Dimensionality',
-                       'Coordinate type',
-                       'Coordinate typ',
-                       'Coordinate reference value',
-                       'Coordinate reference value',
-                       'Coordinate reference pixel',
-                       'Coordinate reference pixel',
-                       'Coordinate matrix',
-                       'Coordinate matrix',
-                       'Coordinate matrix',
-                       'Coordinate matrix']
-
-    return name, value, description
-
-
-
-def generatePrimaryHeader(xlen = 9232, ylen = 9216,pointNum = '1', ra = 60, dec = -40, psize = 0.074, row_num = 1, col_num = 1):
-
-    # array_size1, array_size2, flux, sigma = int(argv[1]), int(argv[2]), 1000.0, 5.0
-    filerParm_fn = os.path.split(os.path.realpath(__file__))[0] + '/filter.lst'
-    f = open(filerParm_fn)
-    s = f.readline()
-    s = s.strip("\n")
-    filter = s.split(' ')
-    
-    k = (row_num-1)*5+col_num
-    ccdnum = str(k)
-
-    g_header_fn = os.path.split(os.path.realpath(__file__))[0] + '/global_header.param'
-    name, value, description = read_header_parameter(g_header_fn)
-
-    h_prim = fits.Header()
-
-    date = '200930'
-    time_obs = '120000'
-
-    for i in range(len(name)):
-        if(name[i]=='FILTER'):
-            value[i] = filter[k-1]
-        
-        if(name[i]=='FILENAME'):
-            value[i] = 'CSST_' + date + '_' +time_obs + '_' + pointNum.rjust(6,'0') + '_' +ccdnum.rjust(2,'0')+'_raw'
-        
-        if(name[i]=='DETSIZE'):
-            value[i] = '[1:' + str(int(xlen)) + ',1:'+  str(int(ylen)) + ']'
-
-        if(name[i]=='PIXSCAL1'):
-            value[i] = str(psize)
-
-        if(name[i]=='PIXSCAL2'):
-            value[i] = str(psize)
-        
-
-        h_prim[name[i]] = (value[i],description[i])
-
-    h_prim.add_comment('==================================================================',after='FILETYPE')
-    h_prim.add_comment('Target information')
-    h_prim.add_comment('==================================================================')
-
-    h_prim.add_comment('==================================================================',after='EQUINOX')
-    h_prim.add_comment('Exposure information')
-    h_prim.add_comment('==================================================================')
-
-    h_prim.add_comment('==================================================================',after='MJDEND')
-    h_prim.add_comment('Telescope information')
-    h_prim.add_comment('==================================================================')
-
-    h_prim.add_comment('==================================================================',after='REFFRAME')
-    h_prim.add_comment('Detector information')
-    h_prim.add_comment('==================================================================')
-
-    h_prim.add_comment('==================================================================',after='FILTER')
-    h_prim.add_comment('Other information')
-    h_prim.add_comment('==================================================================')
-
-    return h_prim
-
-def generateExtensionHeader(xlen = 9232, ylen = 9216,ra = 60, dec = -40, pa = -23.433, gain = 1.0, readout = 5.0, dark = 0.02, saturation=90000, psize = 0.074, row_num = 1, col_num = 1):
-
-    h_ext = fits.Header()
-
-    for i in range(1,2):
-        
-        # NAXIS1:Number of pixels per row;  NAXIS2:Number of rows
-        h_ext['NAXIS1'] = xlen
-        h_ext['NAXIS2'] = ylen
-        name, value, description = Header_extention(xlen = xlen, ylen = ylen, gain = gain, readout = readout, dark = dark, saturation=saturation, row_num = row_num, col_num = col_num)
-
-        for j in range(len(name)):
-            h_ext[name[j]] = (value[j],description[j])
-
-        name, value, description = WCS_def(xlen = xlen, ylen = ylen, gapx = 898.0, gapy1 = 534, gapy2 = 1309, ra = ra, dec = dec, pa = pa ,psize = psize, row_num = row_num, col_num = col_num)
-
-        for j in range(len(name)):
-            h_ext[name[j]] = (value[j],description[j])
-
-        h_ext.add_comment('==================================================================',after='OBSID')
-        h_ext.add_comment('Readout information')
-        h_ext.add_comment('==================================================================')
-
-        h_ext.add_comment('==================================================================',after='CHIPTEMP')
-        h_ext.add_comment('Chip information')
-        h_ext.add_comment('==================================================================')
-
-        h_ext.add_comment('==================================================================',after='DTM2_2')
-        h_ext.add_comment('WCS information')
-        h_ext.add_comment('==================================================================')
-
-    return h_ext
-
-
-
-def main(argv):
-
-    xlen = int(argv[1])
-    ylen = int(argv[2])
-    pointingNum = argv[3]
-    ra = float(argv[4])
-    dec = float(argv[5])
-    pSize = float(argv[6])
-    ccd_row_num = int(argv[7])
-    ccd_col_num = int(argv[8])
-    pa_aper = float(argv[9])
-    gain = float(argv[10])
-    readout = float(argv[11])
-    dark = float(argv[12])
-    fw = float(argv[13])
-
-
-
-    h_prim = generatePrimaryHeader(xlen = xlen, ylen = ylen,ra = ra, dec = dec, psize = pSize, row_num = ccd_row_num, col_num = ccd_col_num, pointNum = pointingNum)
-
-    h_ext = generateExtensionHeader(xlen = xlen, ylen = ylen,ra = ra, dec = dec, pa = pa_aper, gain = gain, readout = readout, dark = dark, saturation=fw, psize = pSize, row_num = ccd_row_num, col_num = ccd_col_num)
-    hdu1 = fits.PrimaryHDU(header=h_prim)
-    hdu2 = fits.ImageHDU(np.zeros([ylen,xlen]),header = h_ext)
-
-    hdul = fits.HDUList([hdu1,hdu2])
-
-    hdul.writeto(h_prim['FILENAME']+'.fits',output_verify='ignore')
-
-# if __name__ == "__main__":
-#     main(sys.argv)
diff --git a/ObservationSim/Config/_util.py b/ObservationSim/Config/_util.py
deleted file mode 100644
index 7e49dee6110de0c4683f772d4ca0226cf6200dd8..0000000000000000000000000000000000000000
--- a/ObservationSim/Config/_util.py
+++ /dev/null
@@ -1,16 +0,0 @@
-
-def get_obs_id(img_type='SCI', project_cycle=6, run_counter=0, pointing_id='00000001',pointing_type_code='101'):
-    # obs_type = {'SCI': '01', 'BIAS': '03', 'DARK': '07', 'FLAT': '11', 'CRS': '98', 'CRD': '99'}
-    # obs_type = {'SCIE': '01', 'BIAS': '03', 'DARK': '07', 'FLAT': '11', 'CRS': '98', 'CRD': '99', 'CAL': '01'}
-    obs_id = pointing_type_code + str(int(project_cycle)).rjust(2, '0') + str(int(run_counter)) + pointing_id
-    return obs_id
-
-# def get_obs_id(img_type='SCI', project_cycle=6, run_counter=0, pointing_num=0):
-#     # obs_type = {'SCI': '01', 'BIAS': '03', 'DARK': '07', 'FLAT': '11', 'CRS': '98', 'CRD': '99'}
-#     obs_type = {'SCIE': '01', 'BIAS': '03', 'DARK': '07', 'FLAT': '11', 'CRS': '98', 'CRD': '99', 'CAL': '01'}
-#     obs_id = '1'+ obs_type[img_type] + str(int(project_cycle)).rjust(2, '0') + str(int(run_counter)) + str(pointing_num).rjust(8,'0')
-#     return obs_id
-
-def get_file_type(img_type='SCI'):
-    file_type = {'SCI':'SCI', 'BIAS':'BIAS', 'DARK':'DARK', 'FLAT':'FLAT', 'CRS':'CRS', 'CRD':'CRD','CALS':'CALS','CALF':'CALF'}
-    return file_type[img_type]
\ No newline at end of file
diff --git a/ObservationSim/Instrument/Chip/Chip.py b/ObservationSim/Instrument/Chip/Chip.py
deleted file mode 100755
index 03532ee6b7e022b00023f589de31459bbf66cd6d..0000000000000000000000000000000000000000
--- a/ObservationSim/Instrument/Chip/Chip.py
+++ /dev/null
@@ -1,1053 +0,0 @@
-import galsim
-import os
-import numpy as np
-import pickle
-import json
-import ObservationSim.Instrument._util as _util
-from astropy.table import Table
-from numpy.random import Generator, PCG64
-from astropy.io import fits
-from datetime import datetime
-
-from ObservationSim.Instrument.Chip import Effects as effects
-from ObservationSim.Instrument.FocalPlane import FocalPlane
-from ObservationSim.Config.Header import generatePrimaryHeader, generateExtensionHeader
-from ObservationSim.Instrument._util import rotate_conterclockwise
-from ObservationSim.Instrument.Chip import ChipUtils as chip_utils
-
-from ObservationSim.Instrument.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('ObservationSim.Instrument.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('ObservationSim.Instrument.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('ObservationSim.Instrument.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('ObservationSim.Instrument.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('ObservationSim.Instrument.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('ObservationSim.Instrument.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('ObservationSim.Instrument.data.sls_conf').joinpath(slsconfs) as conf_path:
-                    self.sls_conf = str(conf_path)
-            except AttributeError:
-                with pkg_resources.path('ObservationSim.Instrument.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('ObservationSim.Instrument.data.sls_conf').joinpath(slsconfs[0]) as conf_path:
-                    self.sls_conf.append(str(conf_path))
-            except AttributeError:
-                with pkg_resources.path('ObservationSim.Instrument.data.sls_conf', slsconfs[0]) as conf_path:
-                    self.sls_conf.append(str(conf_path))
-            try:
-                with pkg_resources.files('ObservationSim.Instrument.data.sls_conf').joinpath(slsconfs[1]) as conf_path:
-                    self.sls_conf.append(str(conf_path))
-            except AttributeError:
-                with pkg_resources.path('ObservationSim.Instrument.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('ObservationSim.Instrument.data.ccd').joinpath(filename) as ccd_path:
-                table = Table.read(ccd_path, format='ascii')
-        except AttributeError:
-            with pkg_resources.path('ObservationSim.Instrument.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('ObservationSim.Instrument.data').joinpath("wfc-cr-attachpixel.dat") as cr_path:
-                self.attachedSizes = np.loadtxt(cr_path)
-        except AttributeError:
-            with pkg_resources.path('ObservationSim.Instrument.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('ObservationSim.Instrument.data').joinpath(flat_fn) as data_path:
-    #             flat_fits = fits.open(data_path, ignore_missing_simple=True)
-    #     except AttributeError:
-    #         with pkg_resources.path('ObservationSim.Instrument.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
-
-    # def addEffects(self, config, img, chip_output, filt, ra_cen, dec_cen, img_rot, exptime=150., pointing_ID=0, timestamp_obs=1621915200, pointing_type='SCI', sky_map=None, post_flash_map=None, tel=None, logger=None):
-    #     # Set random seeds
-    #     SeedGainNonuni = int(config["random_seeds"]["seed_gainNonUniform"])
-    #     SeedBiasNonuni = int(config["random_seeds"]["seed_biasNonUniform"])
-    #     SeedRnNonuni = int(config["random_seeds"]["seed_rnNonUniform"])
-    #     SeedBadColumns = int(config["random_seeds"]["seed_badcolumns"])
-    #     SeedDefective = int(config["random_seeds"]["seed_defective"])
-    #     SeedCosmicRay = int(config["random_seeds"]["seed_CR"])
-    #     fullwell = int(self.full_well)
-    #     if config["ins_effects"]["add_hotpixels"] == True:
-    #         BoolHotPix = True
-    #     else:
-    #         BoolHotPix = False
-    #     if config["ins_effects"]["add_deadpixels"] == True:
-    #         BoolDeadPix = True
-    #     else:
-    #         BoolDeadPix = False
-    #     self.logger = logger
-
-    #     # Get Poisson noise generator
-    #     rng_poisson, poisson_noise = chip_utils.get_poisson(
-    #         seed=int(config["random_seeds"]["seed_poisson"]) + pointing_ID*30 + self.chipID, sky_level=0.)
-
-    #     # Add sky background
-    #     if config["ins_effects"]["add_back"] == True:
-    #         img, sky_map = chip_utils.add_sky_background(
-    #             img=img, filt=filt, exptime=exptime, sky_map=sky_map, tel=tel)
-    #         del sky_map
-
-    #     # Apply flat-field large scale structure for one chip
-    #     if config["ins_effects"]["flat_fielding"] == True:
-    #         chip_utils.log_info(
-    #             msg="  Creating and applying Flat-Fielding", logger=self.logger)
-    #         chip_utils.log_info(msg=str(img.bounds), logger=self.logger)
-    #         flat_img, flat_normal = chip_utils.get_flat(
-    #             img=img, seed=int(config["random_seeds"]["seed_flat"]))
-    #         if self.survey_type == "photometric":
-    #             img *= flat_normal
-    #         del flat_normal
-    #         if config["output_setting"]["flat_output"] == False:
-    #             del flat_img
-
-    #     if post_flash_map is not None:
-    #         img = img + post_flash_map
-
-    #     # Apply Shutter-effect for one chip
-    #     if config["ins_effects"]["shutter_effect"] == True:
-    #         chip_utils.log_info(
-    #             msg="  Apply shutter effect", logger=self.logger)
-    #         # shutter effect normalized image for this chip
-    #         shuttimg = effects.ShutterEffectArr(
-    #             img, t_shutter=1.3, dist_bearing=735, dt=1E-3)
-    #         if self.survey_type == "photometric":
-    #             img *= shuttimg
-    #         # output 16-bit shutter effect image with pixel value <=65535
-    #         if config["output_setting"]["shutter_output"] == True:
-    #             shutt_gsimg = galsim.ImageUS(shuttimg*6E4)
-    #             shutt_gsimg.write("%s/ShutterEffect_%s_1.fits" %
-    #                               (chip_output.subdir, self.chipID))
-    #             del shutt_gsimg
-    #         del shuttimg
-    #     # # Add Poisson noise to the resulting images
-    #     # # (NOTE): this can only applied to the slitless image
-    #     # # since it dose not use photon shooting to draw stamps
-    #     # if self.survey_type == "spectroscopic":
-    #     #     img.addNoise(poisson_noise)
-
-    #     # Add cosmic-rays
-    #     if config["ins_effects"]["cosmic_ray"] == True and pointing_type == 'SCI':
-    #         chip_utils.log_info(msg="  Adding Cosmic-Ray", logger=self.logger)
-    #         img, crmap_gsimg, cr_event_num = chip_utils.add_cosmic_rays(img=img, chip=self, exptime=exptime,
-    #                                                                     seed=SeedCosmicRay+pointing_ID*30+self.chipID)
-    #         chip_utils.outputCal(
-    #             chip=self,
-    #             img=crmap_gsimg,
-    #             ra_cen=ra_cen,
-    #             dec_cen=dec_cen,
-    #             img_rot=img_rot,
-    #             im_type='CRS',
-    #             pointing_ID=pointing_ID,
-    #             output_dir=chip_output.subdir,
-    #             exptime=exptime,
-    #             project_cycle=config["project_cycle"],
-    #             run_counter=config["run_counter"],
-    #             timestamp=timestamp_obs)
-    #         del crmap_gsimg
-
-    #     # Apply PRNU effect and output PRNU flat file:
-    #     if config["ins_effects"]["prnu_effect"] == True:
-    #         chip_utils.log_info(
-    #             msg="  Applying PRNU effect", logger=self.logger)
-    #         img, prnu_img = chip_utils.add_PRNU(img=img, chip=self,
-    #                                             seed=int(config["random_seeds"]["seed_prnu"]+self.chipID))
-    #         if config["output_setting"]["prnu_output"] == True:
-    #             prnu_img.write("%s/FlatImg_PRNU_%s.fits" %
-    #                            (chip_output.subdir, self.chipID))
-    #         if config["output_setting"]["flat_output"] == False:
-    #             del prnu_img
-
-    #     # # Add dark current
-    #     # if config["ins_effects"]["add_dark"] == True:
-    #     #     dark_noise = galsim.DeviateNoise(galsim.PoissonDeviate(rng_poisson, self.dark_noise*(exptime+0.5*self.readout_time)))
-    #     #     img.addNoise(dark_noise)
-
-    #     # Add dark current & Poisson noise
-    #     InputDark = False
-    #     if config["ins_effects"]["add_dark"] == True:
-    #         if InputDark:
-    #             img = chip_utils.add_inputdark(
-    #                 img=img, chip=self, exptime=exptime)
-    #         else:
-    #             img, _ = chip_utils.add_poisson(
-    #                 img=img, chip=self, exptime=exptime, poisson_noise=poisson_noise)
-    #     else:
-    #         img, _ = chip_utils.add_poisson(
-    #             img=img, chip=self, exptime=exptime, poisson_noise=poisson_noise, dark_noise=0.)
-
-    #     # Add diffusion & brighter-fatter effects
-    #     if config["ins_effects"]["bright_fatter"] == True:
-    #         img = chip_utils.add_brighter_fatter(img=img)
-
-    #     # Add Hot Pixels or/and Dead Pixels
-    #     rgbadpix = Generator(PCG64(int(SeedDefective+self.chipID)))
-    #     badfraction = 5E-5*(rgbadpix.random()*0.5+0.7)
-    #     img = effects.DefectivePixels(img, IfHotPix=BoolHotPix, IfDeadPix=BoolDeadPix,
-    #                                   fraction=badfraction, seed=SeedDefective+self.chipID, biaslevel=0)
-
-    #     # Apply Bad lines
-    #     if config["ins_effects"]["add_badcolumns"] == True:
-    #         img = effects.BadColumns(
-    #             img, seed=SeedBadColumns, chipid=self.chipID, logger=self.logger)
-
-    #     # Apply Nonlinearity on the chip image
-    #     if config["ins_effects"]["non_linear"] == True:
-    #         chip_utils.log_info(
-    #             msg="  Applying Non-Linearity on the chip image", logger=self.logger)
-    #         img = effects.NonLinearity(GSImage=img, beta1=5.e-7, beta2=0)
-
-    #     # Apply CCD Saturation & Blooming
-    #     if config["ins_effects"]["saturbloom"] == True:
-    #         chip_utils.log_info(
-    #             msg="  Applying CCD Saturation & Blooming", logger=self.logger)
-    #         img = effects.SaturBloom(
-    #             GSImage=img, nsect_x=1, nsect_y=1, fullwell=fullwell)
-
-    #     # Apply CTE Effect
-    #     # if config["ins_effects"]["cte_trail"] == True:
-    #     # chip_utils.log_info(msg="  Apply CTE Effect", logger=self.logger)
-    #     # img = effects.CTE_Effect(GSImage=img, threshold=27)
-
-    #     pre1 = self.prescan_x  # 27
-    #     over1 = self.overscan_x  # 71
-    #     pre2 = self.prescan_y  # 0 #4
-    #     over2 = self.overscan_y  # 84 #80
-
-    #     if config["ins_effects"]["cte_trail"] == True:
-    #         chip_utils.log_info(msg="  Apply CTE Effect", logger=self.logger)
-    #         # img = effects.CTE_Effect(GSImage=img, threshold=27)
-    #         # CTI_modeling
-    #         # 2*8 -> 1*16 img-layout
-    #         img = chip_utils.formatOutput(GSImage=img)
-    #         self.nsecy = 1
-    #         self.nsecx = 16
-
-    #         img_arr = img.array
-    #         ny, nx = img_arr.shape
-    #         dx = int(nx/self.nsecx)
-    #         dy = int(ny/self.nsecy)
-    #         newimg = galsim.Image(nx, int(ny+over2), init_value=0)
-    #         for ichannel in range(16):
-    #             print('\n***add CTI effects: pointing-{:} chip-{:} channel-{:}***'.format(
-    #                 pointing_ID, self.chipID, ichannel+1))
-    #             # nx,ny,noverscan,nsp,nmax = 4608,4616,84,3,10
-    #             noverscan, nsp, nmax = over2, 3, 10
-    #             beta, w, c = 0.478, 84700, 0
-    #             t = np.array([0.74, 7.7, 37], dtype=np.float32)
-    #             rho_trap = np.array([0.6, 1.6, 1.4], dtype=np.float32)
-    #             trap_seeds = np.array(
-    #                 [0, 1000, 10000], dtype=np.int32) + ichannel + self.chipID*16
-    #             release_seed = 50 + ichannel + pointing_ID*30 + self.chipID*16
-    #             newimg.array[:, 0+ichannel*dx:dx+ichannel*dx] = CTI_sim(
-    #                 img_arr[:, 0+ichannel*dx:dx+ichannel*dx], dx, dy, noverscan, nsp, nmax, beta, w, c, t, rho_trap, trap_seeds, release_seed)
-    #         newimg.wcs = img.wcs
-    #         del img
-    #         img = newimg
-
-    #         # 1*16 -> 2*8 img-layout
-    #         img = chip_utils.formatRevert(GSImage=img)
-    #         self.nsecy = 2
-    #         self.nsecx = 8
-
-    #     # prescan & overscan
-    #     if config["ins_effects"]["add_prescan"] == True:
-    #         chip_utils.log_info(
-    #             msg="  Apply pre/over-scan", logger=self.logger)
-    #         if config["ins_effects"]["cte_trail"] == False:
-    #             img = chip_utils.AddPreScan(
-    #                 GSImage=img, pre1=pre1, pre2=pre2, over1=over1, over2=over2)
-    #         if config["ins_effects"]["cte_trail"] == True:
-    #             img = chip_utils.AddPreScan(
-    #                 GSImage=img, pre1=pre1, pre2=pre2, over1=over1, over2=0)
-
-    #     # 1*16 output
-    #     if config["ins_effects"]["format_output"] == True:
-    #         chip_utils.log_info(msg="  Apply 1*16 format", logger=self.logger)
-    #         img = chip_utils.formatOutput(GSImage=img)
-    #         self.nsecy = 1
-    #         self.nsecx = 16
-
-    #     # Add Bias level
-    #     if config["ins_effects"]["add_bias"] == True:
-    #         chip_utils.log_info(
-    #             msg="  Adding Bias level and 16-channel non-uniformity", logger=self.logger)
-    #         if config["ins_effects"]["bias_16channel"] == True:
-    #             img = effects.AddBiasNonUniform16(img,
-    #                                               bias_level=float(
-    #                                                   self.bias_level),
-    #                                               nsecy=self.nsecy, nsecx=self.nsecx,
-    #                                               seed=SeedBiasNonuni+self.chipID,
-    #                                               logger=self.logger)
-    #         elif config["ins_effects"]["bias_16channel"] == False:
-    #             img += self.bias_level
-
-    #     # Add Read-out Noise
-    #     if config["ins_effects"]["add_readout"] == True:
-    #         seed = int(config["random_seeds"]["seed_readout"]
-    #                    ) + pointing_ID*30 + self.chipID
-    #         rng_readout = galsim.BaseDeviate(seed)
-    #         readout_noise = galsim.GaussianNoise(
-    #             rng=rng_readout, sigma=self.read_noise)
-    #         img.addNoise(readout_noise)
-
-    #     # Apply Gain & Quantization
-    #     chip_utils.log_info(
-    #         msg="  Applying Gain (and 16 channel non-uniformity) & Quantization", logger=self.logger)
-    #     if config["ins_effects"]["gain_16channel"] == True:
-    #         img, self.gain_channel = effects.ApplyGainNonUniform16(
-    #             img, gain=self.gain,
-    #             nsecy=self.nsecy, nsecx=self.nsecx,
-    #             seed=SeedGainNonuni+self.chipID,
-    #             logger=self.logger)
-    #     elif config["ins_effects"]["gain_16channel"] == False:
-    #         img /= self.gain
-
-    #     img.array[img.array > 65535] = 65535
-    #     img.replaceNegative(replace_value=0)
-    #     img.quantize()
-
-    #     ######################################################################################
-    #     # Output images for calibration pointing
-    #     ######################################################################################
-    #     # Bias output
-    #     if config["ins_effects"]["add_bias"] == True and config["output_setting"]["bias_output"] == True and pointing_type == 'CAL':
-    #         if self.logger is not None:
-    #             self.logger.info("  Output N frame Bias files")
-    #         else:
-    #             print("  Output N frame Bias files", flush=True)
-    #         NBias = int(config["output_setting"]["NBias"])
-    #         for i in range(NBias):
-    #             # BiasCombImg, BiasTag = effects.MakeBiasNcomb(
-    #             # self.npix_x, self.npix_y,
-    #             # bias_level=float(self.bias_level),
-    #             # ncombine=1, read_noise=self.read_noise, gain=1,
-    #             # seed=SeedBiasNonuni+self.chipID,
-    #             # logger=self.logger)
-    #             BiasCombImg = galsim.Image(
-    #                 self.npix_x, self.npix_y, init_value=0)
-    #             if config["ins_effects"]["add_bias"] == True:
-    #                 biaslevel = self.bias_level
-    #                 overscan = biaslevel-2
-    #             elif config["ins_effects"]["add_bias"] == False:
-    #                 biaslevel = 0
-    #                 overscan = 0
-
-    #             # Readout noise for Biases is not generated with random seeds. So readout noise for bias images can't be reproduced.
-    #             if config["ins_effects"]["cosmic_ray"] == True:
-    #                 if config["ins_effects"]["cray_differ"] == True:
-    #                     cr_map, cr_event_num = effects.produceCR_Map(
-    #                         xLen=self.npix_x, yLen=self.npix_y,
-    #                         exTime=0.01,
-    #                         cr_pixelRatio=0.003 *
-    #                         (0.01+0.5*self.readout_time)/150.,
-    #                         gain=self.gain,
-    #                         attachedSizes=self.attachedSizes,
-    #                         seed=SeedCosmicRay+pointing_ID*30+self.chipID+1)
-    #                     # seed: obj-imaging:+0; bias:+1; dark:+2; flat:+3;
-    #                 BiasCombImg += cr_map
-    #                 del cr_map
-
-    #             # Apply Bad lines
-    #             if config["ins_effects"]["add_badcolumns"] == True:
-    #                 BiasCombImg = effects.BadColumns(
-    #                     BiasCombImg-float(self.bias_level)+5, seed=SeedBadColumns, chipid=self.chipID, logger=self.logger) + float(self.bias_level)-5
-
-    #             # Non-Linearity for Bias
-    #             if config["ins_effects"]["non_linear"] == True:
-    #                 if self.logger is not None:
-    #                     self.logger.info(
-    #                         "  Applying Non-Linearity on the Bias image")
-    #                 else:
-    #                     print(
-    #                         "  Applying Non-Linearity on the Bias image", flush=True)
-    #                 BiasCombImg = effects.NonLinearity(
-    #                     GSImage=BiasCombImg, beta1=5.e-7, beta2=0)
-
-    #             # START
-    #             pre1 = self.prescan_x  # 27
-    #             over1 = self.overscan_x  # 71
-    #             pre2 = self.prescan_y  # 0 #4
-    #             over2 = self.overscan_y  # 84 #80
-
-    #             # prescan & overscan
-    #             if config["ins_effects"]["add_prescan"] == True:
-    #                 chip_utils.log_info(
-    #                     msg="  Apply pre/over-scan", logger=self.logger)
-    #                 BiasCombImg = chip_utils.AddPreScan(
-    #                     GSImage=BiasCombImg, pre1=pre1, pre2=pre2, over1=over1, over2=over2)
-
-    #             # 1*16 output
-    #             if config["ins_effects"]["format_output"] == True:
-    #                 chip_utils.log_info(
-    #                     msg="  Apply 1*16 format", logger=self.logger)
-    #                 BiasCombImg = chip_utils.formatOutput(GSImage=BiasCombImg)
-    #                 self.nsecy = 1
-    #                 self.nsecx = 16
-    #             # END
-
-    #             # Add Bias level
-    #             if config["ins_effects"]["add_bias"] == True:
-    #                 if self.logger is not None:
-    #                     self.logger.info(
-    #                         "  Adding Bias level and 16-channel non-uniformity")
-    #                 else:
-    #                     print("  Adding Bias level and 16-channel non-uniformity")
-    #                 BiasCombImg = effects.AddBiasNonUniform16(BiasCombImg,
-    #                                                           bias_level=biaslevel,
-    #                                                           nsecy=self.nsecy, nsecx=self.nsecx,
-    #                                                           seed=SeedBiasNonuni+self.chipID,
-    #                                                           logger=self.logger)
-    #                 rng = galsim.UniformDeviate()
-    #                 ncombine = 1
-    #                 NoiseBias = galsim.GaussianNoise(
-    #                     rng=rng, sigma=self.read_noise*ncombine**0.5)
-    #                 BiasCombImg.addNoise(NoiseBias)
-
-    #             BiasCombImg, self.gain_channel = effects.ApplyGainNonUniform16(BiasCombImg, gain=self.gain,
-    #                                                                            nsecy=self.nsecy, nsecx=self.nsecx,
-    #                                                                            seed=SeedGainNonuni+self.chipID,
-    #                                                                            logger=self.logger)
-    #             # BiasCombImg = effects.AddOverscan(
-    #             #     BiasCombImg,
-    #             #     overscan=float(config["ins_effects"]["bias_level"])-2, gain=self.gain,
-    #             #     widthl=27, widthr=27, widtht=8, widthb=8)
-    #             BiasCombImg.replaceNegative(replace_value=0)
-    #             BiasCombImg.quantize()
-    #             BiasCombImg = galsim.ImageUS(BiasCombImg)
-    #             timestamp_obs += 10 * 60
-    #             chip_utils.outputCal(
-    #                 chip=self,
-    #                 img=BiasCombImg,
-    #                 ra_cen=ra_cen,
-    #                 dec_cen=dec_cen,
-    #                 img_rot=img_rot,
-    #                 im_type='BIAS',
-    #                 pointing_ID=pointing_ID,
-    #                 output_dir=chip_output.subdir,
-    #                 exptime=0.0,
-    #                 project_cycle=config["project_cycle"],
-    #                 run_counter=config["run_counter"],
-    #                 timestamp=timestamp_obs)
-    #         del BiasCombImg
-
-    #     # Export combined (ncombine, Vignetting + PRNU) & single vignetting flat-field file
-    #     if config["ins_effects"]["flat_fielding"] == True and config["output_setting"]["flat_output"] == True and pointing_type == 'CAL':
-    #         if self.logger is not None:
-    #             self.logger.info("  Output N frame Flat-Field files")
-    #         else:
-    #             print("  Output N frame Flat-Field files", flush=True)
-    #         NFlat = int(config["output_setting"]["NFlat"])
-    #         if config["ins_effects"]["add_bias"] == True:
-    #             biaslevel = self.bias_level
-    #             overscan = biaslevel-2
-    #         elif config["ins_effects"]["add_bias"] == False:
-    #             biaslevel = 0
-    #             overscan = 0
-    #         darklevel = self.dark_noise * \
-    #             (self.flat_exptime+0.5*self.readout_time)
-    #         for i in range(NFlat):
-    #             FlatSingle = flat_img * prnu_img + darklevel
-    #             FlatCombImg, FlatTag = effects.MakeFlatNcomb(
-    #                 flat_single_image=FlatSingle,
-    #                 ncombine=1,
-    #                 read_noise=self.read_noise,
-    #                 gain=1,
-    #                 overscan=overscan,
-    #                 biaslevel=0,
-    #                 seed_bias=SeedDefective+self.chipID,
-    #                 logger=self.logger
-    #             )
-    #             if config["ins_effects"]["cosmic_ray"] == True:
-    #                 if config["ins_effects"]["cray_differ"] == True:
-    #                     cr_map, cr_event_num = effects.produceCR_Map(
-    #                         xLen=self.npix_x, yLen=self.npix_y,
-    #                         exTime=self.flat_exptime+0.5*self.readout_time,
-    #                         cr_pixelRatio=0.003 *
-    #                         (self.flat_exptime+0.5*self.readout_time)/150.,
-    #                         gain=self.gain,
-    #                         attachedSizes=self.attachedSizes,
-    #                         seed=SeedCosmicRay+pointing_ID*30+self.chipID+3)
-    #                     # seed: obj-imaging:+0; bias:+1; dark:+2; flat:+3;
-    #                 FlatCombImg += cr_map
-    #                 del cr_map
-
-    #             # Add Hot Pixels or/and Dead Pixels
-    #             rgbadpix = Generator(PCG64(int(SeedDefective+self.chipID)))
-    #             badfraction = 5E-5*(rgbadpix.random()*0.5+0.7)
-    #             FlatCombImg = effects.DefectivePixels(
-    #                 FlatCombImg, IfHotPix=BoolHotPix, IfDeadPix=BoolDeadPix, fraction=badfraction, seed=SeedDefective+self.chipID, biaslevel=0)
-
-    #             # Apply Bad lines
-    #             if config["ins_effects"]["add_badcolumns"] == True:
-    #                 FlatCombImg = effects.BadColumns(
-    #                     FlatCombImg, seed=SeedBadColumns, chipid=self.chipID, logger=self.logger)
-
-    #             if config["ins_effects"]["non_linear"] == True:
-    #                 if self.logger is not None:
-    #                     self.logger.info(
-    #                         "  Applying Non-Linearity on the Flat image")
-    #                 else:
-    #                     print(
-    #                         "  Applying Non-Linearity on the Flat image", flush=True)
-    #                 FlatCombImg = effects.NonLinearity(
-    #                     GSImage=FlatCombImg, beta1=5.e-7, beta2=0)
-
-    #             # if config["ins_effects"]["cte_trail"] == True:
-    #             # FlatCombImg = effects.CTE_Effect(GSImage=FlatCombImg, threshold=3)
-    #             # START
-    #             pre1 = self.prescan_x  # 27
-    #             over1 = self.overscan_x  # 71
-    #             pre2 = self.prescan_y  # 0 #4
-    #             over2 = self.overscan_y  # 84 #80
-    #             if config["ins_effects"]["cte_trail"] == True:
-    #                 chip_utils.log_info(
-    #                     msg="  Apply CTE Effect", logger=self.logger)
-    #                 # img = effects.CTE_Effect(GSImage=img, threshold=27)
-    #                 # CTI_modeling
-    #                 # 2*8 -> 1*16 img-layout
-    #                 FlatCombImg = chip_utils.formatOutput(GSImage=FlatCombImg)
-    #                 self.nsecy = 1
-    #                 self.nsecx = 16
-
-    #                 img_arr = FlatCombImg.array
-    #                 ny, nx = img_arr.shape
-    #                 dx = int(nx/self.nsecx)
-    #                 dy = int(ny/self.nsecy)
-    #                 newimg = galsim.Image(nx, int(ny+over2), init_value=0)
-    #                 for ichannel in range(16):
-    #                     print('\n***add CTI effects: pointing-{:} chip-{:} channel-{:}***'.format(
-    #                         pointing_ID, self.chipID, ichannel+1))
-    #                     # nx,ny,noverscan,nsp,nmax = 4608,4616,84,3,10
-    #                     noverscan, nsp, nmax = over2, 3, 10
-    #                     beta, w, c = 0.478, 84700, 0
-    #                     t = np.array([0.74, 7.7, 37], dtype=np.float32)
-    #                     rho_trap = np.array([0.6, 1.6, 1.4], dtype=np.float32)
-    #                     trap_seeds = np.array(
-    #                         [0, 1000, 10000], dtype=np.int32) + ichannel + self.chipID*16
-    #                     release_seed = 50 + ichannel + pointing_ID*30 + self.chipID*16
-    #                     newimg.array[:, 0+ichannel*dx:dx+ichannel*dx] = CTI_sim(
-    #                         img_arr[:, 0+ichannel*dx:dx+ichannel*dx], dx, dy, noverscan, nsp, nmax, beta, w, c, t, rho_trap, trap_seeds, release_seed)
-    #                 newimg.wcs = FlatCombImg.wcs
-    #                 del FlatCombImg
-    #                 FlatCombImg = newimg
-
-    #                 # 1*16 -> 2*8 img-layout
-    #                 FlatCombImg = chip_utils.formatRevert(GSImage=FlatCombImg)
-    #                 self.nsecy = 2
-    #                 self.nsecx = 8
-
-    #             # prescan & overscan
-    #             if config["ins_effects"]["add_prescan"] == True:
-    #                 chip_utils.log_info(
-    #                     msg="  Apply pre/over-scan", logger=self.logger)
-    #                 if config["ins_effects"]["cte_trail"] == False:
-    #                     FlatCombImg = chip_utils.AddPreScan(
-    #                         GSImage=FlatCombImg, pre1=pre1, pre2=pre2, over1=over1, over2=over2)
-    #                 if config["ins_effects"]["cte_trail"] == True:
-    #                     FlatCombImg = chip_utils.AddPreScan(
-    #                         GSImage=FlatCombImg, pre1=pre1, pre2=pre2, over1=over1, over2=0)
-
-    #             # 1*16 output
-    #             if config["ins_effects"]["format_output"] == True:
-    #                 chip_utils.log_info(
-    #                     msg="  Apply 1*16 format", logger=self.logger)
-    #                 FlatCombImg = chip_utils.formatOutput(GSImage=FlatCombImg)
-    #                 self.nsecy = 1
-    #                 self.nsecx = 16
-    #             # END
-
-    #             # Add Bias level
-    #             if config["ins_effects"]["add_bias"] == True:
-    #                 if self.logger is not None:
-    #                     self.logger.info(
-    #                         "  Adding Bias level and 16-channel non-uniformity")
-    #                 else:
-    #                     print("  Adding Bias level and 16-channel non-uniformity")
-    #                 # img += float(config["ins_effects"]["bias_level"])
-    #                 FlatCombImg = effects.AddBiasNonUniform16(FlatCombImg,
-    #                                                           bias_level=biaslevel,
-    #                                                           nsecy=self.nsecy, nsecx=self.nsecx,
-    #                                                           seed=SeedBiasNonuni+self.chipID,
-    #                                                           logger=self.logger)
-
-    #             # Add Read-out Noise
-    #             if config["ins_effects"]["add_readout"] == True:
-    #                 seed = int(config["random_seeds"]["seed_readout"]
-    #                            ) + pointing_ID*30 + self.chipID + 3
-    #                 rng_readout = galsim.BaseDeviate(seed)
-    #                 readout_noise = galsim.GaussianNoise(
-    #                     rng=rng_readout, sigma=self.read_noise)
-    #                 FlatCombImg.addNoise(readout_noise)
-
-    #             FlatCombImg, self.gain_channel = effects.ApplyGainNonUniform16(FlatCombImg, gain=self.gain,
-    #                                                                            nsecy=self.nsecy, nsecx=self.nsecx,
-    #                                                                            seed=SeedGainNonuni+self.chipID,
-    #                                                                            logger=self.logger)
-    #             # FlatCombImg = effects.AddOverscan(FlatCombImg, overscan=overscan, gain=self.gain, widthl=27, widthr=27, widtht=8, widthb=8)
-    #             FlatCombImg.replaceNegative(replace_value=0)
-    #             FlatCombImg.quantize()
-    #             FlatCombImg = galsim.ImageUS(FlatCombImg)
-    #             timestamp_obs += 10 * 60
-    #             chip_utils.outputCal(
-    #                 chip=self,
-    #                 img=FlatCombImg,
-    #                 ra_cen=ra_cen,
-    #                 dec_cen=dec_cen,
-    #                 img_rot=img_rot,
-    #                 im_type='FLAT',
-    #                 pointing_ID=pointing_ID,
-    #                 output_dir=chip_output.subdir,
-    #                 exptime=self.flat_exptime,
-    #                 project_cycle=config["project_cycle"],
-    #                 run_counter=config["run_counter"],
-    #                 timestamp=timestamp_obs)
-
-    #         del FlatCombImg, FlatSingle, prnu_img
-    #         # flat_img.replaceNegative(replace_value=0)
-    #         # flat_img.quantize()
-    #         # galsim.ImageUS(flat_img).write("%s/FlatImg_Vignette_%s.fits" % (chip_output.subdir, self.chipID))
-    #         del flat_img
-
-    #     # Export Dark current images
-    #     if config["ins_effects"]["add_dark"] == True and config["output_setting"]["dark_output"] == True and pointing_type == 'CAL':
-    #         if self.logger is not None:
-    #             self.logger.info("  Output N frame Dark Current files")
-    #         else:
-    #             print("  Output N frame Dark Current files", flush=True)
-    #         NDark = int(config["output_setting"]["NDark"])
-    #         if config["ins_effects"]["add_bias"] == True:
-    #             biaslevel = self.bias_level
-    #             overscan = biaslevel-2
-    #         elif config["ins_effects"]["add_bias"] == False:
-    #             biaslevel = 0
-    #             overscan = 0
-    #         for i in range(NDark):
-    #             DarkCombImg, DarkTag = effects.MakeDarkNcomb(
-    #                 self.npix_x, self.npix_y,
-    #                 overscan=overscan, bias_level=0, darkpsec=0.02, exptime=self.dark_exptime+0.5*self.readout_time,
-    #                 ncombine=1, read_noise=self.read_noise,
-    #                 gain=1, seed_bias=SeedBiasNonuni+self.chipID,
-    #                 logger=self.logger)
-    #             if config["ins_effects"]["cosmic_ray"] == True:
-    #                 if config["ins_effects"]["cray_differ"] == True:
-    #                     cr_map, cr_event_num = effects.produceCR_Map(
-    #                         xLen=self.npix_x, yLen=self.npix_y,
-    #                         exTime=self.dark_exptime+0.5*self.readout_time,
-    #                         cr_pixelRatio=0.003 *
-    #                         (self.dark_exptime+0.5*self.readout_time)/150.,
-    #                         gain=self.gain,
-    #                         attachedSizes=self.attachedSizes,
-    #                         seed=SeedCosmicRay+pointing_ID*30+self.chipID+2)
-    #                     # seed: obj-imaging:+0; bias:+1; dark:+2; flat:+3;
-    #                 DarkCombImg += cr_map
-    #                 cr_map[cr_map > 65535] = 65535
-    #                 cr_map[cr_map < 0] = 0
-    #                 crmap_gsimg = galsim.Image(cr_map, dtype=np.uint16)
-    #                 del cr_map
-    #                 # START
-    #                 # prescan & overscan
-    #                 if config["ins_effects"]["add_prescan"] == True:
-    #                     chip_utils.log_info(
-    #                         msg="  Apply pre/over-scan", logger=self.logger)
-    #                     crmap_gsimg = chip_utils.AddPreScan(
-    #                         GSImage=crmap_gsimg, pre1=pre1, pre2=pre2, over1=over1, over2=over2)
-
-    #                 # 1*16 output
-    #                 if config["ins_effects"]["format_output"] == True:
-    #                     chip_utils.log_info(
-    #                         msg="  Apply 1*16 format", logger=self.logger)
-    #                     crmap_gsimg = chip_utils.formatOutput(
-    #                         GSImage=crmap_gsimg)
-    #                     self.nsecy = 1
-    #                     self.nsecx = 16
-    #                 # END
-    #                 chip_utils.outputCal(
-    #                     chip=self,
-    #                     img=crmap_gsimg,
-    #                     ra_cen=ra_cen,
-    #                     dec_cen=dec_cen,
-    #                     img_rot=img_rot,
-    #                     im_type='CRD',
-    #                     pointing_ID=pointing_ID,
-    #                     output_dir=chip_output.subdir,
-    #                     exptime=self.dark_exptime,
-    #                     project_cycle=config["project_cycle"],
-    #                     run_counter=config["run_counter"],
-    #                     timestamp=timestamp_obs)
-    #                 del crmap_gsimg
-
-    #             # Add Hot Pixels or/and Dead Pixels
-    #             rgbadpix = Generator(PCG64(int(SeedDefective+self.chipID)))
-    #             badfraction = 5E-5*(rgbadpix.random()*0.5+0.7)
-    #             DarkCombImg = effects.DefectivePixels(
-    #                 DarkCombImg, IfHotPix=BoolHotPix, IfDeadPix=BoolDeadPix, fraction=badfraction, seed=SeedDefective+self.chipID, biaslevel=0)
-
-    #             # Apply Bad lines
-    #             if config["ins_effects"]["add_badcolumns"] == True:
-    #                 DarkCombImg = effects.BadColumns(
-    #                     DarkCombImg, seed=SeedBadColumns, chipid=self.chipID, logger=self.logger)
-
-    #             # Non-Linearity for Dark
-    #             if config["ins_effects"]["non_linear"] == True:
-    #                 if self.logger is not None:
-    #                     self.logger.info(
-    #                         "  Applying Non-Linearity on the Dark image")
-    #                 else:
-    #                     print(
-    #                         "  Applying Non-Linearity on the Dark image", flush=True)
-    #                 DarkCombImg = effects.NonLinearity(
-    #                     GSImage=DarkCombImg, beta1=5.e-7, beta2=0)
-
-    #             # if config["ins_effects"]["cte_trail"] == True:
-    #             # DarkCombImg = effects.CTE_Effect(GSImage=DarkCombImg, threshold=3)
-    #             # START
-    #             pre1 = self.prescan_x  # 27
-    #             over1 = self.overscan_x  # 71
-    #             pre2 = self.prescan_y  # 0 #4
-    #             over2 = self.overscan_y  # 84 #80
-    #             if config["ins_effects"]["cte_trail"] == True:
-    #                 chip_utils.log_info(
-    #                     msg="  Apply CTE Effect", logger=self.logger)
-    #                 # img = effects.CTE_Effect(GSImage=img, threshold=27)
-    #                 # CTI_modeling
-    #                 # 2*8 -> 1*16 img-layout
-    #                 DarkCombImg = chip_utils.formatOutput(GSImage=DarkCombImg)
-    #                 self.nsecy = 1
-    #                 self.nsecx = 16
-
-    #                 img_arr = DarkCombImg.array
-    #                 ny, nx = img_arr.shape
-    #                 dx = int(nx/self.nsecx)
-    #                 dy = int(ny/self.nsecy)
-    #                 newimg = galsim.Image(nx, int(ny+over2), init_value=0)
-    #                 for ichannel in range(16):
-    #                     print('\n***add CTI effects: pointing-{:} chip-{:} channel-{:}***'.format(
-    #                         pointing_ID, self.chipID, ichannel+1))
-    #                     # nx,ny,noverscan,nsp,nmax = 4608,4616,84,3,10
-    #                     noverscan, nsp, nmax = over2, 3, 10
-    #                     beta, w, c = 0.478, 84700, 0
-    #                     t = np.array([0.74, 7.7, 37], dtype=np.float32)
-    #                     rho_trap = np.array([0.6, 1.6, 1.4], dtype=np.float32)
-    #                     trap_seeds = np.array(
-    #                         [0, 1000, 10000], dtype=np.int32) + ichannel + self.chipID*16
-    #                     release_seed = 50 + ichannel + pointing_ID*30 + self.chipID*16
-    #                     newimg.array[:, 0+ichannel*dx:dx+ichannel*dx] = CTI_sim(
-    #                         img_arr[:, 0+ichannel*dx:dx+ichannel*dx], dx, dy, noverscan, nsp, nmax, beta, w, c, t, rho_trap, trap_seeds, release_seed)
-    #                 newimg.wcs = DarkCombImg.wcs
-    #                 del DarkCombImg
-    #                 DarkCombImg = newimg
-
-    #                 # 1*16 -> 2*8 img-layout
-    #                 DarkCombImg = chip_utils.formatRevert(GSImage=DarkCombImg)
-    #                 self.nsecy = 2
-    #                 self.nsecx = 8
-
-    #             # prescan & overscan
-    #             if config["ins_effects"]["add_prescan"] == True:
-    #                 chip_utils.log_info(
-    #                     msg="  Apply pre/over-scan", logger=self.logger)
-    #                 if config["ins_effects"]["cte_trail"] == False:
-    #                     DarkCombImg = chip_utils.AddPreScan(
-    #                         GSImage=DarkCombImg, pre1=pre1, pre2=pre2, over1=over1, over2=over2)
-    #                 if config["ins_effects"]["cte_trail"] == True:
-    #                     DarkCombImg = chip_utils.AddPreScan(
-    #                         GSImage=DarkCombImg, pre1=pre1, pre2=pre2, over1=over1, over2=0)
-
-    #             # 1*16 output
-    #             if config["ins_effects"]["format_output"] == True:
-    #                 chip_utils.log_info(
-    #                     msg="  Apply 1*16 format", logger=self.logger)
-    #                 DarkCombImg = chip_utils.formatOutput(GSImage=DarkCombImg)
-    #                 self.nsecy = 1
-    #                 self.nsecx = 16
-    #             # END
-
-    #             # Add Bias level
-    #             if config["ins_effects"]["add_bias"] == True:
-    #                 if self.logger is not None:
-    #                     self.logger.info(
-    #                         "  Adding Bias level and 16-channel non-uniformity")
-    #                 else:
-    #                     print("  Adding Bias level and 16-channel non-uniformity")
-    #                 # img += float(config["ins_effects"]["bias_level"])
-    #                 DarkCombImg = effects.AddBiasNonUniform16(DarkCombImg,
-    #                                                           bias_level=biaslevel,
-    #                                                           nsecy=self.nsecy, nsecx=self.nsecx,
-    #                                                           seed=SeedBiasNonuni+self.chipID,
-    #                                                           logger=self.logger)
-
-    #             # Add Read-out Noise
-    #             if config["ins_effects"]["add_readout"] == True:
-    #                 seed = int(config["random_seeds"]["seed_readout"]
-    #                            ) + pointing_ID*30 + self.chipID + 2
-    #                 rng_readout = galsim.BaseDeviate(seed)
-    #                 readout_noise = galsim.GaussianNoise(
-    #                     rng=rng_readout, sigma=self.read_noise)
-    #                 DarkCombImg.addNoise(readout_noise)
-
-    #             DarkCombImg, self.gain_channel = effects.ApplyGainNonUniform16(
-    #                 DarkCombImg, gain=self.gain,
-    #                 nsecy=self.nsecy, nsecx=self.nsecx,
-    #                 seed=SeedGainNonuni+self.chipID,
-    #                 logger=self.logger)
-    #             # DarkCombImg = effects.AddOverscan(
-    #             #     DarkCombImg,
-    #             #     overscan=overscan, gain=self.gain,
-    #             #     widthl=27, widthr=27, widtht=8, widthb=8)
-    #             DarkCombImg.replaceNegative(replace_value=0)
-    #             DarkCombImg.quantize()
-    #             DarkCombImg = galsim.ImageUS(DarkCombImg)
-    #             timestamp_obs += 10 * 60
-    #             chip_utils.outputCal(
-    #                 chip=self,
-    #                 img=DarkCombImg,
-    #                 ra_cen=ra_cen,
-    #                 dec_cen=dec_cen,
-    #                 img_rot=img_rot,
-    #                 im_type='DARK',
-    #                 pointing_ID=pointing_ID,
-    #                 output_dir=chip_output.subdir,
-    #                 exptime=self.dark_exptime,
-    #                 project_cycle=config["project_cycle"],
-    #                 run_counter=config["run_counter"],
-    #                 timestamp=timestamp_obs)
-    #         del DarkCombImg
-    #     # img = galsim.ImageUS(img)
-
-    #     # # 16 output channel, with each a single image file
-    #     # if config["ins_effects"]["readout16"] == True:
-    #     #     print("  16 Output Channel simulation")
-    #     #     for coli in [0, 1]:
-    #     #         for rowi in range(8):
-    #     #             sub_img = effects.readout16(
-    #     #                 GSImage=img,
-    #     #                 rowi=rowi,
-    #     #                 coli=coli,
-    #     #                 overscan_value=self.overscan)
-    #     #             rowcoltag = str(rowi) + str(coli)
-    #     #             img_name_root = chip_output.img_name.split(".")[0]
-    #     #             sub_img.write("%s/%s_%s.fits" % (chip_output.subdir, img_name_root, rowcoltag))
-    #     #     del sub_img
-    #     return img
diff --git a/ObservationSim/Instrument/Telescope.py b/ObservationSim/Instrument/Telescope.py
deleted file mode 100755
index 719a422dd748fa2c96fc2ef51782e24e698d713f..0000000000000000000000000000000000000000
--- a/ObservationSim/Instrument/Telescope.py
+++ /dev/null
@@ -1,44 +0,0 @@
-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('ObservationSim.Instrument.data').joinpath('mirror_ccdnote.txt') as optEffCurve_path:
-					self.efficiency = self._get_efficiency(optEffCurve_path)
-			except AttributeError:
-				with pkg_resources.path('ObservationSim.Instrument.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
\ No newline at end of file
diff --git a/ObservationSim/Instrument/_util.py b/ObservationSim/Instrument/_util.py
deleted file mode 100755
index 58d153ccaa04160f776fb0a1752a0a3db9329d17..0000000000000000000000000000000000000000
--- a/ObservationSim/Instrument/_util.py
+++ /dev/null
@@ -1,130 +0,0 @@
-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('ObservationSim.Instrument.data.throughputs').joinpath(throughputFn) as data_file:
-			throughput_f = np.loadtxt(data_file)
-	except AttributeError:
-		with pkg_resources.path('ObservationSim.Instrument.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('ObservationSim.Instrument.data.throughputs').joinpath(skyFn) as data_file:
-			skydata = np.loadtxt(data_file)
-	except AttributeError:
-		with pkg_resources.path('ObservationSim.Instrument.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
\ No newline at end of file
diff --git a/ObservationSim/MockObject/CosmicRay.py b/ObservationSim/MockObject/CosmicRay.py
deleted file mode 100755
index bdfb9ab3ae1fe2705b42b347592bde7c11649a6c..0000000000000000000000000000000000000000
--- a/ObservationSim/MockObject/CosmicRay.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from ObservationSim.MockObject.MockObject import MockObject
-
-class CosmicRay(MockObject):
-	pass
\ No newline at end of file
diff --git a/ObservationSim/PSF/PSFGauss.py b/ObservationSim/PSF/PSFGauss.py
deleted file mode 100644
index 234d5d08f8c7e0f2ac7026115cfb185b923ce0d1..0000000000000000000000000000000000000000
--- a/ObservationSim/PSF/PSFGauss.py
+++ /dev/null
@@ -1,118 +0,0 @@
-import galsim
-import sep
-import numpy as np
-from scipy.interpolate import interp1d
-
-from ObservationSim.PSF.PSFModel import PSFModel
-
-class PSFGauss(PSFModel):
-	def __init__(self, chip, fwhm=0.187, sigSpin=0., psfRa=None):
-		self.pix_size = chip.pix_scale
-		self.chip = chip
-		if psfRa is None:
-			self.fwhm = fwhm
-			self.sigGauss = 0.15
-		else:
-			self.fwhm = self.fwhmGauss(r=psfRa)
-			self.sigGauss = psfRa # 80% light radius
-		self.sigSpin = sigSpin
-		self.psf = galsim.Gaussian(flux=1.0,fwhm=fwhm)
-
-	def perfGauss(self, r, sig):
-		"""
-		pseudo-error function, i.e. Cumulative distribution function of Gaussian distribution
-
-		Parameter:
-		r: radius
-		sig: sigma of the Gaussian distribution
-
-		Return:
-		the value of the pseudo CDF
-		"""
-		gaussFun = lambda sigma, r: 1.0/(np.sqrt(2.0*np.pi)*sigma) * np.exp(-r**2/(2.0*sigma**2))
-		nxx = 1000
-		rArr = np.linspace(0.0,r,nxx)
-		gauss = gaussFun(sig,rArr)
-		erf = 2.0*np.trapz(gauss,rArr)
-		return erf
-
-	def fracGauss(self, sig, r=0.15, pscale=None):
-		"""
-		For a given Gaussian PSF with sigma=sig,
-		derive the flux ratio ar the given radius r
-		
-		Parameters:
-		sig: sigma of the Gauss PSF Function in arcsec
-		r:   radius in arcsec
-		pscale: pixel scale
-
-		Return: the flux ratio
-		"""
-		if pscale == None:
-			pscale = self.pix_size
-		gaussx = galsim.Gaussian(flux=1.0,sigma=sig)
-		gaussImg  = gaussx.drawImage(scale=pscale, method='no_pixel')
-		gaussImg = gaussImg.array
-		size = np.size(gaussImg,axis=0)
-		cxy = 0.5*(size-1)
-		flux, ferr, flag = sep.sum_circle(gaussImg,[cxy],[cxy],[r/pscale],subpix=0)
-		return flux
-
-	def fwhmGauss(self, r=0.15,fr=0.8,pscale=None):
-		"""
-		Given a total flux ratio 'fr' within a fixed radius 'r',
-		estimate the fwhm of the Gaussian function
-
-		return the fwhm in arcsec
-		"""
-		if pscale == None:
-			pscale = self.pix_size
-		err = 1.0e-3
-		nxx = 100
-		sig = np.linspace(0.5*pscale,1.0,nxx)
-		frA = np.zeros(nxx)
-		for i in range(nxx): frA[i] = self.fracGauss(sig[i],r=r,pscale=pscale)
-		index = [i for i in range(nxx-1) if (fr-frA[i])*(fr-frA[i+1])<=0.0][0]
-
-		while abs(frA[index]-fr)>1.0e-3:
-			sig = np.linspace(sig[index],sig[index+1],nxx)
-			for i in range(nxx): frA[i] = self.fracGauss(sig[i],r=r,pscale=pscale)
-			index = [i for i in range(nxx-1) if (fr-frA[i])*(fr-frA[i+1])<=0.0][0]
-
-		fwhm = 2.35482*sig[index]
-		return fwhm
-
-	def get_PSF(self, pos_img, chip=None, bandpass=None, folding_threshold=5.e-3):
-		dx = pos_img.x - self.chip.cen_pix_x
-		dy = pos_img.y - self.chip.cen_pix_y
-		return self.PSFspin(dx, dy)
-
-	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
\ No newline at end of file
diff --git a/ObservationSim/PSF/PSFModel.py b/ObservationSim/PSF/PSFModel.py
deleted file mode 100755
index 0f37d31b444dcc7354297475e71a3860d4e29243..0000000000000000000000000000000000000000
--- a/ObservationSim/PSF/PSFModel.py
+++ /dev/null
@@ -1,41 +0,0 @@
-import galsim
-import sep
-import numpy as np
-from scipy.interpolate import interp1d
-import pylab as pl
-import os, sys
-
-class PSFModel(object):
-	def __init__(self, sigSpin=0., psfRa=0.15):
-		# TODO: what are the nesseary fields in PSFModel class?
-		pass
-
-	def PSFspin(self, psf, sigSpin, sigGauss, dx, dy):
-		"""
-		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 = sigGauss * 0.107 * (1000.0/10.0) # in unit of [pixels]
-		rc = np.sqrt(dx*dx + dy*dy)
-		cpix = rc*(sigSpin*a2Rad)
-
-		beta = (np.arctan2(dy,dx) + 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 psf.shear(PSFshear), PSFshear
\ No newline at end of file
diff --git a/ObservationSim/sim_steps/add_LED_flat.py b/ObservationSim/sim_steps/add_LED_flat.py
deleted file mode 100644
index befd04d9e1a4e3272c80264cef40f803533cdcdc..0000000000000000000000000000000000000000
--- a/ObservationSim/sim_steps/add_LED_flat.py
+++ /dev/null
@@ -1,51 +0,0 @@
-import numpy as np
-from ObservationSim.MockObject import FlatLED
-import galsim
-
-from astropy.time import Time
-from datetime import datetime, timezone
-
-import gc
-
-def add_LED_Flat(self, chip, filt, tel, pointing, catalog, obs_param):
-        
-    if not hasattr(self, 'h_ext'):
-        _, _ = self.prepare_headers(chip=chip, pointing=pointing)
-    chip_wcs = galsim.FitsWCS(header = self.h_ext)
-    pf_map = np.zeros_like(chip.img.array)
-    if obs_param["LED_TYPE"] is not None:
-        if len(obs_param["LED_TYPE"]) != 0:
-            print("LED OPEN--------")
-
-            led_obj = FlatLED(chip, filt)
-            led_flat, ledstat, letts = led_obj.drawObj_LEDFlat(led_type_list=obs_param["LED_TYPE"], exp_t_list=obs_param["LED_TIME"])
-            pf_map = led_flat
-            self.updateHeaderInfo(header_flag='ext', keys = ['LEDSTAT'], values = [ledstat])
-            self.updateHeaderInfo(header_flag='ext', keys = ['LEDT01','LEDT02','LEDT03','LEDT04','LEDT05','LEDT06','LEDT07','LEDT08','LEDT09','LEDT10','LEDT11','LEDT12','LEDT13','LEDT14'], values = letts)
-        
-
-    if obs_param["shutter_effect"] == True:
-        pf_map = pf_map * chip.shutter_img
-        pf_map = np.array(pf_map, dtype='float32')
-        self.updateHeaderInfo(header_flag='ext', keys = ['SHTSTAT'], values = [True])
-    else:
-        self.updateHeaderInfo(header_flag='ext', keys = ['SHTSTAT','SHTOPEN1','SHTCLOS0'], values = [True,self.h_ext['SHTCLOS1'],self.h_ext['SHTOPEN0']])
-
-    chip.img = chip.img + pf_map
-
-    # renew header info
-    datetime_obs = datetime.utcfromtimestamp(pointing.timestamp)
-    datetime_obs = datetime_obs.replace(tzinfo=timezone.utc)
-    t_obs = Time(datetime_obs)
-    
-    ##ccd刷新2s,等待0.5s,开灯后等待0.5s,开始曝光
-    t_obs_renew = Time(t_obs.mjd - (2.) / 86400., format="mjd")
-
-    t_obs_utc = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(t_obs_renew.unix).replace(tzinfo=timezone.utc).timestamp(), 1))
-    self.updateHeaderInfo(header_flag='prim', keys = ['DATE-OBS'], values = [t_obs_utc.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5]])
-
-    #dark time : 
-    self.updateHeaderInfo(header_flag='ext', keys = ['DARKTIME'], values = [pointing.exp_time])
-
-    gc.collect()
-    return chip, filt, tel, pointing
\ No newline at end of file
diff --git a/ObservationSim/sim_steps/add_pattern_noise.py b/ObservationSim/sim_steps/add_pattern_noise.py
deleted file mode 100644
index 4fb2598ae15062d766d34207924497416abbd767..0000000000000000000000000000000000000000
--- a/ObservationSim/sim_steps/add_pattern_noise.py
+++ /dev/null
@@ -1,75 +0,0 @@
-from numpy.random import Generator, PCG64
-from ObservationSim.Instrument.Chip import ChipUtils as chip_utils
-from ObservationSim.Instrument.Chip import Effects
-
-def apply_PRNU(self, chip, filt, tel, pointing, catalog, obs_param):
-    chip.img *= chip.prnu_img
-    if self.overall_config["output_setting"]["prnu_output"] == True:
-        chip.prnu_img.write("%s/FlatImg_PRNU_%s.fits" % (self.chip_output.subdir, str(chip.chipID).rjust(2, '0')))
-    return chip, filt, tel, pointing
-
-def add_poisson_and_dark(self, chip, filt, tel, pointing, catalog, obs_param):
-    # Add dark current & Poisson noise
-    # Get exposure time
-    if (obs_param) and ("exptime" in obs_param) and (obs_param["exptime"] is not None):
-        exptime = obs_param["exptime"]
-    else:
-        exptime = pointing.exp_time
-    
-    if obs_param["add_dark"] == True:
-        chip.img, _ = chip_utils.add_poisson(img=chip.img,
-                                            chip=chip,
-                                            exptime=pointing.exp_time,
-                                            poisson_noise=chip.poisson_noise,
-                                            InputDark=None)
-    else:
-        chip.img, _ = chip_utils.add_poisson(img=chip.img, 
-                                            chip=self, 
-                                            exptime=exptime, 
-                                            poisson_noise=chip.poisson_noise, 
-                                            dark_noise=0.)
-    return chip, filt, tel, pointing
-
-def add_detector_defects(self, chip, filt, tel, pointing, catalog, obs_param):
-    # Add Hot Pixels or/and Dead Pixels
-    rgbadpix = Generator(PCG64(int(self.overall_config["random_seeds"]["seed_defective"]+chip.chipID)))
-    badfraction = 5E-5*(rgbadpix.random()*0.5+0.7)
-    chip.img = Effects.DefectivePixels(
-        chip.img, 
-        IfHotPix=obs_param["hot_pixels"], 
-        IfDeadPix=obs_param["dead_pixels"],
-        fraction=badfraction, 
-        seed=self.overall_config["random_seeds"]["seed_defective"]+chip.chipID, biaslevel=0)
-    # Apply Bad columns 
-    if obs_param["bad_columns"] == True:
-        chip.img = Effects.BadColumns(chip.img, 
-                                     seed=self.overall_config["random_seeds"]["seed_badcolumns"],  
-                                     chipid=chip.chipID)
-    return chip, filt, tel, pointing
-
-def add_nonlinearity(self, chip, filt, tel, pointing, catalog, obs_param):
-    self.chip_output.Log_info("  Applying Non-Linearity on the chip image")
-    chip.img = Effects.NonLinearity(GSImage=chip.img, 
-                                   beta1=5.e-7, 
-                                   beta2=0)
-    return chip, filt, tel, pointing
-
-def add_blooming(self, chip, filt, tel, pointing, catalog, obs_param):
-    self.chip_output.Log_info("  Applying CCD Saturation & Blooming")
-    chip.img = Effects.SaturBloom(GSImage=chip.img, 
-                                 nsect_x=1, 
-                                 nsect_y=1, 
-                                 fullwell=int(chip.full_well))
-    return chip, filt, tel, pointing
-
-def add_bias(self, chip, filt, tel, pointing, catalog, obs_param):
-    self.chip_output.Log_info("  Adding Bias level and 16-channel non-uniformity")
-    if obs_param["bias_16channel"] == True:
-        chip.img = Effects.AddBiasNonUniform16(chip.img, 
-                                              bias_level=float(chip.bias_level), 
-                                              nsecy = chip.nsecy, 
-                                              nsecx=chip.nsecx, 
-                                              seed=self.overall_config["random_seeds"]["seed_biasNonUniform"]+chip.chipID)
-    elif obs_param["bias_16channel"] == False:
-        chip.img += self.bias_level
-    return chip, filt, tel, pointing
diff --git a/ObservationSim/sim_steps/prepare_headers.py b/ObservationSim/sim_steps/prepare_headers.py
deleted file mode 100644
index bfd88e904612939a1adde6d56a6be08d1bacaa82..0000000000000000000000000000000000000000
--- a/ObservationSim/sim_steps/prepare_headers.py
+++ /dev/null
@@ -1,50 +0,0 @@
-from ObservationSim.Config.Header import generatePrimaryHeader, generateExtensionHeader
-
-def prepare_headers(self, chip, pointing):
-    self.h_prim = generatePrimaryHeader(
-        xlen=chip.npix_x, 
-        ylen=chip.npix_y, 
-        pointing_id = pointing.obs_id,
-        pointing_type_code = pointing.pointing_type_code, 
-        ra=pointing.ra, 
-        dec=pointing.dec, 
-        pixel_scale=chip.pix_scale,
-        time_pt = pointing.timestamp,
-        exptime=pointing.exp_time,
-        im_type=pointing.pointing_type,
-        sat_pos=[pointing.sat_x, pointing.sat_y, pointing.sat_z],
-        sat_vel=[pointing.sat_vx, pointing.sat_vy, pointing.sat_vz],
-        project_cycle=self.overall_config["project_cycle"],
-        run_counter=self.overall_config["run_counter"],
-        chip_name=str(chip.chipID).rjust(2, '0'))
-    self.h_ext = generateExtensionHeader(
-        chip=chip,
-        xlen=chip.npix_x, 
-        ylen=chip.npix_y, 
-        ra=pointing.ra, 
-        dec=pointing.dec, 
-        pa=pointing.img_pa.deg, 
-        gain=chip.gain, 
-        readout=chip.read_noise, 
-        dark=chip.dark_noise, 
-        saturation=90000, 
-        pixel_scale=chip.pix_scale, 
-        pixel_size=chip.pix_size,
-        xcen=chip.x_cen,
-        ycen=chip.y_cen,
-        extName=pointing.pointing_type,
-        timestamp = pointing.timestamp,
-        exptime = pointing.exp_time,
-        readoutTime = chip.readout_time,
-        t_shutter_open = pointing.t_shutter_open, 
-        t_shutter_close = pointing.t_shutter_close)
-
-    return self.h_prim, self.h_ext
-
-def updateHeaderInfo(self,header_flag='prim', keys = ['key'], values = [0]):
-    if header_flag == 'prim':
-        for key,value in zip(keys, values):
-            self.h_prim[key] = value
-    if header_flag == 'ext':
-        for key,value in zip(keys, values):
-            self.h_ext[key] = value
diff --git a/Catalog/C9_Catalog.py b/catalog/C9_Catalog.py
similarity index 73%
rename from Catalog/C9_Catalog.py
rename to catalog/C9_Catalog.py
index 23fea6583f7e25a527497b59a35700b17e6af469..6b9a0dcc059e89331e09e4f597d7795f2470c40a 100644
--- a/Catalog/C9_Catalog.py
+++ b/catalog/C9_Catalog.py
@@ -12,9 +12,9 @@ from astropy.table import Table
 from scipy import interpolate
 from datetime import datetime
 
-from ObservationSim.MockObject import CatalogBase, Star, Galaxy, Quasar
-from ObservationSim.MockObject._util import tag_sed, getObservedSED, getABMAG, integrate_sed_bandpass, comoving_dist
-from ObservationSim.Astrometry.Astrometry_util import on_orbit_obs_position
+from observation_sim.mock_objects import CatalogBase, Star, Galaxy, Quasar
+from observation_sim.mock_objects._util import tag_sed, getObservedSED, getABMAG, integrate_sed_bandpass, comoving_dist
+from observation_sim.astrometry.Astrometry_util import on_orbit_obs_position
 
 # (TEST)
 from astropy.cosmology import FlatLambdaCDM
@@ -34,23 +34,29 @@ except ImportError:
 
 NSIDE = 128
 
-bundle_file_list = ['galaxies_C6_bundle000199.h5','galaxies_C6_bundle000200.h5','galaxies_C6_bundle000241.h5','galaxies_C6_bundle000242.h5','galaxies_C6_bundle000287.h5','galaxies_C6_bundle000288.h5','galaxies_C6_bundle000714.h5','galaxies_C6_bundle000715.h5','galaxies_C6_bundle000778.h5','galaxies_C6_bundle000779.h5','galaxies_C6_bundle000842.h5','galaxies_C6_bundle000843.h5','galaxies_C6_bundle002046.h5','galaxies_C6_bundle002110.h5','galaxies_C6_bundle002111.h5','galaxies_C6_bundle002173.h5','galaxies_C6_bundle002174.h5','galaxies_C6_bundle002238.h5','galaxies_C6_bundle002596.h5','galaxies_C6_bundle002597.h5','galaxies_C6_bundle002656.h5','galaxies_C6_bundle002657.h5','galaxies_C6_bundle002711.h5','galaxies_C6_bundle002712.h5','galaxies_C6_bundle002844.h5','galaxies_C6_bundle002845.h5','galaxies_C6_bundle002884.h5','galaxies_C6_bundle002885.h5','galaxies_C6_bundle002921.h5','galaxies_C6_bundle002922.h5']
+bundle_file_list = ['galaxies_C6_bundle000199.h5', 'galaxies_C6_bundle000200.h5', 'galaxies_C6_bundle000241.h5', 'galaxies_C6_bundle000242.h5', 'galaxies_C6_bundle000287.h5', 'galaxies_C6_bundle000288.h5', 'galaxies_C6_bundle000714.h5', 'galaxies_C6_bundle000715.h5', 'galaxies_C6_bundle000778.h5', 'galaxies_C6_bundle000779.h5', 'galaxies_C6_bundle000842.h5', 'galaxies_C6_bundle000843.h5', 'galaxies_C6_bundle002046.h5', 'galaxies_C6_bundle002110.h5', 'galaxies_C6_bundle002111.h5',
+                    'galaxies_C6_bundle002173.h5', 'galaxies_C6_bundle002174.h5', 'galaxies_C6_bundle002238.h5', 'galaxies_C6_bundle002596.h5', 'galaxies_C6_bundle002597.h5', 'galaxies_C6_bundle002656.h5', 'galaxies_C6_bundle002657.h5', 'galaxies_C6_bundle002711.h5', 'galaxies_C6_bundle002712.h5', 'galaxies_C6_bundle002844.h5', 'galaxies_C6_bundle002845.h5', 'galaxies_C6_bundle002884.h5', 'galaxies_C6_bundle002885.h5', 'galaxies_C6_bundle002921.h5', 'galaxies_C6_bundle002922.h5']
 
-qsosed_file_list = ['quickspeclib_interp1d_run1.fits','quickspeclib_interp1d_run2.fits','quickspeclib_interp1d_run3.fits','quickspeclib_interp1d_run4.fits','quickspeclib_interp1d_run5.fits','quickspeclib_interp1d_run6.fits','quickspeclib_interp1d_run7.fits','quickspeclib_interp1d_run8.fits','quickspeclib_interp1d_run9.fits','quickspeclib_interp1d_run10.fits','quickspeclib_interp1d_run11.fits','quickspeclib_interp1d_run12.fits','quickspeclib_interp1d_run13.fits','quickspeclib_interp1d_run14.fits','quickspeclib_interp1d_run15.fits','quickspeclib_interp1d_run16.fits','quickspeclib_interp1d_run17.fits','quickspeclib_interp1d_run18.fits','quickspeclib_interp1d_run19.fits','quickspeclib_interp1d_run20.fits','quickspeclib_interp1d_run21.fits','quickspeclib_interp1d_run22.fits','quickspeclib_interp1d_run23.fits','quickspeclib_interp1d_run24.fits','quickspeclib_interp1d_run25.fits','quickspeclib_interp1d_run26.fits','quickspeclib_interp1d_run27.fits','quickspeclib_interp1d_run28.fits','quickspeclib_interp1d_run29.fits','quickspeclib_interp1d_run30.fits']
+qsosed_file_list = ['quickspeclib_interp1d_run1.fits', 'quickspeclib_interp1d_run2.fits', 'quickspeclib_interp1d_run3.fits', 'quickspeclib_interp1d_run4.fits', 'quickspeclib_interp1d_run5.fits', 'quickspeclib_interp1d_run6.fits', 'quickspeclib_interp1d_run7.fits', 'quickspeclib_interp1d_run8.fits', 'quickspeclib_interp1d_run9.fits', 'quickspeclib_interp1d_run10.fits', 'quickspeclib_interp1d_run11.fits', 'quickspeclib_interp1d_run12.fits', 'quickspeclib_interp1d_run13.fits', 'quickspeclib_interp1d_run14.fits', 'quickspeclib_interp1d_run15.fits',
+                    'quickspeclib_interp1d_run16.fits', 'quickspeclib_interp1d_run17.fits', 'quickspeclib_interp1d_run18.fits', 'quickspeclib_interp1d_run19.fits', 'quickspeclib_interp1d_run20.fits', 'quickspeclib_interp1d_run21.fits', 'quickspeclib_interp1d_run22.fits', 'quickspeclib_interp1d_run23.fits', 'quickspeclib_interp1d_run24.fits', 'quickspeclib_interp1d_run25.fits', 'quickspeclib_interp1d_run26.fits', 'quickspeclib_interp1d_run27.fits', 'quickspeclib_interp1d_run28.fits', 'quickspeclib_interp1d_run29.fits', 'quickspeclib_interp1d_run30.fits']
 
 # star_file_list = ['C7_Gaia_Galaxia_RA170DECm23_healpix.hdf5', 'C7_Gaia_Galaxia_RA180DECp60_healpix.hdf5', 'C7_Gaia_Galaxia_RA240DECp30_healpix.hdf5', 'C7_Gaia_Galaxia_RA300DECm60_healpix.hdf5', 'C7_Gaia_Galaxia_RA30DECm48_healpix.hdf5']
-star_center_list = [(170., -23.), (180., 60.), (240., 30.), (300., -60.), (30., -48.),[246.5, 40]]
+star_center_list = [(170., -23.), (180., 60.), (240., 30.),
+                    (300., -60.), (30., -48.), [246.5, 40]]
+
+star_file_list = ['C9_RA170_DECm23_calmag_Nside_128_healpix.hdf5', 'C9_RA180_DECp60_calmag_Nside_128_healpix.hdf5', 'C9_RA240_DECp30_calmag_Nside_128_healpix.hdf5',
+                  'C9_RA300_DECm60_calmag_Nside_128_healpix.hdf5', 'C9_RA30_DECm48_calmag_Nside_128_healpix.hdf5', 'trilegal_calMag_mpi_Nside_128_healpix.hdf5']
 
-star_file_list = ['C9_RA170_DECm23_calmag_Nside_128_healpix.hdf5', 'C9_RA180_DECp60_calmag_Nside_128_healpix.hdf5', 'C9_RA240_DECp30_calmag_Nside_128_healpix.hdf5', 'C9_RA300_DECm60_calmag_Nside_128_healpix.hdf5', 'C9_RA30_DECm48_calmag_Nside_128_healpix.hdf5','trilegal_calMag_mpi_Nside_128_healpix.hdf5']
 
 class StarParm(ctypes.Structure):
     _fields_ = [
-               ('logte',ctypes.c_float),
-               ('logg',ctypes.c_float),
-               ('Mass',ctypes.c_float),
-               ('Av', ctypes.c_float),
-               ('mu0', ctypes.c_float),
-               ('Z', ctypes.c_float)]
+        ('logte', ctypes.c_float),
+        ('logg', ctypes.c_float),
+        ('Mass', ctypes.c_float),
+        ('Av', ctypes.c_float),
+        ('mu0', ctypes.c_float),
+        ('Z', ctypes.c_float)]
+
 
 def get_bundleIndex(healpixID_ring, bundleOrder=4, healpixOrder=7):
     assert NSIDE == 2**healpixOrder
@@ -58,17 +64,19 @@ def get_bundleIndex(healpixID_ring, bundleOrder=4, healpixOrder=7):
     shift = 2*shift
 
     nside_bundle = 2**bundleOrder
-    nside_healpix= 2**healpixOrder
+    nside_healpix = 2**healpixOrder
 
-    healpixID_nest= hp.ring2nest(nside_healpix, healpixID_ring)
+    healpixID_nest = hp.ring2nest(nside_healpix, healpixID_ring)
     bundleID_nest = (healpixID_nest >> shift)
     bundleID_ring = hp.nest2ring(nside_bundle, bundleID_nest)
 
     return bundleID_ring
 
+
 def get_agnsed_file(bundle_file_name):
     return qsosed_file_list[bundle_file_list.index(bundle_file_name)]
 
+
 def get_star_cat(ra_pointing, dec_pointing):
     pointing_c = SkyCoord(ra=ra_pointing*U.deg, dec=dec_pointing*U.deg)
     max_dist = 10
@@ -81,6 +89,7 @@ def get_star_cat(ra_pointing, dec_pointing):
             max_dist = dist
     return return_star_path
 
+
 class Catalog(CatalogBase):
     def __init__(self, config, chip, pointing, chip_output, filt, **kwargs):
         super().__init__()
@@ -92,9 +101,9 @@ class Catalog(CatalogBase):
         self.filt = filt
         self.logger = chip_output.logger
 
-        with pkg_resources.path('Catalog.data', 'SLOAN_SDSS.g.fits') as filter_path:
+        with pkg_resources.path('catalog.data', 'SLOAN_SDSS.g.fits') as filter_path:
             self.normF_star = Table.read(str(filter_path))
-        
+
         self.config = config
         self.chip = chip
         self.pointing = pointing
@@ -103,12 +112,14 @@ class Catalog(CatalogBase):
 
         if "star_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["star_cat"] and not config["catalog_options"]["galaxy_only"]:
             # Get the cloest star catalog file
-            star_file_name = get_star_cat(ra_pointing=self.pointing.ra, dec_pointing=self.pointing.dec)
-            star_path = os.path.join(config["catalog_options"]["input_path"]["star_cat"], star_file_name)
+            star_file_name = get_star_cat(
+                ra_pointing=self.pointing.ra, dec_pointing=self.pointing.dec)
+            star_path = os.path.join(
+                config["catalog_options"]["input_path"]["star_cat"], star_file_name)
             self.star_path = os.path.join(self.cat_dir, star_path)
             self.star_SED_path = config["catalog_options"]["SED_templates_path"]["star_SED"]
             self._load_SED_lib_star()
-        
+
         if "galaxy_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["galaxy_cat"] and not config["catalog_options"]["star_only"]:
             galaxy_dir = config["catalog_options"]["input_path"]["galaxy_cat"]
             self.galaxy_path = os.path.join(self.cat_dir, galaxy_dir)
@@ -120,7 +131,8 @@ class Catalog(CatalogBase):
             self.AGN_SED_path = config["catalog_options"]["SED_templates_path"]["AGN_SED"]
 
         if "rotateEll" in config["catalog_options"]:
-            self.rotation = np.radians(float(config["catalog_options"]["rotateEll"]))
+            self.rotation = np.radians(
+                float(config["catalog_options"]["rotateEll"]))
         else:
             self.rotation = 0.
 
@@ -129,17 +141,19 @@ class Catalog(CatalogBase):
 
         self._get_healpix_list()
         self._load()
-    
+
     def _add_output_columns_header(self):
         self.add_hdr = " av stellarmass dm teff logg feh"
         self.add_hdr += " bulgemass diskmass detA e1 e2 kappa g1 g2 size galType veldisp "
 
         self.add_fmt = "%8.4f %8.4f %8.4f %8.4f %8.4f %8.4f"
         self.add_fmt += " %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %4d %8.4f "
-        self.chip_output.update_output_header(additional_column_names=self.add_hdr)
+        self.chip_output.update_output_header(
+            additional_column_names=self.add_hdr)
 
     def _get_healpix_list(self):
-        self.sky_coverage = self.chip.getSkyCoverageEnlarged(self.chip.img.wcs, margin=0.2)
+        self.sky_coverage = self.chip.getSkyCoverageEnlarged(
+            self.chip.img.wcs, margin=0.2)
         ra_min, ra_max, dec_min, dec_max = self.sky_coverage.xmin, self.sky_coverage.xmax, self.sky_coverage.ymin, self.sky_coverage.ymax
         ra = np.deg2rad(np.array([ra_min, ra_max, ra_max, ra_min]))
         dec = np.deg2rad(np.array([dec_max, dec_max, dec_min, dec_min]))
@@ -167,27 +181,31 @@ class Catalog(CatalogBase):
     #     self.tempSED_star = h5.File(self.star_SED_path,'r')
     def _load_SED_lib_star(self):
         # self.tempSED_star = h5.File(self.star_SED_path,'r')
-        with pkg_resources.path('Catalog.data', 'starSpecInterp.so') as ddl_path:
+        with pkg_resources.path('catalog.data', 'starSpecInterp.so') as ddl_path:
             self.starDDL = ctypes.CDLL(str(ddl_path))
-        self.starDDL.loadSpecLibs.argtypes=[ctypes.c_char_p, ctypes.c_char_p]
-        self.starDDL.loadExts.argtypes=[ctypes.c_char_p]
-        nwv = self.starDDL.loadSpecLibs(str.encode(os.path.join(self.star_SED_path,'file_BT-Settl_CSST_wl1000-24000_R1000.par')),str.encode(self.star_SED_path))
-        self.starDDL.loadExts(str.encode(os.path.join(self.star_SED_path,"Ext_odonnell94_R3.1_CSST_wl1000-24000_R1000.fits")))
+        self.starDDL.loadSpecLibs.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
+        self.starDDL.loadExts.argtypes = [ctypes.c_char_p]
+        nwv = self.starDDL.loadSpecLibs(str.encode(os.path.join(
+            self.star_SED_path, 'file_BT-Settl_CSST_wl1000-24000_R1000.par')), str.encode(self.star_SED_path))
+        self.starDDL.loadExts(str.encode(os.path.join(
+            self.star_SED_path, "Ext_odonnell94_R3.1_CSST_wl1000-24000_R1000.fits")))
         self.star_spec_len = nwv
 
     def _interp_star_sed(self, obj):
         spec = (ctypes.c_float*self.star_spec_len)()
         wave = (ctypes.c_float*self.star_spec_len)()
-        self.starDDL.interpSingleStar.argtypes=[ctypes.Structure, ctypes.POINTER(ctypes.c_float)]
+        self.starDDL.interpSingleStar.argtypes = [
+            ctypes.Structure, ctypes.POINTER(ctypes.c_float)]
         # s=Star(obj.param['teff'], obj.param['grav''], obj.paramstar['mwmsc_mass'], obj.param['AV'], obj.param['DM'], obj.param['z_met'])
-        s=StarParm(obj.param['teff'], obj.param['logg'], obj.param['stellarMass'], obj.param['av'], obj.param['DM'], obj.param['feh'])
+        s = StarParm(obj.param['teff'], obj.param['logg'], obj.param['stellarMass'],
+                     obj.param['av'], obj.param['DM'], obj.param['feh'])
 
         self.starDDL.interpSingleStar(s, spec, wave)
 
         rv_c = obj.param['rv']/(atcons.c.value/1000.)
         Doppler_factor = np.sqrt((1+rv_c)/(1-rv_c))
         wave_RV = wave*Doppler_factor
-        return wave_RV, np.power(10,spec[:])
+        return wave_RV, np.power(10, spec[:])
 
     def _load_SED_lib_gals(self):
         pcs = h5.File(os.path.join(self.galaxy_SED_path, "pcs.h5"), "r")
@@ -231,10 +249,10 @@ class Catalog(CatalogBase):
             )
 
         for igals in range(ngals):
-            # # (TEST)
-            # if igals > 100:
-            #     break
-            
+            # (TEST)
+            if igals > 100:
+                break
+
             param = self.initialize_param()
             param['ra'] = ra_arr[igals]
             param['dec'] = dec_arr[igals]
@@ -243,12 +261,13 @@ class Catalog(CatalogBase):
 
             if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200):
                 continue
-            
+
             # param['mag_use_normal'] = gals['mag_csst_%s'%(self.filt.filter_type)][igals]
             if self.filt.filter_type == 'NUV':
                 param['mag_use_normal'] = gals['mag_csst_nuv'][igals]
             else:
-                param['mag_use_normal'] = gals['mag_csst_%s'%(self.filt.filter_type)][igals]
+                param['mag_use_normal'] = gals['mag_csst_%s' %
+                                               (self.filt.filter_type)][igals]
             if self.filt.is_too_dim(mag=param['mag_use_normal'], margin=self.config["obs_setting"]["mag_lim_margin"]):
                 continue
 
@@ -259,26 +278,25 @@ class Catalog(CatalogBase):
             param['kappa'] = gals['kappa'][igals]
             param['e1'] = gals['ellipticity_true'][igals][0]
             param['e2'] = gals['ellipticity_true'][igals][1]
-            
+
             # For shape calculation
             param['e1'], param['e2'], param['ell_total'] = self.rotate_ellipticity(
-                                                                    e1=gals['ellipticity_true'][igals][0],
-                                                                    e2=gals['ellipticity_true'][igals][1],
-                                                                    rotation=self.rotation,
-                                                                    unit='radians')
+                e1=gals['ellipticity_true'][igals][0],
+                e2=gals['ellipticity_true'][igals][1],
+                rotation=self.rotation,
+                unit='radians')
             # param['ell_total'] = np.sqrt(param['e1']**2 + param['e2']**2)
             if param['ell_total'] > 0.9:
                 continue
             # phi_e = cmath.phase(complex(param['e1'], param['e2']))
             # param['e1'] = param['ell_total'] * np.cos(phi_e + 2*self.rotation)
             # param['e2'] = param['ell_total'] * np.sin(phi_e + 2*self.rotation)
-            
+
             param['e1_disk'] = param['e1']
             param['e2_disk'] = param['e2']
             param['e1_bulge'] = param['e1']
             param['e2_bulge'] = param['e2']
 
-
             param['delta_ra'] = 0
             param['delta_dec'] = 0
 
@@ -295,7 +313,8 @@ class Catalog(CatalogBase):
             param['bulge_sersic_idx'] = 4.
 
             # Sizes
-            param['bfrac'] = param['bulgemass']/(param['bulgemass'] + param['diskmass'])
+            param['bfrac'] = param['bulgemass'] / \
+                (param['bulgemass'] + param['diskmass'])
             if param['bfrac'] >= 0.6:
                 param['hlr_bulge'] = param['size']
                 param['hlr_disk'] = param['size'] * (1. - param['bfrac'])
@@ -310,14 +329,15 @@ class Catalog(CatalogBase):
             # Others
             param['galType'] = gals['type'][igals]
             param['veldisp'] = gals['veldisp'][igals]
-            
+
             # TEST no redening and no extinction
             param['av'] = 0.0
             param['redden'] = 0
 
             # TEMP
             self.ids += 1
-            param['id'] = '%06d'%(int(pix_id)) + '%06d'%(cat_id) + '%08d'%(igals)
+            param['id'] = '%06d' % (int(pix_id)) + \
+                '%06d' % (cat_id) + '%08d' % (igals)
 
             # Is this an Quasar?
             param['qsoindex'] = gals['qsoindex'][igals]
@@ -332,20 +352,20 @@ class Catalog(CatalogBase):
                 # First add QSO model
                 obj = Quasar(param_qso, logger=self.logger)
                 # Need to deal with additional output columns
-                obj.additional_output_str = self.add_fmt%(0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
-                                                        0, 0.)
+                obj.additional_output_str = self.add_fmt % (0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
+                                                            0, 0.)
                 self.objs.append(obj)
                 # Then add host galaxy model
                 param['star'] = 0   # Galaxy
                 param['agnsed_file'] = ""
                 obj = Galaxy(param, logger=self.logger)
-            
+
             # Need to deal with additional output columns for (host) galaxy
-            obj.additional_output_str = self.add_fmt%(0., 0., 0., 0., 0., 0.,
-                                                    param['bulgemass'], param['diskmass'], param['detA'],
-                                                    param['e1'], param['e2'], param['kappa'], param['g1'], param['g2'], param['size'],
-                                                    param['galType'], param['veldisp'])
-            
+            obj.additional_output_str = self.add_fmt % (0., 0., 0., 0., 0., 0.,
+                                                        param['bulgemass'], param['diskmass'], param['detA'],
+                                                        param['e1'], param['e2'], param['kappa'], param['g1'], param['g2'], param['size'],
+                                                        param['galType'], param['veldisp'])
+
             self.objs.append(obj)
 
     def _load_stars(self, stars, pix_id=None):
@@ -387,8 +407,8 @@ class Catalog(CatalogBase):
             )
         for istars in range(nstars):
             # (TEST)
-            # if istars > 100:
-            #     break
+            if istars > 100:
+                break
 
             param = self.initialize_param()
             param['ra'] = ra_arr[istars]
@@ -404,7 +424,7 @@ class Catalog(CatalogBase):
             param['mag_use_normal'] = stars['app_sdss_g'][istars]
             self.ids += 1
 
-            param['id'] = '%06d'%(int(pix_id)) + '%08d'%(istars)
+            param['id'] = '%06d' % (int(pix_id)) + '%08d' % (istars)
             # param['sed_type'] = istars
             # param['model_tag'] = ''
             param['teff'] = stars['teff'][istars]
@@ -412,29 +432,28 @@ class Catalog(CatalogBase):
             param['feh'] = stars['z_met'][istars]
             param['stellarMass'] = stars['mass'][istars]
 
-
             param['av'] = stars['AV'][istars]
             param['DM'] = stars['DM'][istars]
             # param['z_met'] = stars['z_met'][istars]
 
             param['z'] = 0.0
             param['star'] = 1   # Star
-            
+
             try:
                 obj = Star(param, logger=self.logger)
             except Exception as e:
                 print(e)
 
             # Append additional output columns to the .cat file
-            obj.additional_output_str = self.add_fmt%(param["av"], param['stellarMass'], param['DM'], param['teff'], param['logg'], param['feh'],
-                                                    0., 0., 0., 0., 0., 0., 0., 0., 0., -1, 0.)
+            obj.additional_output_str = self.add_fmt % (param["av"], param['stellarMass'], param['DM'], param['teff'], param['logg'], param['feh'],
+                                                        0., 0., 0., 0., 0., 0., 0., 0., 0., -1, 0.)
 
             self.objs.append(obj)
 
     def _load(self, **kwargs):
         self.objs = []
         self.ids = 0
-        
+
         if "star_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["star_cat"] and not self.config["catalog_options"]["galaxy_only"]:
             star_cat = h5.File(self.star_path, 'r')['star_catalog']
             for pix in self.pix_list:
@@ -445,11 +464,11 @@ class Catalog(CatalogBase):
                 except Exception as e:
                     self.logger.error(str(e))
                     # print(e)
-        
+
         if "galaxy_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["galaxy_cat"] and not self.config["catalog_options"]["star_only"]:
             for pix in self.pix_list:
                 try:
-                    bundleID  = get_bundleIndex(pix)
+                    bundleID = get_bundleIndex(pix)
                     bundle_file = "galaxies_C6_bundle{:06}.h5".format(bundleID)
                     file_path = os.path.join(self.galaxy_path, bundle_file)
                     gals_cat = h5.File(file_path, 'r')['galaxies']
@@ -460,7 +479,8 @@ class Catalog(CatalogBase):
                     agnsed_path = os.path.join(self.AGN_SED_path, agnsed_file)
                     self.agn_seds[agnsed_file] = fits.open(agnsed_path)[0].data
 
-                    self._load_gals(gals, pix_id=pix, cat_id=bundleID, agnsed_file=agnsed_file)
+                    self._load_gals(gals, pix_id=pix,
+                                    cat_id=bundleID, agnsed_file=agnsed_file)
 
                     del gals
                 except Exception as e:
@@ -469,8 +489,9 @@ class Catalog(CatalogBase):
                     print(e)
 
         if self.logger is not None:
-            self.logger.info("maximum galaxy size: %.4f"%(self.max_size))
-            self.logger.info("number of objects in catalog: %d"%(len(self.objs)))
+            self.logger.info("maximum galaxy size: %.4f" % (self.max_size))
+            self.logger.info("number of objects in catalog: %d" %
+                             (len(self.objs)))
         else:
             print("number of objects in catalog: ", len(self.objs))
 
@@ -500,7 +521,8 @@ class Catalog(CatalogBase):
                 )
                 wave, flux = sed_data[0], sed_data[1]
             elif obj.type == 'quasar':
-                flux = self.agn_seds[obj.agnsed_file][int(obj.qsoindex)] * 1e-17
+                flux = self.agn_seds[obj.agnsed_file][int(
+                    obj.qsoindex)] * 1e-17
                 flux[flux < 0] = 0.
                 wave = self.lamb_gal * (1.0 + obj.z)
         else:
@@ -514,10 +536,14 @@ class Catalog(CatalogBase):
         if obj.type == 'quasar':
             # integrate to get the magnitudes
             sed_photon = np.array([sed['WAVELENGTH'], sed['FLUX']]).T
-            sed_photon = galsim.LookupTable(x=np.array(sed_photon[:, 0]), f=np.array(sed_photon[:, 1]), interpolant='nearest')
-            sed_photon = galsim.SED(sed_photon, wave_type='A', flux_type='1', fast=False)
-            interFlux = integrate_sed_bandpass(sed=sed_photon, bandpass=self.filt.bandpass_full)
-            obj.param['mag_use_normal'] = getABMAG(interFlux, self.filt.bandpass_full)
+            sed_photon = galsim.LookupTable(x=np.array(sed_photon[:, 0]), f=np.array(
+                sed_photon[:, 1]), interpolant='nearest')
+            sed_photon = galsim.SED(
+                sed_photon, wave_type='A', flux_type='1', fast=False)
+            interFlux = integrate_sed_bandpass(
+                sed=sed_photon, bandpass=self.filt.bandpass_full)
+            obj.param['mag_use_normal'] = getABMAG(
+                interFlux, self.filt.bandpass_full)
             # mag = getABMAG(interFlux, self.filt.bandpass_full)
             # print("mag diff = %.3f"%(mag - obj.param['mag_use_normal']))
         del wave
diff --git a/Catalog/Catalog_example.py b/catalog/Catalog_example.py
similarity index 94%
rename from Catalog/Catalog_example.py
rename to catalog/Catalog_example.py
index 24c6cf66abab5fb67623c397cc4df3c320fc7495..99fb1768beac34319c2ef1efcbc4e743b72478f3 100644
--- a/Catalog/Catalog_example.py
+++ b/catalog/Catalog_example.py
@@ -4,15 +4,16 @@ import astropy.constants as cons
 from astropy.table import Table
 from scipy import interpolate
 
-from ObservationSim.MockObject import CatalogBase, Star, Galaxy, Quasar
+from observation_sim.mock_objects import CatalogBase, Star, Galaxy, Quasar
+
 
 class Catalog(CatalogBase):
     """An user customizable class for reading in catalog(s) of objects and SEDs.
-    
+
     NOTE: must inherit the "CatalogBase" abstract class
 
     ...
-    
+
     Attributes
     ----------
     cat_dir : str
@@ -24,7 +25,7 @@ class Catalog(CatalogBase):
     objs : list
         a list of ObservationSim.MockObject (Star, Galaxy, or Quasar)
         NOTE: must have "obj" list when implement your own Catalog
-    
+
     Methods
     ----------
     load_sed(obj, **kwargs):
@@ -32,9 +33,10 @@ class Catalog(CatalogBase):
     load_norm_filt(obj):
         load the filter throughput for the input catalog's photometric system.
     """
+
     def __init__(self, config, chip, **kwargs):
         """Constructor method.
-        
+
         Parameters
         ----------
         config : dict
@@ -44,20 +46,22 @@ class Catalog(CatalogBase):
         **kwargs : dict
             other needed input parameters (in key-value pairs), please modify corresponding
             initialization call in "ObservationSim.py" as you need.
-        
+
         Returns
         ----------
         None
         """
-        
+
         super().__init__()
-        self.cat_dir = os.path.join(config["data_dir"], config["catalog_options"]["input_path"]["cat_dir"])
+        self.cat_dir = os.path.join(
+            config["data_dir"], config["catalog_options"]["input_path"]["cat_dir"])
         self.chip = chip
         if "star_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["star_cat"]:
             star_file = config["catalog_options"]["input_path"]["star_cat"]
             star_SED_file = config["catalog_options"]["SED_templates_path"]["star_SED"]
             self.star_path = os.path.join(self.cat_dir, star_file)
-            self.star_SED_path = os.path.join(config["data_dir"], star_SED_file)
+            self.star_SED_path = os.path.join(
+                config["data_dir"], star_SED_file)
         # NOTE: must call _load() method here to read in all objects
         self.objs = []
         self._load()
@@ -67,7 +71,7 @@ class Catalog(CatalogBase):
 
         This is a must implemented method which is used to read in all objects, and
         then convert them to ObservationSim.MockObject (Star, Galaxy, or Quasar).
-        
+
         Currently, 
         the model of ObservationSim.MockObject.Star class requires:
             param["star"] : int
@@ -83,7 +87,7 @@ class Catalog(CatalogBase):
                 NOTE: if that filter is not the corresponding CSST filter, the 
                 load_norm_filt(obj) function must be implemented to load the filter
                 throughput of that particular photometric system
-        
+
         the model of ObservationSim.MockObject.Galaxy class requires:
             param["star"] : int
                 specify the object type: 0: galaxy, 1: star, 2: quasar
@@ -173,7 +177,8 @@ class Catalog(CatalogBase):
         """
 
         if obj.type == 'star':
-            wave = Table.read(self.star_SED_path, path=f"/SED/wave_{obj.model_tag}")
+            wave = Table.read(self.star_SED_path,
+                              path=f"/SED/wave_{obj.model_tag}")
             flux = Table.read(self.star_SED_path, path=f"/SED/{obj.sed_type}")
             wave, flux = wave['col0'].data, flux['col0'].data
         else:
@@ -203,4 +208,4 @@ class Catalog(CatalogBase):
                 norm_filt["WAVELENGTH"] : wavelengthes in Angstroms
                 norm_filt["SENSITIVITY"] : efficiencies
         """
-        return None
\ No newline at end of file
+        return None
diff --git a/Catalog/data/SLOAN_SDSS.g.fits b/catalog/data/SLOAN_SDSS.g.fits
similarity index 100%
rename from Catalog/data/SLOAN_SDSS.g.fits
rename to catalog/data/SLOAN_SDSS.g.fits
diff --git a/Catalog/data/__init__.py b/catalog/data/__init__.py
similarity index 100%
rename from Catalog/data/__init__.py
rename to catalog/data/__init__.py
diff --git a/Catalog/data/lsst_throuput_g.fits b/catalog/data/lsst_throuput_g.fits
similarity index 100%
rename from Catalog/data/lsst_throuput_g.fits
rename to catalog/data/lsst_throuput_g.fits
diff --git a/Catalog/data/starSpecInterp.so b/catalog/data/starSpecInterp.so
similarity index 100%
rename from Catalog/data/starSpecInterp.so
rename to catalog/data/starSpecInterp.so
diff --git a/Catalog/testCat_fits.py b/catalog/testCat_fits.py
similarity index 71%
rename from Catalog/testCat_fits.py
rename to catalog/testCat_fits.py
index 869095be06d1657f433672b464a10582330df006..6ae1bada7eb8b6ff34db22ec4aaa6f725de69219 100644
--- a/Catalog/testCat_fits.py
+++ b/catalog/testCat_fits.py
@@ -11,12 +11,12 @@ from astropy.table import Table
 from scipy import interpolate
 from datetime import datetime
 
-from ObservationSim.MockObject import CatalogBase, Star, Galaxy, Quasar, Stamp
-from ObservationSim.MockObject._util import tag_sed, getObservedSED, getABMAG, integrate_sed_bandpass, comoving_dist
-from ObservationSim.Astrometry.Astrometry_util import on_orbit_obs_position
+from observation_sim.mock_objects import CatalogBase, Star, Galaxy, Quasar, Stamp
+from observation_sim.mock_objects._util import tag_sed, getObservedSED, getABMAG, integrate_sed_bandpass, comoving_dist
+from observation_sim.astrometry.Astrometry_util import on_orbit_obs_position
 
 import astropy.io.fits as fitsio
-from ObservationSim.MockObject._util import seds, sed_assign, extAv
+from observation_sim.mock_objects._util import seds, sed_assign, extAv
 
 # (TEST)
 from astropy.cosmology import FlatLambdaCDM
@@ -31,11 +31,12 @@ except ImportError:
 
 NSIDE = 128
 
+
 class Catalog(CatalogBase):
     def __init__(self, config, chip, pointing, chip_output, filt, **kwargs):
         super().__init__()
         self.cat_dir = config["catalog_options"]["input_path"]["cat_dir"]
-        self.seed_Av = 121212 #config["catalog_options"]["seed_Av"]
+        self.seed_Av = 121212  # config["catalog_options"]["seed_Av"]
 
         # (TEST)
         self.cosmo = FlatLambdaCDM(H0=67.66, Om0=0.3111)
@@ -44,11 +45,11 @@ class Catalog(CatalogBase):
         self.filt = filt
         self.logger = chip_output.logger
 
-        with pkg_resources.path('Catalog.data', 'SLOAN_SDSS.g.fits') as filter_path:
+        with pkg_resources.path('catalog.data', 'SLOAN_SDSS.g.fits') as filter_path:
             self.normF_star = Table.read(str(filter_path))
-        with pkg_resources.path('Catalog.data', 'lsst_throuput_g.fits') as filter_path:
+        with pkg_resources.path('catalog.data', 'lsst_throuput_g.fits') as filter_path:
             self.normF_galaxy = Table.read(str(filter_path))
-        
+
         self.config = config
         self.chip = chip
         self.pointing = pointing
@@ -58,24 +59,27 @@ class Catalog(CatalogBase):
         if "stamp_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["stamp_cat"] and config["catalog_options"]["stamp_yes"]:
             stamp_file = config["catalog_options"]["input_path"]["stamp_cat"]
             self.stamp_path = os.path.join(self.cat_dir, stamp_file)
-            #self.stamp_SED_path = os.path.join(config["data_dir"], config["SED_templates_path"]["stamp_SED"]) ###shoule be stamp-SED
-            #self._load_SED_lib_stamps() ###shoule be stamp-SED
-            self.tempSed_gal, self.tempRed_gal = seds("galaxy.list", seddir="/public/home/chengliang/CSSOSDataProductsSims/testCats/Templates/Galaxy/") #only for test
+            # self.stamp_SED_path = os.path.join(config["data_dir"], config["SED_templates_path"]["stamp_SED"]) ###shoule be stamp-SED
+            # self._load_SED_lib_stamps() ###shoule be stamp-SED
+            self.tempSed_gal, self.tempRed_gal = seds(
+                "galaxy.list", seddir="/public/home/chengliang/CSSOSDataProductsSims/testCats/Templates/Galaxy/")  # only for test
 
         self._add_output_columns_header()
         self._get_healpix_list()
         self._load()
-    
+
     def _add_output_columns_header(self):
         self.add_hdr = " model_tag teff logg feh"
         self.add_hdr += " bulgemass diskmass detA e1 e2 kappa g1 g2 size galType veldisp "
 
         self.add_fmt = " %10s %8.4f %8.4f %8.4f"
         self.add_fmt += " %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %4d %8.4f "
-        self.chip_output.update_output_header(additional_column_names=self.add_hdr)
+        self.chip_output.update_output_header(
+            additional_column_names=self.add_hdr)
 
     def _get_healpix_list(self):
-        self.sky_coverage = self.chip.getSkyCoverageEnlarged(self.chip.img.wcs, margin=0.2)
+        self.sky_coverage = self.chip.getSkyCoverageEnlarged(
+            self.chip.img.wcs, margin=0.2)
         ra_min, ra_max, dec_min, dec_max = self.sky_coverage.xmin, self.sky_coverage.xmax, self.sky_coverage.ymin, self.sky_coverage.ymax
         ra = np.deg2rad(np.array([ra_min, ra_max, ra_max, ra_min]))
         dec = np.deg2rad(np.array([dec_max, dec_max, dec_min, dec_min]))
@@ -94,7 +98,7 @@ class Catalog(CatalogBase):
 
     def load_norm_filt(self, obj):
         if obj.type == "stamp":
-            return self.normF_galaxy  ###normalize_filter for stamp
+            return self.normF_galaxy  # normalize_filter for stamp
         else:
             return None
 
@@ -102,35 +106,38 @@ class Catalog(CatalogBase):
         print("debug:: load_stamps")
         nstamps = len(stamps['filename'])
         self.rng_sedGal = random.Random()
-        self.rng_sedGal.seed(float(pix_id)) # Use healpix index as the random seed
+        # Use healpix index as the random seed
+        self.rng_sedGal.seed(float(pix_id))
         self.ud = galsim.UniformDeviate(pix_id)
 
         for istamp in range(nstamps):
             print("debug::", istamp)
-            fitsfile = os.path.join(self.cat_dir, "stampCats/"+stamps['filename'][istamp].decode('utf-8'))
+            fitsfile = os.path.join(
+                self.cat_dir, "stampCats/"+stamps['filename'][istamp].decode('utf-8'))
             print("debug::", istamp, fitsfile)
-            hdu=fitsio.open(fitsfile)
+            hdu = fitsio.open(fitsfile)
 
             param = self.initialize_param()
-            param['id']   = hdu[0].header['index'] #istamp
+            param['id'] = hdu[0].header['index']  # istamp
             param['star'] = 3      # Stamp type in .cat file
             param['ra'] = hdu[0].header['ra']
-            param['dec']= hdu[0].header['dec']
-            param['pixScale']= hdu[0].header['pixScale']
-            #param['srcGalaxyID'] = hdu[0].header['srcGID']
-            #param['mu']= hdu[0].header['mu']
-            #param['PA']= hdu[0].header['PA']
-            #param['bfrac']= hdu[0].header['bfrac']
-            #param['z']= hdu[0].header['z']
-            param['mag_use_normal'] = hdu[0].header['mag_g'] #gals['mag_true_g_lsst']
+            param['dec'] = hdu[0].header['dec']
+            param['pixScale'] = hdu[0].header['pixScale']
+            # param['srcGalaxyID'] = hdu[0].header['srcGID']
+            # param['mu']= hdu[0].header['mu']
+            # param['PA']= hdu[0].header['PA']
+            # param['bfrac']= hdu[0].header['bfrac']
+            # param['z']= hdu[0].header['z']
+            # gals['mag_true_g_lsst']
+            param['mag_use_normal'] = hdu[0].header['mag_g']
 
             # Apply astrometric modeling
             # in C3 case only aberration
             param['ra_orig'] = param['ra']
-            param['dec_orig']= param['dec']
+            param['dec_orig'] = param['dec']
             if self.config["obs_setting"]["enable_astrometric_model"]:
-                ra_list = [param['ra']] #ra_arr.tolist()
-                dec_list= [param['dec']] #dec_arr.tolist()
+                ra_list = [param['ra']]  # ra_arr.tolist()
+                dec_list = [param['dec']]  # dec_arr.tolist()
                 pmra_list = np.zeros(1).tolist()
                 pmdec_list = np.zeros(1).tolist()
                 rv_list = np.zeros(1).tolist()
@@ -157,19 +164,20 @@ class Catalog(CatalogBase):
                     input_time_str=time_str
                 )
                 param['ra'] = ra_arr[0]
-                param['dec']= dec_arr[0]
+                param['dec'] = dec_arr[0]
 
             # Assign each galaxy a template SED
-            param['sed_type'] = sed_assign(phz=param['z'], btt=param['bfrac'], rng=self.rng_sedGal)
+            param['sed_type'] = sed_assign(
+                phz=param['z'], btt=param['bfrac'], rng=self.rng_sedGal)
             param['redden'] = self.tempRed_gal[param['sed_type']]
             param['av'] = 0.0
             param['redden'] = 0
             param['mu'] = 1
 
-            #param["CSSTmag"]= True
-            #param["mag_r"] = 20.
-            #param['']
-            ###more keywords for stamp###
+            # param["CSSTmag"]= True
+            # param["mag_r"] = 20.
+            # param['']
+            ### more keywords for stamp###
             param['image'] = hdu[0].data
             param['image'] = param['image']/(np.sum(param['image']))
             obj = Stamp(param)
@@ -181,12 +189,12 @@ class Catalog(CatalogBase):
 
         if "stamp_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["stamp_cat"] and self.config["catalog_options"]["stamp_yes"]:
             stamps_cat = h5.File(self.stamp_path, 'r')['Stamps']
-            print("debug::",stamps_cat.keys())
+            print("debug::", stamps_cat.keys())
 
             for pix in self.pix_list:
                 try:
                     stamps = stamps_cat[str(pix)]
-                    print("debug::",stamps.keys())
+                    print("debug::", stamps.keys())
                     self._load_stamps(stamps, pix_id=pix)
                     del stamps
                 except Exception as e:
@@ -194,12 +202,12 @@ class Catalog(CatalogBase):
                     print(e)
 
         if self.logger is not None:
-            self.logger.info("maximum galaxy size: %.4f"%(self.max_size))
-            self.logger.info("number of objects in catalog: %d"%(len(self.objs)))
+            self.logger.info("maximum galaxy size: %.4f" % (self.max_size))
+            self.logger.info("number of objects in catalog: %d" %
+                             (len(self.objs)))
         else:
             print("number of objects in catalog: ", len(self.objs))
 
-
     def load_sed(self, obj, **kwargs):
         if obj.type == 'stamp':
             sed_data = getObservedSED(
@@ -217,7 +225,7 @@ class Catalog(CatalogBase):
         # erg/s/cm2/A --> photon/s/m2/A
         all_sed = y * lamb / (cons.h.value * cons.c.value) * 1e-13
         sed = Table(np.array([lamb, all_sed]).T, names=('WAVELENGTH', 'FLUX'))
-        
+
         del wave
         del flux
         return sed
diff --git a/ObservationSim/ObservationSim.py b/observation_sim/ObservationSim.py
similarity index 73%
rename from ObservationSim/ObservationSim.py
rename to observation_sim/ObservationSim.py
index f25551e3e06e5b73786d3bfb893692f742591a49..051d6d18757b97151e4e56b191d6492f8fa6ce0a 100755
--- a/ObservationSim/ObservationSim.py
+++ b/observation_sim/ObservationSim.py
@@ -8,24 +8,26 @@ from datetime import datetime
 
 import traceback
 
-from ObservationSim.Config import ChipOutput
-from ObservationSim.Instrument import Telescope, Filter, FilterParam, FocalPlane, Chip
-from ObservationSim.Instrument.Chip import Effects
-from ObservationSim.Instrument.Chip import ChipUtils as chip_utils
-from ObservationSim.Astrometry.Astrometry_util import on_orbit_obs_position
-from ObservationSim.sim_steps import SimSteps, SIM_STEP_TYPES
+from observation_sim.config import ChipOutput
+from observation_sim.instruments import Telescope, Filter, FilterParam, FocalPlane, Chip
+from observation_sim.instruments.chip import effects
+from observation_sim.instruments.chip import chip_utils as chip_utils
+from observation_sim.astrometry.Astrometry_util import on_orbit_obs_position
+from observation_sim.sim_steps import SimSteps, SIM_STEP_TYPES
+
 
 class Observation(object):
     def __init__(self, config, Catalog, work_dir=None, data_dir=None):
         self.config = config
         self.tel = Telescope()
-        self.filter_param = FilterParam() 
+        self.filter_param = FilterParam()
         self.Catalog = Catalog
 
     def prepare_chip_for_exposure(self, chip, ra_cen, dec_cen, pointing, wcs_fp=None):
         # Get WCS for the focal plane
         if wcs_fp == None:
-            wcs_fp = self.focal_plane.getTanWCS(ra_cen, dec_cen, pointing.img_pa, chip.pix_scale)
+            wcs_fp = self.focal_plane.getTanWCS(
+                ra_cen, dec_cen, pointing.img_pa, chip.pix_scale)
 
         # Create chip Image
         chip.img = galsim.ImageF(chip.npix_x, chip.npix_y)
@@ -35,29 +37,36 @@ class Observation(object):
         # Get random generators for this chip
         chip.rng_poisson, chip.poisson_noise = chip_utils.get_poisson(
             seed=int(self.config["random_seeds"]["seed_poisson"]) + pointing.id*30 + chip.chipID, sky_level=0.)
-        
+
         # Get flat, shutter, and PRNU images
-        chip.flat_img, _ = chip_utils.get_flat(img=chip.img, seed=int(self.config["random_seeds"]["seed_flat"]))
+        chip.flat_img, _ = chip_utils.get_flat(
+            img=chip.img, seed=int(self.config["random_seeds"]["seed_flat"]))
         if chip.chipID > 30:
             chip.shutter_img = np.ones_like(chip.img.array)
         else:
-            chip.shutter_img = Effects.ShutterEffectArr(chip.img, t_shutter=1.3, dist_bearing=735, dt=1E-3)
-        chip.prnu_img = Effects.PRNU_Img(xsize=chip.npix_x, ysize=chip.npix_y, sigma=0.01,
+            chip.shutter_img = effects.ShutterEffectArr(
+                chip.img, t_shutter=1.3, dist_bearing=735, dt=1E-3)
+        chip.prnu_img = effects.PRNU_Img(xsize=chip.npix_x, ysize=chip.npix_y, sigma=0.01,
                                          seed=int(self.config["random_seeds"]["seed_prnu"]+chip.chipID))
-        
+
         return chip
 
     def run_one_chip(self, chip, filt, pointing, chip_output, wcs_fp=None, psf_model=None, cat_dir=None, sed_dir=None):
 
-        chip_output.Log_info(':::::::::::::::::::Current Pointing Information::::::::::::::::::')
+        chip_output.Log_info(
+            ':::::::::::::::::::Current Pointing Information::::::::::::::::::')
         chip_output.Log_info("RA: %f, DEC; %f" % (pointing.ra, pointing.dec))
-        chip_output.Log_info("Time: %s" % datetime.utcfromtimestamp(pointing.timestamp).isoformat())
+        chip_output.Log_info("Time: %s" % datetime.utcfromtimestamp(
+            pointing.timestamp).isoformat())
         chip_output.Log_info("Exposure time: %f" % pointing.exp_time)
-        chip_output.Log_info("Satellite Position (x, y, z): (%f, %f, %f)" % (pointing.sat_x, pointing.sat_y, pointing.sat_z))
-        chip_output.Log_info("Satellite Velocity (x, y, z): (%f, %f, %f)" % (pointing.sat_vx, pointing.sat_vy, pointing.sat_vz))
+        chip_output.Log_info("Satellite Position (x, y, z): (%f, %f, %f)" % (
+            pointing.sat_x, pointing.sat_y, pointing.sat_z))
+        chip_output.Log_info("Satellite Velocity (x, y, z): (%f, %f, %f)" % (
+            pointing.sat_vx, pointing.sat_vy, pointing.sat_vz))
         chip_output.Log_info("Position Angle: %f" % pointing.img_pa.deg)
         chip_output.Log_info('Chip : %d' % chip.chipID)
-        chip_output.Log_info(':::::::::::::::::::::::::::END:::::::::::::::::::::::::::::::::::')
+        chip_output.Log_info(
+            ':::::::::::::::::::::::::::END:::::::::::::::::::::::::::::::::::')
 
         # Apply astrometric simulation for pointing
         if self.config["obs_setting"]["enable_astrometric_model"]:
@@ -91,32 +100,35 @@ class Observation(object):
         chip = self.prepare_chip_for_exposure(chip, ra_cen, dec_cen, pointing)
 
         # Initialize SimSteps
-        sim_steps = SimSteps(overall_config=self.config, chip_output=chip_output, all_filters=self.all_filters)
+        sim_steps = SimSteps(overall_config=self.config,
+                             chip_output=chip_output, all_filters=self.all_filters)
 
         for step in pointing.obs_param["call_sequence"]:
             if self.config["run_option"]["out_cat_only"]:
                 if step != "scie_obs":
                     continue
-            chip_output.Log_info("Starting simulation step: %s, calling function: %s"%(step, SIM_STEP_TYPES[step]))
+            chip_output.Log_info("Starting simulation step: %s, calling function: %s" % (
+                step, SIM_STEP_TYPES[step]))
             obs_param = pointing.obs_param["call_sequence"][step]
             step_name = SIM_STEP_TYPES[step]
             try:
                 step_func = getattr(sim_steps, step_name)
                 chip, filt, tel, pointing = step_func(
-                    chip=chip, 
-                    filt=filt, 
+                    chip=chip,
+                    filt=filt,
                     tel=self.tel,
-                    pointing=pointing, 
-                    catalog=self.Catalog, 
+                    pointing=pointing,
+                    catalog=self.Catalog,
                     obs_param=obs_param)
-                chip_output.Log_info("Finished simulation step: %s"%(step))
+                chip_output.Log_info("Finished simulation step: %s" % (step))
             except Exception as e:
                 traceback.print_exc()
                 chip_output.Log_error(e)
-                chip_output.Log_error("Failed simulation on step: %s"%(step))
+                chip_output.Log_error("Failed simulation on step: %s" % (step))
                 break
 
-        chip_output.Log_info("check running:1: pointing-%d chip-%d pid-%d memory-%6.2fGB"%(pointing.id, chip.chipID, os.getpid(), (psutil.Process(os.getpid()).memory_info().rss / 1024 / 1024 / 1024) ))
+        chip_output.Log_info("check running:1: pointing-%d chip-%d pid-%d memory-%6.2fGB" % (pointing.id,
+                             chip.chipID, os.getpid(), (psutil.Process(os.getpid()).memory_info().rss / 1024 / 1024 / 1024)))
         del chip.img
 
     def runExposure_MPI_PointingList(self, pointing_list, chips=None):
@@ -131,9 +143,11 @@ class Observation(object):
             # pointing_ID = pointing.id
             pointing_ID = pointing.obs_id
 
-            pointing.make_output_pointing_dir(overall_config=self.config, copy_obs_config=True)
+            pointing.make_output_pointing_dir(
+                overall_config=self.config, copy_obs_config=True)
 
-            self.focal_plane = FocalPlane(chip_list=pointing.obs_param["run_chips"])
+            self.focal_plane = FocalPlane(
+                chip_list=pointing.obs_param["run_chips"])
             # Make Chip & Filter lists
             self.chip_list = []
             self.filter_list = []
@@ -167,7 +181,7 @@ class Observation(object):
                         run_chips.append(chip)
                         run_filts.append(filt)
                 nchips_per_fp = len(chips)
-            
+
             for ichip in range(nchips_per_fp):
                 i_process = process_counter + ichip
                 if i_process % num_thread != ind_thread:
@@ -176,20 +190,22 @@ class Observation(object):
 
                 chip = run_chips[ichip]
                 filt = run_filts[ichip]
-                
+
                 chip_output = ChipOutput(
-                    config = self.config,
-                    chip = chip,
-                    filt = filt,
-                    pointing = pointing
+                    config=self.config,
+                    chip=chip,
+                    filt=filt,
+                    pointing=pointing
                 )
-                chip_output.Log_info("running pointing#%d, chip#%d, at PID#%d..."%(int(pointing_ID), chip.chipID, pid))
+                chip_output.Log_info("running pointing#%d, chip#%d, at PID#%d..." % (
+                    int(pointing_ID), chip.chipID, pid))
                 self.run_one_chip(
                     chip=chip,
                     filt=filt,
                     chip_output=chip_output,
                     pointing=pointing)
-                chip_output.Log_info("finished running chip#%d..."%(chip.chipID))
+                chip_output.Log_info(
+                    "finished running chip#%d..." % (chip.chipID))
                 for handler in chip_output.logger.handlers[:]:
                     chip_output.logger.removeHandler(handler)
                 gc.collect()
diff --git a/ObservationSim/PSF/FieldDistortion.py b/observation_sim/PSF/FieldDistortion.py
similarity index 82%
rename from ObservationSim/PSF/FieldDistortion.py
rename to observation_sim/PSF/FieldDistortion.py
index 7c95fd6b7b3369cb2ae5792569dc293989d02a6c..506bbba487cc91b1c7a97418eb648c2a53491d9a 100644
--- a/ObservationSim/PSF/FieldDistortion.py
+++ b/observation_sim/PSF/FieldDistortion.py
@@ -2,6 +2,7 @@ import galsim
 import numpy as np
 import cmath
 
+
 class FieldDistortion(object):
 
     def __init__(self, chip, fdModel=None, fdModel_path=None, img_rot=0.):
@@ -13,7 +14,8 @@ class FieldDistortion(object):
                 with open(fdModel_path, "rb") as f:
                     self.fdModel = pickle.load(f)
             else:
-                raise ValueError("Error: no field distortion model has been specified!")
+                raise ValueError(
+                    "Error: no field distortion model has been specified!")
         else:
             self.fdModel = fdModel
         self.img_rot = img_rot
@@ -21,19 +23,20 @@ class FieldDistortion(object):
         self.ixfdModel = self.ifdModel["xImagePos"]
         self.iyfdModel = self.ifdModel["yImagePos"]
         # first-order derivatives of the global field distortion model
-        self.ifx_dx    = self.ixfdModel.partial_derivative(1,0)
-        self.ifx_dy    = self.ixfdModel.partial_derivative(0,1)
-        self.ify_dx    = self.iyfdModel.partial_derivative(1,0)
-        self.ify_dy    = self.iyfdModel.partial_derivative(0,1)
+        self.ifx_dx = self.ixfdModel.partial_derivative(1, 0)
+        self.ifx_dy = self.ixfdModel.partial_derivative(0, 1)
+        self.ify_dx = self.iyfdModel.partial_derivative(1, 0)
+        self.ify_dy = self.iyfdModel.partial_derivative(0, 1)
         if "residual" in self.fdModel["wave1"]:
-            self.irsModel = self.fdModel["wave1"]["residual"]["ccd" + chip.getChipLabel(chipID=chip.chipID)]
+            self.irsModel = self.fdModel["wave1"]["residual"]["ccd" +
+                                                              chip.getChipLabel(chipID=chip.chipID)]
             self.ixrsModel = self.irsModel["xResidual"]
             self.iyrsModel = self.irsModel["yResidual"]
             # first-order derivatives of the residual field distortion model
-            self.irx_dx    = self.ixrsModel.partial_derivative(1,0)
-            self.irx_dy    = self.ixrsModel.partial_derivative(0,1)
-            self.iry_dx    = self.iyrsModel.partial_derivative(1,0)
-            self.iry_dy    = self.iyrsModel.partial_derivative(0,1)
+            self.irx_dx = self.ixrsModel.partial_derivative(1, 0)
+            self.irx_dy = self.ixrsModel.partial_derivative(0, 1)
+            self.iry_dx = self.iyrsModel.partial_derivative(1, 0)
+            self.iry_dy = self.iyrsModel.partial_derivative(0, 1)
         else:
             self.irsModel = None
 
@@ -95,8 +98,8 @@ class FieldDistortion(object):
             ix_dy = self.ifx_dy(x, y)
             iy_dx = self.ify_dx(x, y)
             iy_dy = self.ify_dy(x, y)
-        g1k_fd   = 0.0 + (iy_dy - ix_dx) / (iy_dy + ix_dx)
-        g2k_fd   = 0.0 - (iy_dx + ix_dy) / (iy_dy + ix_dx)
+        g1k_fd = 0.0 + (iy_dy - ix_dx) / (iy_dy + ix_dx)
+        g2k_fd = 0.0 - (iy_dx + ix_dy) / (iy_dy + ix_dx)
 
         # [TODO] [TESTING] Rotate the shear:
         g_abs = np.sqrt(g1k_fd**2 + g2k_fd**2)
@@ -107,4 +110,3 @@ class FieldDistortion(object):
 
         fd_shear = galsim.Shear(g1=g1k_fd, g2=g2k_fd)
         return galsim.PositionD(x, y), fd_shear
-        
diff --git a/observation_sim/PSF/PSFGauss.py b/observation_sim/PSF/PSFGauss.py
new file mode 100644
index 0000000000000000000000000000000000000000..ed437d9c15a16697c6d759820dfd554ff36c35bf
--- /dev/null
+++ b/observation_sim/PSF/PSFGauss.py
@@ -0,0 +1,125 @@
+import galsim
+import sep
+import numpy as np
+from scipy.interpolate import interp1d
+
+from observation_sim.PSF.PSFModel import PSFModel
+
+
+class PSFGauss(PSFModel):
+    def __init__(self, chip, fwhm=0.187, sigSpin=0., psfRa=None):
+        self.pix_size = chip.pix_scale
+        self.chip = chip
+        if psfRa is None:
+            self.fwhm = fwhm
+            self.sigGauss = 0.15
+        else:
+            self.fwhm = self.fwhmGauss(r=psfRa)
+            self.sigGauss = psfRa  # 80% light radius
+        self.sigSpin = sigSpin
+        self.psf = galsim.Gaussian(flux=1.0, fwhm=fwhm)
+
+    def perfGauss(self, r, sig):
+        """
+        pseudo-error function, i.e. Cumulative distribution function of Gaussian distribution
+
+        Parameter:
+        r: radius
+        sig: sigma of the Gaussian distribution
+
+        Return:
+        the value of the pseudo CDF
+        """
+        def gaussFun(sigma, r): return 1.0/(np.sqrt(2.0*np.pi)
+                                            * sigma) * np.exp(-r**2/(2.0*sigma**2))
+        nxx = 1000
+        rArr = np.linspace(0.0, r, nxx)
+        gauss = gaussFun(sig, rArr)
+        erf = 2.0*np.trapz(gauss, rArr)
+        return erf
+
+    def fracGauss(self, sig, r=0.15, pscale=None):
+        """
+        For a given Gaussian PSF with sigma=sig,
+        derive the flux ratio ar the given radius r
+
+        Parameters:
+        sig: sigma of the Gauss PSF Function in arcsec
+        r:   radius in arcsec
+        pscale: pixel scale
+
+        Return: the flux ratio
+        """
+        if pscale == None:
+            pscale = self.pix_size
+        gaussx = galsim.Gaussian(flux=1.0, sigma=sig)
+        gaussImg = gaussx.drawImage(scale=pscale, method='no_pixel')
+        gaussImg = gaussImg.array
+        size = np.size(gaussImg, axis=0)
+        cxy = 0.5*(size-1)
+        flux, ferr, flag = sep.sum_circle(
+            gaussImg, [cxy], [cxy], [r/pscale], subpix=0)
+        return flux
+
+    def fwhmGauss(self, r=0.15, fr=0.8, pscale=None):
+        """
+        Given a total flux ratio 'fr' within a fixed radius 'r',
+        estimate the fwhm of the Gaussian function
+
+        return the fwhm in arcsec
+        """
+        if pscale == None:
+            pscale = self.pix_size
+        err = 1.0e-3
+        nxx = 100
+        sig = np.linspace(0.5*pscale, 1.0, nxx)
+        frA = np.zeros(nxx)
+        for i in range(nxx):
+            frA[i] = self.fracGauss(sig[i], r=r, pscale=pscale)
+        index = [i for i in range(nxx-1) if (fr-frA[i])
+                 * (fr-frA[i+1]) <= 0.0][0]
+
+        while abs(frA[index]-fr) > 1.0e-3:
+            sig = np.linspace(sig[index], sig[index+1], nxx)
+            for i in range(nxx):
+                frA[i] = self.fracGauss(sig[i], r=r, pscale=pscale)
+            index = [i for i in range(
+                nxx-1) if (fr-frA[i])*(fr-frA[i+1]) <= 0.0][0]
+
+        fwhm = 2.35482*sig[index]
+        return fwhm
+
+    def get_PSF(self, pos_img, chip=None, bandpass=None, folding_threshold=5.e-3):
+        dx = pos_img.x - self.chip.cen_pix_x
+        dy = pos_img.y - self.chip.cen_pix_y
+        return self.PSFspin(dx, dy)
+
+    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
diff --git a/ObservationSim/PSF/PSFInterp.py b/observation_sim/PSF/PSFInterp.py
similarity index 70%
rename from ObservationSim/PSF/PSFInterp.py
rename to observation_sim/PSF/PSFInterp.py
index 9e9b65c0773d1d47452d9875a8389cec7c34e37e..d96d91470425fb5d7928e2c005431c138558372f 100644
--- a/ObservationSim/PSF/PSFInterp.py
+++ b/observation_sim/PSF/PSFInterp.py
@@ -12,14 +12,14 @@ import scipy.spatial as spatial
 import galsim
 import h5py
 
-from ObservationSim.PSF.PSFModel import PSFModel
+from observation_sim.PSF.PSFModel import PSFModel
 
 
-NPSF      = 900    #***# 30*30
-PixSizeInMicrons = 5.  #***# in microns
+NPSF = 900  # ***# 30*30
+PixSizeInMicrons = 5.  # ***# in microns
 
 
-###find neighbors-KDtree###
+### find neighbors-KDtree###
 def findNeighbors(tx, ty, px, py, dr=0.1, dn=1, OnlyDistance=True):
     """
     find nearest neighbors by 2D-KDTree
@@ -38,7 +38,7 @@ def findNeighbors(tx, ty, px, py, dr=0.1, dn=1, OnlyDistance=True):
     datay = py
     tree = spatial.KDTree(list(zip(datax.ravel(), datay.ravel())))
 
-    dataq=[]
+    dataq = []
     rr = dr
     if OnlyDistance == True:
         dataq = tree.query_ball_point([tx, ty], rr)
@@ -51,7 +51,9 @@ def findNeighbors(tx, ty, px, py, dr=0.1, dn=1, OnlyDistance=True):
         dataq = np.array(dataq)[ddSortindx[0:dn]]
     return dataq
 
-###find neighbors-hoclist###
+### find neighbors-hoclist###
+
+
 def hocBuild(partx, party, nhocx, nhocy, dhocx, dhocy):
     if np.max(partx) > nhocx*dhocx:
         print('ERROR')
@@ -60,8 +62,8 @@ def hocBuild(partx, party, nhocx, nhocy, dhocx, dhocy):
         print('ERROR')
         sys.exit()
 
-    npart  = partx.size
-    hoclist= np.zeros(npart, dtype=np.int32)-1
+    npart = partx.size
+    hoclist = np.zeros(npart, dtype=np.int32)-1
     hoc = np.zeros([nhocy, nhocx], dtype=np.int32)-1
     for ipart in range(npart):
         ix = int(partx[ipart]/dhocx)
@@ -70,18 +72,20 @@ def hocBuild(partx, party, nhocx, nhocy, dhocx, dhocy):
         hoc[iy, ix] = ipart
     return hoc, hoclist
 
+
 def hocFind(px, py, dhocx, dhocy, hoc, hoclist):
     ix = int(px/dhocx)
     iy = int(py/dhocy)
 
-    neigh=[]
+    neigh = []
     it = hoc[iy, ix]
     while it != -1:
         neigh.append(it)
         it = hoclist[it]
     return neigh
 
-def findNeighbors_hoclist(px, py, tx=None,ty=None, dn=4, hoc=None, hoclist=None):
+
+def findNeighbors_hoclist(px, py, tx=None, ty=None, dn=4, hoc=None, hoclist=None):
     nhocy = nhocx = 20
 
     pxMin = np.min(px)
@@ -91,21 +95,21 @@ def findNeighbors_hoclist(px, py, tx=None,ty=None, dn=4, hoc=None, hoclist=None)
 
     dhocx = (pxMax - pxMin)/(nhocx-1)
     dhocy = (pyMax - pyMin)/(nhocy-1)
-    partx = px - pxMin +dhocx/2
-    party = py - pyMin +dhocy/2
+    partx = px - pxMin + dhocx/2
+    party = py - pyMin + dhocy/2
 
     if hoc is None:
         hoc, hoclist = hocBuild(partx, party, nhocx, nhocy, dhocx, dhocy)
         return hoc, hoclist
 
     if hoc is not None:
-        tx = tx - pxMin +dhocx/2
-        ty = ty - pyMin +dhocy/2
+        tx = tx - pxMin + dhocx/2
+        ty = ty - pyMin + dhocy/2
         itx = int(tx/dhocx)
         ity = int(ty/dhocy)
 
         ps = [-1, 0, 1]
-        neigh=[]
+        neigh = []
         for ii in range(3):
             for jj in range(3):
                 ix = itx + ps[ii]
@@ -119,23 +123,23 @@ def findNeighbors_hoclist(px, py, tx=None,ty=None, dn=4, hoc=None, hoclist=None)
                 if iy > nhocy-1:
                     continue
 
-                #neightt = myUtil.hocFind(ppx, ppy, dhocx, dhocy, hoc, hoclist)
+                # neightt = myUtil.hocFind(ppx, ppy, dhocx, dhocy, hoc, hoclist)
                 it = hoc[iy, ix]
                 while it != -1:
                     neigh.append(it)
                     it = hoclist[it]
-                #neigh.append(neightt)
-        #ll = [i for k in neigh for i in k]
+                # neigh.append(neightt)
+        # ll = [i for k in neigh for i in k]
         if dn != -1:
             ptx = np.array(partx[neigh])
             pty = np.array(party[neigh])
-            dd  = np.hypot(ptx-tx, pty-ty)
+            dd = np.hypot(ptx-tx, pty-ty)
             idx = np.argsort(dd)
-            neigh= np.array(neigh)[idx[0:dn]]
+            neigh = np.array(neigh)[idx[0:dn]]
         return neigh
 
 
-###PSF-IDW###
+### 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
@@ -161,9 +165,11 @@ def psfMaker_IDW(px, py, PSFMat, cen_col, cen_row, IDWindex=2, OnlyNeighbors=Tru
 
     if OnlyNeighbors == True:
         if hoc is None:
-            neigh = findNeighbors(px, py, cen_col, cen_row, dr=5., dn=4, OnlyDistance=False)
+            neigh = findNeighbors(px, py, cen_col, cen_row,
+                                  dr=5., dn=4, OnlyDistance=False)
         if hoc is not None:
-            neigh = findNeighbors_hoclist(cen_col, cen_row, tx=px,ty=py, dn=4, hoc=hoc, hoclist=hoclist)
+            neigh = findNeighbors_hoclist(
+                cen_col, cen_row, tx=px, ty=py, dn=4, hoc=hoc, hoclist=hoclist)
 
         neighFlag = np.zeros(npsf)
         neighFlag[neigh] = 1
@@ -173,7 +179,8 @@ def psfMaker_IDW(px, py, PSFMat, cen_col, cen_row, IDWindex=2, OnlyNeighbors=Tru
             if neighFlag[ipsf] != 1:
                 continue
 
-        dist = np.sqrt((ref_col - cen_col[ipsf])**2 + (ref_row - cen_row[ipsf])**2)
+        dist = np.sqrt((ref_col - cen_col[ipsf])
+                       ** 2 + (ref_row - cen_row[ipsf])**2)
         if IDWindex == 1:
             psfWeight[ipsf] = dist
         if IDWindex == 2:
@@ -186,7 +193,7 @@ def psfMaker_IDW(px, py, PSFMat, cen_col, cen_row, IDWindex=2, OnlyNeighbors=Tru
         psfWeight[ipsf] = 1./psfWeight[ipsf]
     psfWeight /= np.sum(psfWeight)
 
-    psfMaker  = np.zeros([ngy, ngx], dtype=np.float32)
+    psfMaker = np.zeros([ngy, ngx], dtype=np.float32)
     for ipsf in range(npsf):
         if OnlyNeighbors == True:
             if neighFlag[ipsf] != 1:
@@ -201,15 +208,14 @@ def psfMaker_IDW(px, py, PSFMat, cen_col, cen_row, IDWindex=2, OnlyNeighbors=Tru
     return psfMaker
 
 
-
-###define PSFInterp###
+### define PSFInterp###
 class PSFInterp(PSFModel):
     def __init__(self, chip, npsf=NPSF, PSF_data=None, PSF_data_file=None, PSF_data_prefix="", sigSpin=0, psfRa=0.15, HocBuild=False, LOG_DEBUG=False):
         self.LOG_DEBUG = LOG_DEBUG
         if self.LOG_DEBUG:
             print('===================================================')
-            print('DEBUG: psf module for csstSim ' \
-                  +time.strftime("(%Y-%m-%d %H:%M:%S)", time.localtime()), flush=True)
+            print('DEBUG: psf module for csstSim '
+                  + time.strftime("(%Y-%m-%d %H:%M:%S)", time.localtime()), flush=True)
             print('===================================================')
 
         self.sigSpin = sigSpin
@@ -221,53 +227,62 @@ class PSFInterp(PSFModel):
             print('Error - PSF_data_file is None')
             sys.exit()
 
-        self.nwave= self._getPSFwave(self.iccd, PSF_data_file, PSF_data_prefix)
+        self.nwave = self._getPSFwave(
+            self.iccd, PSF_data_file, PSF_data_prefix)
         self.npsf = npsf
-        self.PSF_data = self._loadPSF(self.iccd, PSF_data_file, PSF_data_prefix)
+        self.PSF_data = self._loadPSF(
+            self.iccd, PSF_data_file, PSF_data_prefix)
 
         if self.LOG_DEBUG:
-            print('nwave-{:} on ccd-{:}::'.format(self.nwave, self.iccd), flush=True)
+            print('nwave-{:} on ccd-{:}::'.format(self.nwave,
+                  self.iccd), flush=True)
             print('self.PSF_data ... ok', flush=True)
-            print('Preparing self.[psfMat,cen_col,cen_row] for psfMaker ... ', end='', flush=True)
-
-        ngy, ngx    = self.PSF_data[0][0]['psfMat'].shape
-        self.psfMat = np.zeros([self.nwave, self.npsf, ngy, ngx], dtype=np.float32)
-        self.cen_col= np.zeros([self.nwave, self.npsf], dtype=np.float32)
-        self.cen_row= np.zeros([self.nwave, self.npsf], dtype=np.float32)
-        self.hoc    =[]
-        self.hoclist=[]
-        
+            print(
+                'Preparing self.[psfMat,cen_col,cen_row] for psfMaker ... ', end='', flush=True)
+
+        ngy, ngx = self.PSF_data[0][0]['psfMat'].shape
+        self.psfMat = np.zeros(
+            [self.nwave, self.npsf, ngy, ngx], dtype=np.float32)
+        self.cen_col = np.zeros([self.nwave, self.npsf], dtype=np.float32)
+        self.cen_row = np.zeros([self.nwave, self.npsf], dtype=np.float32)
+        self.hoc = []
+        self.hoclist = []
+
         for twave in range(self.nwave):
             for tpsf in range(self.npsf):
-                self.psfMat[twave, tpsf, :, :] = self.PSF_data[twave][tpsf]['psfMat']
-                self.PSF_data[twave][tpsf]['psfMat'] = 0 ###free psfMat
+                self.psfMat[twave, tpsf, :,
+                            :] = self.PSF_data[twave][tpsf]['psfMat']
+                self.PSF_data[twave][tpsf]['psfMat'] = 0  # free psfMat
 
-                self.pixsize = self.PSF_data[twave][tpsf]['pixsize']*1e-3 ##mm
-                self.cen_col[twave, tpsf] = self.PSF_data[twave][tpsf]['image_x'] + self.PSF_data[twave][tpsf]['centroid_x']
-                self.cen_row[twave, tpsf] = self.PSF_data[twave][tpsf]['image_y'] + self.PSF_data[twave][tpsf]['centroid_y']
+                self.pixsize = self.PSF_data[twave][tpsf]['pixsize']*1e-3  # mm
+                self.cen_col[twave, tpsf] = self.PSF_data[twave][tpsf]['image_x'] + \
+                    self.PSF_data[twave][tpsf]['centroid_x']
+                self.cen_row[twave, tpsf] = self.PSF_data[twave][tpsf]['image_y'] + \
+                    self.PSF_data[twave][tpsf]['centroid_y']
 
             if HocBuild:
-                #hoclist on twave for neighborsFinding
-                hoc,hoclist = findNeighbors_hoclist(self.cen_col[twave], self.cen_row[twave])
+                # hoclist on twave for neighborsFinding
+                hoc, hoclist = findNeighbors_hoclist(
+                    self.cen_col[twave], self.cen_row[twave])
                 self.hoc.append(hoc)
                 self.hoclist.append(hoclist)
 
         if self.LOG_DEBUG:
             print('ok', flush=True)
 
-
     def _getPSFwave(self, iccd, PSF_data_file, PSF_data_prefix):
         # fq = h5py.File(PSF_data_file+'/' +PSF_data_prefix +'psfCube_ccd{:}.h5'.format(iccd), 'r')
-        fq = h5py.File(PSF_data_file+'/' +PSF_data_prefix +'psfCube_{:}.h5'.format(iccd), 'r')
+        fq = h5py.File(PSF_data_file+'/' + PSF_data_prefix +
+                       'psfCube_{:}.h5'.format(iccd), 'r')
         nwave = len(fq.keys())
         fq.close()
         return nwave
 
-
     def _loadPSF(self, iccd, PSF_data_file, PSF_data_prefix):
         psfSet = []
         # fq = h5py.File(PSF_data_file+'/' +PSF_data_prefix +'psfCube_ccd{:}.h5'.format(iccd), 'r')
-        fq = h5py.File(PSF_data_file+'/' +PSF_data_prefix +'psfCube_{:}.h5'.format(iccd), 'r')
+        fq = h5py.File(PSF_data_file+'/' + PSF_data_prefix +
+                       'psfCube_{:}.h5'.format(iccd), 'r')
         for ii in range(self.nwave):
             iwave = ii+1
             psfWave = []
@@ -276,30 +291,30 @@ class PSFInterp(PSFModel):
             for jj in range(self.npsf):
                 ipsf = jj+1
                 psfInfo = {}
-                psfInfo['wavelength']= fq_iwave['wavelength'][()] 
+                psfInfo['wavelength'] = fq_iwave['wavelength'][()]
 
                 fq_iwave_ipsf = fq_iwave['psf_{:}'.format(ipsf)]
-                psfInfo['pixsize']   = PixSizeInMicrons
-                psfInfo['field_x']   = fq_iwave_ipsf['field_x'][()]
-                psfInfo['field_y']   = fq_iwave_ipsf['field_y'][()]
-                psfInfo['image_x']   = fq_iwave_ipsf['image_x'][()]
-                psfInfo['image_y']   = fq_iwave_ipsf['image_y'][()]
-                psfInfo['centroid_x']= fq_iwave_ipsf['cx'][()]
-                psfInfo['centroid_y']= fq_iwave_ipsf['cy'][()]
-                psfInfo['psfMat']    = fq_iwave_ipsf['psfMat'][()] 
-                
+                psfInfo['pixsize'] = PixSizeInMicrons
+                psfInfo['field_x'] = fq_iwave_ipsf['field_x'][()]
+                psfInfo['field_y'] = fq_iwave_ipsf['field_y'][()]
+                psfInfo['image_x'] = fq_iwave_ipsf['image_x'][()]
+                psfInfo['image_y'] = fq_iwave_ipsf['image_y'][()]
+                psfInfo['centroid_x'] = fq_iwave_ipsf['cx'][()]
+                psfInfo['centroid_y'] = fq_iwave_ipsf['cy'][()]
+                psfInfo['psfMat'] = fq_iwave_ipsf['psfMat'][()]
+
                 psfWave.append(psfInfo)
             psfSet.append(psfWave)
         fq.close()
 
         if self.LOG_DEBUG:
             print('psfSet has been loaded:', flush=True)
-            print('psfSet[iwave][ipsf][keys]:', psfSet[0][0].keys(), flush=True)
+            print('psfSet[iwave][ipsf][keys]:',
+                  psfSet[0][0].keys(), flush=True)
         return psfSet
 
-
     def _findWave(self, bandpass):
-        if isinstance(bandpass,int):
+        if isinstance(bandpass, int):
             twave = bandpass
             return twave
 
@@ -308,7 +323,6 @@ class PSFInterp(PSFModel):
             if bandpass.blue_limit < bandwave and bandwave < bandpass.red_limit:
                 return twave
         return -1
- 
 
     def get_PSF(self, chip, pos_img, bandpass, galsimGSObject=True, findNeighMode='treeFind', folding_threshold=5.e-3, pointing_pa=0.0):
         """
@@ -323,7 +337,7 @@ class PSFInterp(PSFModel):
         Returns:
             PSF: A 'galsim.GSObject'.
         """
-        pixSize = np.rad2deg(self.pixsize*1e-3/28)*3600  #set psf pixsize
+        pixSize = np.rad2deg(self.pixsize*1e-3/28)*3600  # set psf pixsize
 
         # assert self.iccd == int(chip.getChipLabel(chipID=chip.chipID)), 'ERROR: self.iccd != chip.chipID'
         twave = self._findWave(bandpass)
@@ -331,16 +345,18 @@ class PSFInterp(PSFModel):
             print("!!!PSF bandpass does not match.")
             exit()
         PSFMat = self.psfMat[twave]
-        cen_col= self.cen_col[twave]
-        cen_row= self.cen_row[twave]
+        cen_col = self.cen_col[twave]
+        cen_row = self.cen_row[twave]
 
         px = (pos_img.x - chip.cen_pix_x)*0.01
         py = (pos_img.y - chip.cen_pix_y)*0.01
         if findNeighMode == 'treeFind':
-            imPSF = psfMaker_IDW(px, py, PSFMat, cen_col, cen_row, IDWindex=2, OnlyNeighbors=True, PSFCentroidWgt=True)
+            imPSF = psfMaker_IDW(px, py, PSFMat, cen_col, cen_row,
+                                 IDWindex=2, OnlyNeighbors=True, PSFCentroidWgt=True)
         if findNeighMode == 'hoclistFind':
-            assert(self.hoc != 0), 'hoclist should be built correctly!'
-            imPSF = psfMaker_IDW(px, py, PSFMat, cen_col, cen_row, IDWindex=2, OnlyNeighbors=True, hoc=self.hoc[twave], hoclist=self.hoclist[twave], PSFCentroidWgt=True)
+            assert (self.hoc != 0), 'hoclist should be built correctly!'
+            imPSF = psfMaker_IDW(px, py, PSFMat, cen_col, cen_row, IDWindex=2, OnlyNeighbors=True,
+                                 hoc=self.hoc[twave], hoclist=self.hoclist[twave], PSFCentroidWgt=True)
 
         '''
         ############TEST: START
@@ -353,20 +369,21 @@ class PSFInterp(PSFModel):
         '''
 
         if galsimGSObject:
-            imPSFt = np.zeros([257,257])
+            imPSFt = np.zeros([257, 257])
             imPSFt[0:256, 0:256] = imPSF
             # imPSFt[120:130, 0:256] = 1.
 
             img = galsim.ImageF(imPSFt, scale=pixSize)
             gsp = galsim.GSParams(folding_threshold=folding_threshold)
-            ############TEST: START
+            # TEST: START
             # Use sheared PSF to test the PSF orientation
             # self.psf = galsim.InterpolatedImage(img, gsparams=gsp).shear(g1=0.8, g2=0.)
-            ############TEST: END
+            # TEST: END
             self.psf = galsim.InterpolatedImage(img, gsparams=gsp)
             wcs = chip.img.wcs.local(pos_img)
             scale = galsim.PixelScale(0.074)
-            self.psf = wcs.toWorld(scale.toImage(self.psf), image_pos=(pos_img))
+            self.psf = wcs.toWorld(scale.toImage(
+                self.psf), image_pos=(pos_img))
 
             # return self.PSFspin(x=px/0.01, y=py/0.01)
             return self.psf, galsim.Shear(e=0., beta=(np.pi/2)*galsim.radians)
diff --git a/ObservationSim/PSF/PSFInterpSLS.py b/observation_sim/PSF/PSFInterpSLS.py
similarity index 88%
rename from ObservationSim/PSF/PSFInterpSLS.py
rename to observation_sim/PSF/PSFInterpSLS.py
index 7dc1624c2ae4305cac78650044e46c95e6de57a2..b3b6e7d8c85a915fdac00b25aa19af1b29dfede1 100644
--- a/ObservationSim/PSF/PSFInterpSLS.py
+++ b/observation_sim/PSF/PSFInterpSLS.py
@@ -4,6 +4,7 @@ PSF interpolation for CSST-Sim
 NOTE: [iccd, iwave, ipsf] are counted from 1 to n, but [tccd, twave, tpsf] are counted from 0 to n-1
 '''
 
+import yaml
 import sys
 import time
 import copy
@@ -12,8 +13,9 @@ import scipy.spatial as spatial
 import galsim
 import h5py
 
-from ObservationSim.PSF.PSFModel import PSFModel
-from ObservationSim.Instrument.Chip import ChipUtils as chip_utils
+from observation_sim.instruments import Filter, FilterParam, Chip
+from observation_sim.PSF.PSFModel import PSFModel
+from observation_sim.instruments.chip import chip_utils
 import os
 from astropy.io import fits
 
@@ -21,12 +23,12 @@ from astropy.modeling.models import Gaussian2D
 from scipy import signal
 
 
-LOG_DEBUG = False  #***#
-NPSF      = 900    #***# 30*30
-PixSizeInMicrons = 5.  #***# in microns
+LOG_DEBUG = False  # ***#
+NPSF = 900  # ***# 30*30
+PIX_SIZE_MICRON = 5.  # ***# in microns
 
 
-###find neighbors-KDtree###
+### find neighbors-KDtree###
 # def findNeighbors(tx, ty, px, py, dr=0.1, dn=1, OnlyDistance=True):
 #     """
 #     find nearest neighbors by 2D-KDTree
@@ -208,36 +210,35 @@ PixSizeInMicrons = 5.  #***# in microns
 #     return psfMaker
 
 
-
-###define PSFInterp###
+### define PSFInterp###
 class PSFInterpSLS(PSFModel):
-    def __init__(self, chip, filt,PSF_data_prefix="", sigSpin=0, psfRa=0.15, pix_size = 0.005):
+    def __init__(self, chip, filt, PSF_data_prefix="", sigSpin=0, psfRa=0.15, pix_size=0.005):
         if LOG_DEBUG:
             print('===================================================')
-            print('DEBUG: psf module for csstSim ' \
-                  +time.strftime("(%Y-%m-%d %H:%M:%S)", time.localtime()), flush=True)
+            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
         self.grating_ids = chip_utils.getChipSLSGratingID(chip.chipID)
-        _,self.grating_type = chip.getChipFilter(chipID=chip.chipID)
+        _, self.grating_type = chip.getChipFilter(chipID=chip.chipID)
         self.data_folder = PSF_data_prefix
         self.getPSFDataFromFile(filt)
-        self.pixsize = pix_size # um
+        self.pixsize = pix_size  # um
 
     def getPSFDataFromFile(self, filt):
-        gratingInwavelist = {'GU':0,'GV':1,'GI':2}
-        grating_orders = ['0','1']
+        gratingInwavelist = {'GU': 0, 'GV': 1, 'GI': 2}
+        grating_orders = ['0', '1']
         waveListFn = self.data_folder + '/wavelist.dat'
         wavelists = np.loadtxt(waveListFn)
-        self.waveList = wavelists[:,gratingInwavelist[self.grating_type]]
-        bandranges = np.zeros([4,2])
+        self.waveList = wavelists[:, gratingInwavelist[self.grating_type]]
+        bandranges = np.zeros([4, 2])
         midBand = (self.waveList[0:3] + self.waveList[1:4])/2.*10000.
-        bandranges[0,0] = filt.blue_limit
-        bandranges[1:4,0] = midBand
+        bandranges[0, 0] = filt.blue_limit
+        bandranges[1:4, 0] = midBand
         bandranges[0:3, 1] = midBand
-        bandranges[3,1] = filt.red_limit
+        bandranges[3, 1] = filt.red_limit
 
         self.bandranges = bandranges
 
@@ -246,7 +247,7 @@ class PSFInterpSLS(PSFModel):
         for g_order in grating_orders:
             g_folder_order = g_folder + 'PSF_Order_' + g_order + '/'
             grating_order_data = {}
-            for bandi in [1,2,3,4]:
+            for bandi in [1, 2, 3, 4]:
                 subBand_data = {}
                 subBand_data['bandrange'] = bandranges[bandi-1]
                 final_folder = g_folder_order + str(bandi) + '/'
@@ -305,7 +306,7 @@ class PSFInterpSLS(PSFModel):
     #             psfInfo['wavelength']= fq_iwave['wavelength'][()]
     #
     #             fq_iwave_ipsf = fq_iwave['psf_{:}'.format(ipsf)]
-    #             psfInfo['pixsize']   = PixSizeInMicrons
+    #             psfInfo['pixsize']   = PIX_SIZE_MICRON
     #             psfInfo['field_x']   = fq_iwave_ipsf['field_x'][()]
     #             psfInfo['field_y']   = fq_iwave_ipsf['field_y'][()]
     #             psfInfo['image_x']   = fq_iwave_ipsf['image_x'][()]
@@ -342,7 +343,7 @@ class PSFInterpSLS(PSFModel):
         offset = int(np.ceil(sigma * 3))
         g_size = 2 * offset + 1
         m_cen = int(g_size / 2)
-        print('-----',g_size)
+        print('-----', g_size)
         g_PSF_ = Gaussian2D(1, m_cen, m_cen, sigma, sigma)
         yp, xp = np.mgrid[0:g_size, 0:g_size]
         g_PSF = g_PSF_(xp, yp)
@@ -351,8 +352,7 @@ class PSFInterpSLS(PSFModel):
         convImg = convImg/np.sum(convImg)
         return convImg
 
-
-    def get_PSF(self, chip, pos_img_local = [1000,1000], bandNo = 1, galsimGSObject=True, folding_threshold=5.e-3, g_order = 'A', grating_split_pos=3685):
+    def get_PSF(self, chip, pos_img_local=[1000, 1000], bandNo=1, galsimGSObject=True, folding_threshold=5.e-3, g_order='A', grating_split_pos=3685):
         """
         Get the PSF at a given image position
 
@@ -365,8 +365,9 @@ class PSFInterpSLS(PSFModel):
         Returns:
             PSF: A 'galsim.GSObject'.
         """
-        order_IDs = {'A': '1', 'B': '0' ,'C': '0', 'D': '0', 'E': '0'}
-        contam_order_sigma = {'C':0.28032344707964174,'D':0.39900182912061344,'E':1.1988309797685412} #arcsec
+        order_IDs = {'A': '1', 'B': '0', 'C': '0', 'D': '0', 'E': '0'}
+        contam_order_sigma = {'C': 0.28032344707964174,
+                              'D': 0.39900182912061344, 'E': 1.1988309797685412}  # arcsec
         x_start = chip.x_cen/chip.pix_size - chip.npix_x / 2.
         y_start = chip.y_cen/chip.pix_size - chip.npix_y / 2.
         # print(pos_img.x - x_start)
@@ -382,7 +383,6 @@ class PSFInterpSLS(PSFModel):
         # if grating_order in ['-2','-1','2']:
         #     grating_order = '1'
 
-
         # if grating_order in ['0', '1']:
         psf_order = psf_data['order'+grating_order]
         psf_order_b = psf_order['band'+str(bandNo)]
@@ -396,31 +396,34 @@ class PSFInterpSLS(PSFModel):
         px = pos_img.x*chip.pix_size
         py = pos_img.y*chip.pix_size
 
-        dist2=(pos_p[:,1] - px)*(pos_p[:,1] - px) + (pos_p[:,0] - py)*(pos_p[:,0] - py)
-        temp_sort_dist = np.zeros([dist2.shape[0],2])
-        temp_sort_dist[:, 0] = np.arange(0, dist2.shape[0],1)
+        dist2 = (pos_p[:, 1] - px)*(pos_p[:, 1] - px) + \
+            (pos_p[:, 0] - py)*(pos_p[:, 0] - py)
+        temp_sort_dist = np.zeros([dist2.shape[0], 2])
+        temp_sort_dist[:, 0] = np.arange(0, dist2.shape[0], 1)
         temp_sort_dist[:, 1] = dist2
         # print(temp_sort_dist)
-        dits2_sortlist = sorted(temp_sort_dist, key=lambda x:x[1])
+        dits2_sortlist = sorted(temp_sort_dist, key=lambda x: x[1])
         # print(dits2_sortlist)
-        nearest4p = np.zeros([4,2])
-        pc_coeff_4p = np.zeros([pc_coeff.data.shape[0],4])
+        nearest4p = np.zeros([4, 2])
+        pc_coeff_4p = np.zeros([pc_coeff.data.shape[0], 4])
 
         for i in np.arange(4):
             smaller_ids = int(dits2_sortlist[i][0])
             nearest4p[i, 0] = pos_p[smaller_ids, 1]
             nearest4p[i, 1] = pos_p[smaller_ids, 0]
-            pc_coeff_4p[:,i] = pc_coeff[:,smaller_ids]
-        idw_dist = 1/(np.sqrt((px-nearest4p[:,0]) * (px-nearest4p[:,0]) + (py-nearest4p[:,1]) * (py-nearest4p[:,1])))
+            pc_coeff_4p[:, i] = pc_coeff[:, smaller_ids]
+        idw_dist = 1/(np.sqrt((px-nearest4p[:, 0]) * (px-nearest4p[:, 0]) + (
+            py-nearest4p[:, 1]) * (py-nearest4p[:, 1])))
 
         coeff_int = np.zeros(pc_coeff.data.shape[0])
         for i in np.arange(4):
-            coeff_int = coeff_int + pc_coeff_4p[:,i]*idw_dist[i]
+            coeff_int = coeff_int + pc_coeff_4p[:, i]*idw_dist[i]
         coeff_int = coeff_int / np.sum(coeff_int)
 
         npc = 10
         m_size = int(pcs.shape[0]**0.5)
-        PSF_int = np.dot(pcs[:,0:npc],coeff_int[0:npc]).reshape(m_size,m_size)
+        PSF_int = np.dot(pcs[:, 0:npc], coeff_int[0:npc]
+                         ).reshape(m_size, m_size)
 
         # PSF_int = PSF_int/np.sum(PSF_int)
         PSF_int_trans = np.flipud(np.fliplr(PSF_int))
@@ -434,7 +437,6 @@ class PSFInterpSLS(PSFModel):
         # from astropy.io import fits
         # fits.writeto(str(bandNo) + '_' + g_order+ '_psf_o.fits', PSF_int_trans)
 
-
         # if g_order in ['C','D','E']:
         #     g_simgma = contam_order_sigma[g_order]/pixel_size_arc
         #     PSF_int_trans = self.convolveWithGauss(PSF_int_trans,g_simgma)
@@ -459,24 +461,24 @@ class PSFInterpSLS(PSFModel):
             pixel_size_arc = np.rad2deg(self.pixsize * 1e-3 / 28) * 3600
             img = galsim.ImageF(PSF_int_trans, scale=pixel_size_arc)
             gsp = galsim.GSParams(folding_threshold=folding_threshold)
-            ############TEST: START
+            # TEST: START
             # Use sheared PSF to test the PSF orientation
             # self.psf = galsim.InterpolatedImage(img, gsparams=gsp).shear(g1=0.8, g2=0.)
-            ############TEST: END
+            # TEST: END
             self.psf = galsim.InterpolatedImage(img, gsparams=gsp)
             # if g_order in ['C','D','E']:
             #     add_psf  = galsim.Gaussian(sigma=contam_order_sigma[g_order], flux=1.0)
             #     self.psf = galsim.Convolve(self.psf, add_psf)
             wcs = chip.img.wcs.local(pos_img)
             scale = galsim.PixelScale(0.074)
-            self.psf = wcs.toWorld(scale.toImage(self.psf), image_pos=(pos_img))
+            self.psf = wcs.toWorld(scale.toImage(
+                self.psf), image_pos=(pos_img))
 
             # return self.PSFspin(x=px/0.01, y=py/0.01)
             return self.psf, galsim.Shear(e=0., beta=(np.pi/2)*galsim.radians)
 
         return PSF_int_trans, PSF_int
 
-
         # pixSize = np.rad2deg(self.pixsize*1e-3/28)*3600  #set psf pixsize
         #
         # # assert self.iccd == int(chip.getChipLabel(chipID=chip.chipID)), 'ERROR: self.iccd != chip.chipID'
@@ -547,24 +549,23 @@ class PSFInterpSLS(PSFModel):
     #     PSFshear = galsim.Shear(e=ell, beta=beta*galsim.radians)
     #     return self.psf.shear(PSFshear), PSFshear
 
-from ObservationSim.Instrument import Filter, FilterParam, Chip
-import yaml
+
 if __name__ == '__main__':
     configfn = '/Users/zhangxin/Work/SlitlessSim/CSST_SIM/CSST_new_sim/csst-simulation/config/config_C6_dev.yaml'
     with open(configfn, "r") as stream:
         try:
             config = yaml.safe_load(stream)
             for key, value in config.items():
-                print (key + " : " + str(value))
+                print(key + " : " + str(value))
         except yaml.YAMLError as exc:
             print(exc)
-    chip = Chip(chipID=1,config=config)
+    chip = Chip(chipID=1, config=config)
     filter_id, filter_type = chip.getChipFilter()
     filt = Filter(filter_id=filter_id,
                   filter_type=filter_type,
                   filter_param=FilterParam())
 
-    psf_i = PSFInterpSLS(chip, filt,PSF_data_prefix="/Volumes/EAGET/CSST_PSF_data/SLS_PSF_PCA_fp/")
+    psf_i = PSFInterpSLS(
+        chip, filt, PSF_data_prefix="/Volumes/EAGET/CSST_PSF_data/SLS_PSF_PCA_fp/")
     pos_img = galsim.PositionD(x=25155, y=-22060)
-    psf_im = psf_i.get_PSF(chip, pos_img = pos_img, g_order = '1')
-
+    psf_im = psf_i.get_PSF(chip, pos_img=pos_img, g_order='1')
diff --git a/observation_sim/PSF/PSFModel.py b/observation_sim/PSF/PSFModel.py
new file mode 100755
index 0000000000000000000000000000000000000000..604ff8b20130ea43ef26e096936b879e842da1f1
--- /dev/null
+++ b/observation_sim/PSF/PSFModel.py
@@ -0,0 +1,43 @@
+import galsim
+import sep
+import numpy as np
+from scipy.interpolate import interp1d
+import pylab as pl
+import os
+import sys
+
+
+class PSFModel(object):
+    def __init__(self, sigSpin=0., psfRa=0.15):
+        # TODO: what are the nesseary fields in PSFModel class?
+        pass
+
+    def PSFspin(self, psf, sigSpin, sigGauss, dx, dy):
+        """
+        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 = sigGauss * 0.107 * (1000.0/10.0)  # in unit of [pixels]
+        rc = np.sqrt(dx*dx + dy*dy)
+        cpix = rc*(sigSpin*a2Rad)
+
+        beta = (np.arctan2(dy, dx) + 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 psf.shear(PSFshear), PSFshear
diff --git a/ObservationSim/PSF/__init__.py b/observation_sim/PSF/__init__.py
similarity index 100%
rename from ObservationSim/PSF/__init__.py
rename to observation_sim/PSF/__init__.py
diff --git a/ObservationSim/Astrometry/__init__.py b/observation_sim/__init__.py
old mode 100644
new mode 100755
similarity index 100%
rename from ObservationSim/Astrometry/__init__.py
rename to observation_sim/__init__.py
diff --git a/ObservationSim/_util.py b/observation_sim/_util.py
similarity index 83%
rename from ObservationSim/_util.py
rename to observation_sim/_util.py
index 1009ec07d170873ab3bf322574b7c0eba47103a7..47c91ce66d01ce7c06b119ee02822b112dc5f7d7 100755
--- a/ObservationSim/_util.py
+++ b/observation_sim/_util.py
@@ -4,7 +4,8 @@ from datetime import datetime
 import argparse
 from astropy.time import Time
 
-from ObservationSim.Config import Pointing
+from observation_sim.config import Pointing
+
 
 def parse_args():
     '''
@@ -12,19 +13,25 @@ def parse_args():
     can be set in the .yaml config file as well.
     '''
     parser = argparse.ArgumentParser()
-    parser.add_argument('--config_file', type=str, required=True, help='.yaml config file for simulation settings.')
-    parser.add_argument('--catalog', type=str, help='name of the catalog interface class to be loaded.')
-    parser.add_argument('-c', '--config_dir', type=str, help='Directory that houses the .yaml config file.')
-    parser.add_argument('-d', '--data_dir', type=str, help='Directory that houses the input data.')
-    parser.add_argument('-w', '--work_dir', type=str, help='The path for output.')
+    parser.add_argument('--config_file', type=str, required=True,
+                        help='.yaml config file for simulation settings.')
+    parser.add_argument('--catalog', type=str,
+                        help='name of the catalog interface class to be loaded.')
+    parser.add_argument('-c', '--config_dir', type=str,
+                        help='Directory that houses the .yaml config file.')
+    parser.add_argument('-d', '--data_dir', type=str,
+                        help='Directory that houses the input data.')
+    parser.add_argument('-w', '--work_dir', type=str,
+                        help='The path for output.')
     return parser.parse_args()
 
+
 def generate_pointing_list(config, pointing_filename=None, data_dir=None):
     pointing_list = []
 
     # Only valid when the pointing list does not contain time stamp column
     t0 = datetime(2021, 5, 25, 12, 0, 0)
-    delta_t = 10. # Time elapsed between exposures (minutes)
+    delta_t = 10.  # Time elapsed between exposures (minutes)
 
     # Calculate starting time(s) for CAL exposures
     # NOTE: temporary implementation
@@ -36,7 +43,7 @@ def generate_pointing_list(config, pointing_filename=None, data_dir=None):
         obs_config_file = config['obs_setting']["obs_config_file"]
     else:
         obs_config_file = None
-    
+
     # if pointing_filename and data_dir:
     if pointing_filename:
         if data_dir:
@@ -48,7 +55,7 @@ def generate_pointing_list(config, pointing_filename=None, data_dir=None):
         #     header = f.readline()
         iline = 0
         for line in f:
-            if len(line.strip()) == 0 or line[0]=='#':
+            if len(line.strip()) == 0 or line[0] == '#':
                 continue
             if run_pointings and iline not in run_pointings:
                 iline += 1
@@ -77,12 +84,13 @@ def generate_pointing_list(config, pointing_filename=None, data_dir=None):
             exp_time=exp_time,
             pointing_type='SCI',
             obs_config_file=obs_config_file
-            )
+        )
         t += delta_t * 60.
         pointing_list.append(pointing)
         ipoint += 1
     return pointing_list
 
+
 def make_run_dirs(work_dir, run_name, pointing_list):
     if not os.path.exists(work_dir):
         try:
@@ -97,6 +105,7 @@ def make_run_dirs(work_dir, run_name, pointing_list):
             pass
     return imgDir
 
+
 def make_output_pointing_dir(path_dict, config, pointing_ID=0):
     imgDir = os.path.join(path_dict["work_dir"], config["run_name"])
     if not os.path.exists(imgDir):
@@ -113,6 +122,7 @@ def make_output_pointing_dir(path_dict, config, pointing_ID=0):
             pass
     return subImgdir, prefix
 
+
 def get_shear_field(config):
     if not config["shear_setting"]["shear_type"] in ["constant", "catalog"]:
         raise ValueError("Please set a right 'shear_method' parameter.")
@@ -125,4 +135,4 @@ def get_shear_field(config):
     else:
         g1, g2 = 0., 0.
         nshear = 0
-    return g1, g2, nshear
\ No newline at end of file
+    return g1, g2, nshear
diff --git a/ObservationSim/Astrometry/Astrometry_util.py b/observation_sim/astrometry/Astrometry_util.py
similarity index 66%
rename from ObservationSim/Astrometry/Astrometry_util.py
rename to observation_sim/astrometry/Astrometry_util.py
index 58f5fd0a5c2d759a02975af88ff57f6b9add67be..dba4466365299b584422dbad4833e342e25bcac8 100644
--- a/ObservationSim/Astrometry/Astrometry_util.py
+++ b/observation_sim/astrometry/Astrometry_util.py
@@ -7,28 +7,32 @@ except ImportError:
     # Try backported to PY<37 'importlib_resources'
     import importlib_resources as pkg_resources
 
+
 def checkInputList(input_list, n):
     if not isinstance(input_list, list):
         raise TypeError("Input type is not list!", input_list)
     for i in input_list:
         if type(i) != type(1.1):
             if type(i) != type(1):
-                raise TypeError("Input list's element is not float or int!", input_list)
+                raise TypeError(
+                    "Input list's element is not float or int!", input_list)
     if len(input_list) != n:
-        raise RuntimeError("Length of input list is not equal to stars' number!", input_list)
-            
+        raise RuntimeError(
+            "Length of input list is not equal to stars' number!", input_list)
+
+
 def on_orbit_obs_position(input_ra_list, input_dec_list, input_pmra_list, input_pmdec_list, input_rv_list, input_parallax_list, input_nstars, input_x, input_y, input_z, input_vx, input_vy, input_vz, input_epoch, input_date_str, input_time_str, lib_path=None):
-    #Check input parameters
+    # Check input parameters
     if not isinstance(input_nstars, int):
         raise TypeError("Parameter 7 is not int!", input_nstars)
-    
+
     checkInputList(input_ra_list, input_nstars)
     checkInputList(input_dec_list, input_nstars)
     checkInputList(input_pmra_list, input_nstars)
     checkInputList(input_pmdec_list, input_nstars)
     checkInputList(input_rv_list, input_nstars)
     checkInputList(input_parallax_list, input_nstars)
-    
+
     if not isinstance(input_x, float):
         raise TypeError("Parameter 8 is not double!", input_x)
     if not isinstance(input_y, float):
@@ -41,69 +45,77 @@ def on_orbit_obs_position(input_ra_list, input_dec_list, input_pmra_list, input_
         raise TypeError("Parameter 12 is not double!", input_vy)
     if not isinstance(input_vz, float):
         raise TypeError("Parameter 13 is not double!", input_vz)
-    #Convert km -> m
-    input_x = input_x*1000.0 
-    input_y = input_y*1000.0 
+    # Convert km -> m
+    input_x = input_x*1000.0
+    input_y = input_y*1000.0
     input_z = input_z*1000.0
     input_vx = input_vx*1000.0
     input_vy = input_vy*1000.0
-    input_vz  = input_vz*1000.0
-    
+    input_vz = input_vz*1000.0
+
     if not isinstance(input_date_str, str):
         raise TypeError("Parameter 15 is not string!", input_date_str)
     else:
         input_date_str = input_date_str.strip()
-        if not (input_date_str[4]=="-" and input_date_str[7]=="-"):
+        if not (input_date_str[4] == "-" and input_date_str[7] == "-"):
             raise TypeError("Parameter 15 format error (1)!", input_date_str)
         else:
             tmp = input_date_str.split("-")
             if len(tmp) != 3:
-                raise TypeError("Parameter 15 format error (2)!", input_date_str)
+                raise TypeError(
+                    "Parameter 15 format error (2)!", input_date_str)
             input_year = int(tmp[0])
             input_month = int(tmp[1])
             input_day = int(tmp[2])
-            if not (input_year>=1900 and input_year<=2100):
-                raise TypeError("Parameter 15 year range error [1900 ~ 2100]!", input_year)
-            if not (input_month>=1 and input_month<=12):
-                raise TypeError("Parameter 15 month range error [1 ~ 12]!", input_month)
-            if not (input_day>=1 and input_day<=31):
-                raise TypeError("Parameter 15 day range error [1 ~ 31]!", input_day)
-    
+            if not (input_year >= 1900 and input_year <= 2100):
+                raise TypeError(
+                    "Parameter 15 year range error [1900 ~ 2100]!", input_year)
+            if not (input_month >= 1 and input_month <= 12):
+                raise TypeError(
+                    "Parameter 15 month range error [1 ~ 12]!", input_month)
+            if not (input_day >= 1 and input_day <= 31):
+                raise TypeError(
+                    "Parameter 15 day range error [1 ~ 31]!", input_day)
+
     if not isinstance(input_time_str, str):
         raise TypeError("Parameter 16 is not string!", input_time_str)
     else:
         input_time_str = input_time_str.strip()
-        if not (input_time_str[2]==":" and input_time_str[5]==":"):
+        if not (input_time_str[2] == ":" and input_time_str[5] == ":"):
             raise TypeError("Parameter 16 format error (1)!", input_time_str)
         else:
             tmp = input_time_str.split(":")
             if len(tmp) != 3:
-                raise TypeError("Parameter 16 format error (2)!", input_time_str)
+                raise TypeError(
+                    "Parameter 16 format error (2)!", input_time_str)
             input_hour = int(tmp[0])
             input_minute = int(tmp[1])
             input_second = float(tmp[2])
-            if not (input_hour>=0 and input_hour<=23):
-                raise TypeError("Parameter 16 hour range error [0 ~ 23]!", input_hour)
-            if not (input_minute>=0 and input_minute<=59):
-                raise TypeError("Parameter 16 minute range error [0 ~ 59]!", input_minute)
-            if not (input_second>=0 and input_second<60.0):
-                raise TypeError("Parameter 16 second range error [0 ~ 60)!", input_second)
-    
-    #Inital dynamic lib
+            if not (input_hour >= 0 and input_hour <= 23):
+                raise TypeError(
+                    "Parameter 16 hour range error [0 ~ 23]!", input_hour)
+            if not (input_minute >= 0 and input_minute <= 59):
+                raise TypeError(
+                    "Parameter 16 minute range error [0 ~ 59]!", input_minute)
+            if not (input_second >= 0 and input_second < 60.0):
+                raise TypeError(
+                    "Parameter 16 second range error [0 ~ 60)!", input_second)
+
+    # Inital dynamic lib
     try:
-        with pkg_resources.files('ObservationSim.Astrometry.lib').joinpath("libshao.so") as lib_path:
+        with pkg_resources.files('observation_sim.astrometry.lib').joinpath("libshao.so") as lib_path:
             shao = cdll.LoadLibrary(lib_path)
     except AttributeError:
-        with pkg_resources.path('ObservationSim.Astrometry.lib', "libshao.so") as lib_path:
+        with pkg_resources.path('observation_sim.astrometry.lib', "libshao.so") as lib_path:
             shao = cdll.LoadLibrary(lib_path)
     shao.onOrbitObs.restype = c_int
-    
+
     d3 = c_double * 3
-    shao.onOrbitObs.argtypes = [c_double, c_double, c_double, c_double, c_double, c_double, \
-                                c_int, c_int, c_int, c_int, c_int, c_double, \
-                                c_double, POINTER(d3), POINTER(d3), \
-                                c_int, c_int, c_int, c_int, c_int, c_double, \
-                                POINTER(c_double), POINTER(c_double) ]
+    shao.onOrbitObs.argtypes = [c_double, c_double, c_double, c_double, c_double, c_double,
+                                c_int, c_int, c_int, c_int, c_int, c_double,
+                                c_double, POINTER(d3), POINTER(d3),
+                                c_int, c_int, c_int, c_int, c_int, c_double,
+                                POINTER(c_double), POINTER(c_double)]
     output_ra_list = list()
     output_dec_list = list()
     for i in range(input_nstars):
@@ -118,17 +130,17 @@ def on_orbit_obs_position(input_ra_list, input_dec_list, input_pmra_list, input_
         v3 = d3(input_vx, input_vy, input_vz)
         input_year_c = c_int(input_year)
         input_month_c = c_int(input_month)
-        input_day_c = c_int(input_day) 
+        input_day_c = c_int(input_day)
         input_hour_c = c_int(input_hour)
         input_minute_c = c_int(input_minute)
-        input_second_c  = c_double(input_second)
+        input_second_c = c_double(input_second)
         DAT = c_double(37.0)
         output_ra = c_double(0.0)
         output_dec = c_double(0.0)
-        rs = shao.onOrbitObs(input_ra, input_dec, input_parallax, input_pmra, input_pmdec, input_rv, \
-                             input_year_c, input_month_c, input_day_c, input_hour_c, input_minute_c, input_second_c, \
-                             DAT, byref(p3), byref(v3), \
-                             input_year_c, input_month_c, input_day_c, input_hour_c, input_minute_c, input_second_c, \
+        rs = shao.onOrbitObs(input_ra, input_dec, input_parallax, input_pmra, input_pmdec, input_rv,
+                             input_year_c, input_month_c, input_day_c, input_hour_c, input_minute_c, input_second_c,
+                             DAT, byref(p3), byref(v3),
+                             input_year_c, input_month_c, input_day_c, input_hour_c, input_minute_c, input_second_c,
                              byref(output_ra), byref(output_dec))
         if rs != 0:
             raise RuntimeError("Calculate error!")
diff --git a/ObservationSim/Astrometry/lib/__init__.py b/observation_sim/astrometry/__init__.py
similarity index 100%
rename from ObservationSim/Astrometry/lib/__init__.py
rename to observation_sim/astrometry/__init__.py
diff --git a/ObservationSim/Instrument/Chip/libBF/__init__.py b/observation_sim/astrometry/lib/__init__.py
similarity index 100%
rename from ObservationSim/Instrument/Chip/libBF/__init__.py
rename to observation_sim/astrometry/lib/__init__.py
diff --git a/ObservationSim/Astrometry/lib/libshao.so b/observation_sim/astrometry/lib/libshao.so
similarity index 100%
rename from ObservationSim/Astrometry/lib/libshao.so
rename to observation_sim/astrometry/lib/libshao.so
diff --git a/ObservationSim/Config/ChipOutput.py b/observation_sim/config/ChipOutput.py
similarity index 94%
rename from ObservationSim/Config/ChipOutput.py
rename to observation_sim/config/ChipOutput.py
index 8b6c8a39339d6bd81ea988fc1eebabfa15e6cdfe..5efd0616e8870d90a0844279d476d4817a9a2135 100755
--- a/ObservationSim/Config/ChipOutput.py
+++ b/observation_sim/config/ChipOutput.py
@@ -1,7 +1,7 @@
 import os
 import logging
-import ObservationSim.Config._util as _util
-from ObservationSim.Config.Header import generatePrimaryHeader
+import observation_sim.config._util as _util
+from observation_sim.config.header import generatePrimaryHeader
 
 
 class ChipOutput(object):
diff --git a/ObservationSim/Config/Pointing.py b/observation_sim/config/Pointing.py
similarity index 84%
rename from ObservationSim/Config/Pointing.py
rename to observation_sim/config/Pointing.py
index 378c4db5e0e4e906bdb718ed1486a9986dac83da..1b399596e8789ef8de1e8a78a2d437cca88565af 100644
--- a/ObservationSim/Config/Pointing.py
+++ b/observation_sim/config/Pointing.py
@@ -5,11 +5,12 @@ import galsim
 import numpy as np
 from astropy.time import Time
 
-from ObservationSim.Config._util import get_obs_id
-import ObservationSim.Instrument._util as _util
+from observation_sim.config._util import get_obs_id
+import observation_sim.instruments._util as _util
+
 
 class Pointing(object):
-    def __init__(self, id=0, ra=0., dec=0., img_pa=0., timestamp=1621915200, sat_x=0., sat_y=0., sat_z=0., sun_x=0., sun_y=0., sun_z=0., sat_vx=0., sat_vy=0., sat_vz=0., exp_time=150., pointing_type='SCI', pointing_type_code='101', pointing_id = '00000001', obs_config_file=None, t_shutter_open = 1.3, t_shutter_close = 1.3):
+    def __init__(self, id=0, ra=0., dec=0., img_pa=0., timestamp=1621915200, sat_x=0., sat_y=0., sat_z=0., sun_x=0., sun_y=0., sun_z=0., sat_vx=0., sat_vy=0., sat_vz=0., exp_time=150., pointing_type='SCI', pointing_type_code='101', pointing_id='00000001', obs_config_file=None, t_shutter_open=1.3, t_shutter_close=1.3):
         self.id = id
         self.ra = ra
         self.dec = dec
@@ -23,7 +24,7 @@ class Pointing(object):
         self.pointing_type_code = pointing_type_code
         self.obs_id = pointing_id
         self.survey_field_type = 'WIDE'
-        self.jdt = 0. 
+        self.jdt = 0.
         self.obs_config_file = obs_config_file
         self.t_shutter_open = t_shutter_open
         self.t_shutter_close = t_shutter_close
@@ -41,7 +42,6 @@ class Pointing(object):
             if self.obs_param["obs_id"]:
                 self.obs_id = str(self.obs_param["obs_id"])
 
-    
     def get_full_depth_exptime(self, filter_type):
         if self.survey_field_type == 'WIDE':
             if filter_type in _util.SPEC_FILTERS:
@@ -52,7 +52,7 @@ class Pointing(object):
                 elif filter_type.lower() in ['u', 'g', 'r', 'i', 'z']:
                     return 150. * 2
                 else:
-                    return max(150., self.exp_time) # [TODO] for FGS
+                    return max(150., self.exp_time)  # [TODO] for FGS
         elif self.survey_field_type == 'DEEP':
             if filter_type in _util.SPEC_FILTERS:
                 return 250. * 4 * 4
@@ -62,8 +62,7 @@ class Pointing(object):
                 elif filter_type.lower() in ['u', 'g', 'r', 'i', 'z']:
                     return 250. * 2 * 4
                 else:
-                    return max(150., self.exp_time) # [TODO] for FGS
-
+                    return max(150., self.exp_time)  # [TODO] for FGS
 
     def read_pointing_columns(self, columns, id=0, t=1621915200, pointing_type='SCI'):
         self.id = id
@@ -91,7 +90,7 @@ class Pointing(object):
             # [TODO] Can also define other survey types
             if is_deep != -1.0:
                 self.survey_field_type = "DEEP"
-            
+
             if not self.obs_config_file:
                 self.obs_config_file = str(columns[20])
                 with open(self.obs_config_file, "r") as stream:
@@ -99,7 +98,7 @@ class Pointing(object):
                         self.obs_param = yaml.safe_load(stream)
                     except yaml.YAMLError as exc:
                         print(exc)
-            
+
             self.pointing_type_code = columns[21][0:3]
             self.obs_id = columns[21][3:]
 
@@ -108,18 +107,19 @@ class Pointing(object):
             self.timestamp = t
 
     def make_output_pointing_dir(self, overall_config, copy_obs_config=False):
-        run_dir = os.path.join(overall_config["work_dir"], overall_config["run_name"])
+        run_dir = os.path.join(
+            overall_config["work_dir"], overall_config["run_name"])
         if not os.path.exists(run_dir):
             try:
                 os.makedirs(run_dir, exist_ok=True)
             except OSError:
                 pass
         self.output_prefix = get_obs_id(
-            img_type=self.pointing_type, 
-            project_cycle=overall_config["project_cycle"], 
-            run_counter=overall_config["run_counter"], 
-            pointing_id=self.obs_id, 
-            pointing_type_code = self.pointing_type_code)
+            img_type=self.pointing_type,
+            project_cycle=overall_config["project_cycle"],
+            run_counter=overall_config["run_counter"],
+            pointing_id=self.obs_id,
+            pointing_type_code=self.pointing_type_code)
         self.output_dir = os.path.join(run_dir, self.output_prefix)
         if not os.path.exists(self.output_dir):
             try:
@@ -127,10 +127,10 @@ class Pointing(object):
             except OSError:
                 pass
         if copy_obs_config and self.obs_config_file:
-            obs_config_output_path = os.path.join(self.output_dir, os.path.basename(self.obs_config_file))
+            obs_config_output_path = os.path.join(
+                self.output_dir, os.path.basename(self.obs_config_file))
             if not os.path.exists(obs_config_output_path):
                 try:
                     shutil.copy(self.obs_config_file, self.output_dir)
                 except OSError:
                     pass
-
diff --git a/ObservationSim/Config/__init__.py b/observation_sim/config/__init__.py
similarity index 100%
rename from ObservationSim/Config/__init__.py
rename to observation_sim/config/__init__.py
diff --git a/observation_sim/config/_util.py b/observation_sim/config/_util.py
new file mode 100644
index 0000000000000000000000000000000000000000..7ab0f59d663cf9ad36bf5c63abb9c63e2cd4cdb0
--- /dev/null
+++ b/observation_sim/config/_util.py
@@ -0,0 +1,14 @@
+
+def get_obs_id(img_type='SCI', project_cycle=6, run_counter=0, pointing_id='00000001', pointing_type_code='101'):
+    # obs_type = {'SCI': '01', 'BIAS': '03', 'DARK': '07', 'FLAT': '11', 'CRS': '98', 'CRD': '99'}
+    # obs_type = {'SCIE': '01', 'BIAS': '03', 'DARK': '07', 'FLAT': '11', 'CRS': '98', 'CRD': '99', 'CAL': '01'}
+    obs_id = pointing_type_code + \
+        str(int(project_cycle)).rjust(2, '0') + \
+        str(int(run_counter)) + pointing_id
+    return obs_id
+
+
+def get_file_type(img_type='SCI'):
+    file_type = {'SCI': 'SCI', 'BIAS': 'BIAS', 'DARK': 'DARK', 'FLAT': 'FLAT',
+                 'CRS': 'CRS', 'CRD': 'CRD', 'CALS': 'CALS', 'CALF': 'CALF'}
+    return file_type[img_type]
diff --git a/ObservationSim/Config/Header/ImageHeader.py b/observation_sim/config/header/ImageHeader.py
similarity index 74%
rename from ObservationSim/Config/Header/ImageHeader.py
rename to observation_sim/config/header/ImageHeader.py
index 516cd260d95c90d296f922291e01e3e7f111efeb..7fc3444c1e48d712673ad67c2dadd3cf0e1eb6b6 100644
--- a/ObservationSim/Config/Header/ImageHeader.py
+++ b/observation_sim/config/header/ImageHeader.py
@@ -17,13 +17,14 @@ from astropy.coordinates import SkyCoord
 from astropy.wcs.utils import fit_wcs_from_points
 from astropy.time import Time
 from astropy import wcs
-from ObservationSim.Config._util import get_obs_id, get_file_type
+from observation_sim.config._util import get_obs_id, get_file_type
 
 from datetime import datetime, timezone
 # import socket
 import platform
 import toml
 
+
 def chara2digit(char):
     """ Function to judge and convert characters to digitals
 
@@ -33,7 +34,7 @@ def chara2digit(char):
     """
 
     try:
-        float(char) # for int, long and float
+        float(char)  # for int, long and float
     except ValueError:
         pass
         return char
@@ -66,41 +67,43 @@ def read_header_parameter(filename='global_header.param'):
 #    print(value)
     return name, value, description
 
+
 def rotate_CD_matrix(cd, pa_aper):
     """Rotate CD matrix
-    
+
     Parameters
     ----------
     cd: (2,2) array
         CD matrix
-    
+
     pa_aper: float
         Position angle, in degrees E from N, of y axis of the detector
-    
+
     Returns
     -------
     cd_rot: (2,2) array
         Rotated CD matrix
-    
+
     Comments
     --------
     `astropy.wcs.WCS.rotateCD` doesn't work for non-square pixels in that it
     doesn't preserve the pixel scale!  The bug seems to come from the fact
     that `rotateCD` assumes a transposed version of its own CD matrix.
-    
+
     """
     rad = np.deg2rad(-pa_aper)
-    mat = np.zeros((2,2))
-    mat[0,:] = np.array([np.cos(rad),-np.sin(rad)])
-    mat[1,:] = np.array([np.sin(rad),np.cos(rad)])
+    mat = np.zeros((2, 2))
+    mat[0, :] = np.array([np.cos(rad), -np.sin(rad)])
+    mat[1, :] = np.array([np.sin(rad), np.cos(rad)])
     cd_rot = np.dot(mat, cd)
     return cd_rot
 
-def calcaluteSLSRotSkyCoor(pix_xy = None,rot_angle = 1, xlen = 9216, ylen = 9232, w = None):
+
+def calcaluteSLSRotSkyCoor(pix_xy=None, rot_angle=1, xlen=9216, ylen=9232, w=None):
     rad = np.deg2rad(rot_angle)
-    mat = np.zeros((2,2))
-    mat[0,:] = np.array([np.cos(rad),-np.sin(rad)])
-    mat[1,:] = np.array([np.sin(rad),np.cos(rad)])
+    mat = np.zeros((2, 2))
+    mat[0, :] = np.array([np.cos(rad), -np.sin(rad)])
+    mat[1, :] = np.array([np.sin(rad), np.cos(rad)])
     center = np.array([xlen/2, ylen/2])
     rot_pix = np.dot(mat, pix_xy-center) + center
     skyCoor = w.wcs_pix2world(np.array([rot_pix]), 1)
@@ -172,10 +175,9 @@ def calcaluteSLSRotSkyCoor(pix_xy = None,rot_angle = 1, xlen = 9216, ylen = 9232
 #     return name, value, description
 
 
-##9232 9216  898 534 1309 60 -40  -23.4333
-def WCS_def(xlen = 9216, ylen = 9232, gapy = 898.0, gapx1 = 534, gapx2 = 1309, ra_ref = 60, dec_ref = -40, pa = -23.433, pixel_scale = 0.074, pixel_size=1e-2, 
-    rotate_chip=0., filter = 'GI', row_num = None, col_num = None, xcen = None, ycen = None):
-
+# 9232 9216  898 534 1309 60 -40  -23.4333
+def WCS_def(xlen=9216, ylen=9232, gapy=898.0, gapx1=534, gapx2=1309, ra_ref=60, dec_ref=-40, pa=-23.433, pixel_scale=0.074, pixel_size=1e-2,
+            rotate_chip=0., filter='GI', row_num=None, col_num=None, xcen=None, ycen=None):
     """ Creat a wcs frame for CCST with multiple extensions
 
     Parameters
@@ -189,11 +191,11 @@ def WCS_def(xlen = 9216, ylen = 9232, gapy = 898.0, gapx1 = 534, gapx2 = 1309, r
     r_dat['CTYPE2'] = 'DEC--TAN'
     r_dat['CRVAL1'] = ra_ref
     r_dat['CRVAL2'] = dec_ref
-    
+
     flag_x = [0, 1, -1, 1, -1]
     flag_y = [0, 1, 1, -1, -1]
-    flag_ext_x = [0,-1,1,-1,1]
-    flag_ext_y = [0,-1,-1,1,1]
+    flag_ext_x = [0, -1, 1, -1, 1]
+    flag_ext_y = [0, -1, -1, 1, 1]
     pa_aper = pa
 
     if (row_num is not None) and (col_num is not None):
@@ -205,35 +207,42 @@ def WCS_def(xlen = 9216, ylen = 9232, gapy = 898.0, gapx1 = 534, gapx2 = 1309, r
         detector_size_x = xlen
         detector_size_y = ylen
         gap_y = gapy
-        gap_x = [gapx1,gapx2]
+        gap_x = [gapx1, gapx2]
 
         gap_x1_num = 3
         gap_x2_num = 2
 
         y_center = (detector_size_y*y_num+gap_y*(y_num-1))/2
 
-        x_center = (detector_size_x*x_num+gap_x[0]*gap_x1_num+gap_x[1]*gap_x2_num)/2
+        x_center = (detector_size_x*x_num +
+                    gap_x[0]*gap_x1_num+gap_x[1]*gap_x2_num)/2
+
+        gap_x_map = np.array([[0, 0, 0, 0, 0], [gap_x[0], gap_x[1], gap_x[1], gap_x[1], gap_x[1]], [gap_x[1], gap_x[0], gap_x[0], gap_x[0], gap_x[0]], [
+                             gap_x[0], gap_x[0], gap_x[0], gap_x[0], gap_x[0]], [gap_x[0], gap_x[0], gap_x[0], gap_x[0], gap_x[1]], [gap_x[1], gap_x[1], gap_x[1], gap_x[1], gap_x[0]]])
 
-        gap_x_map = np.array([[0,0,0,0,0],[gap_x[0],gap_x[1],gap_x[1],gap_x[1],gap_x[1]],[gap_x[1],gap_x[0],gap_x[0],gap_x[0],gap_x[0]],[gap_x[0],gap_x[0],gap_x[0],gap_x[0],gap_x[0]],[gap_x[0],gap_x[0],gap_x[0],gap_x[0],gap_x[1]],[gap_x[1],gap_x[1],gap_x[1],gap_x[1],gap_x[0]]])
-        
         j = row_num
         i = col_num
         # ccdnum = str((j-1)*5+i)
 
-        x_ref, y_ref = detector_size_x*i + sum(gap_x_map[0:i,j-1]) - detector_size_x/2. , (detector_size_y+gap_y)*j-gap_y-detector_size_y/2
-        
-        for k in range(1,2):
-            
-            cd = np.array([[ pixel_scale,  0], [0, pixel_scale]])/3600.*flag_x[k]
+        x_ref, y_ref = detector_size_x*i + \
+            sum(gap_x_map[0:i, j-1]) - detector_size_x / \
+            2., (detector_size_y+gap_y)*j-gap_y-detector_size_y/2
+
+        for k in range(1, 2):
+
+            cd = np.array([[pixel_scale,  0], [0, pixel_scale]]) / \
+                3600.*flag_x[k]
             cd_rot = rotate_CD_matrix(cd, pa_aper)
 
             # f = open("CCD"+ccdnum.rjust(2,'0')+"_extension"+str(k)+"_wcs.param","w")
-            r_dat['CRPIX1'] = flag_ext_x[k]*((x_ref+flag_ext_x[k]*detector_size_x/2)-x_center)
-            r_dat['CRPIX2'] = flag_ext_y[k]*((y_ref+flag_ext_y[k]*detector_size_y/2)-y_center)
-            r_dat['CD1_1'] = cd_rot[0,0]
-            r_dat['CD1_2'] = cd_rot[0,1]
-            r_dat['CD2_1'] = cd_rot[1,0]
-            r_dat['CD2_2'] = cd_rot[1,1]
+            r_dat['CRPIX1'] = flag_ext_x[k] * \
+                ((x_ref+flag_ext_x[k]*detector_size_x/2)-x_center)
+            r_dat['CRPIX2'] = flag_ext_y[k] * \
+                ((y_ref+flag_ext_y[k]*detector_size_y/2)-y_center)
+            r_dat['CD1_1'] = cd_rot[0, 0]
+            r_dat['CD1_2'] = cd_rot[0, 1]
+            r_dat['CD2_1'] = cd_rot[1, 0]
+            r_dat['CD2_2'] = cd_rot[1, 1]
 
             if filter in ['GU', 'GV', 'GI']:
 
@@ -265,12 +274,13 @@ def WCS_def(xlen = 9216, ylen = 9232, gapy = 898.0, gapx1 = 534, gapx2 = 1309, r
                         y_pixs[i_pix] = y
 
                         pix_coor = np.array([x, y])
-                        sc1 = calcaluteSLSRotSkyCoor(pix_xy=pix_coor, rot_angle=sls_rot, xlen=xlen, ylen=ylen, w=w)
+                        sc1 = calcaluteSLSRotSkyCoor(
+                            pix_xy=pix_coor, rot_angle=sls_rot, xlen=xlen, ylen=ylen, w=w)
                         # print(sc1[0,0],sc1[0,1])
                         sky_coors.append((sc1[0, 0], sc1[0, 1]))
 
                 wcs_new = fit_wcs_from_points(xy=np.array([x_pixs, y_pixs]),
-                                            world_coords=SkyCoord(sky_coors, frame="icrs", unit="deg"), projection='TAN')
+                                              world_coords=SkyCoord(sky_coors, frame="icrs", unit="deg"), projection='TAN')
 
                 # print(wcs_new)
                 # test_center = wcs_new.wcs_pix2world(np.array([[xlen / 2, ylen / 2]]), 1)
@@ -294,12 +304,12 @@ def WCS_def(xlen = 9216, ylen = 9232, gapy = 898.0, gapx1 = 534, gapx2 = 1309, r
         r_dat['CRPIX2'] = -y1
 
         # cd = np.array([[ pixel_scale,  0], [0, pixel_scale]])/3600.*flag_x[1]
-        cd = np.array([[ pixel_scale,  0], [0, -pixel_scale]])/3600.
+        cd = np.array([[pixel_scale,  0], [0, -pixel_scale]])/3600.
         cd_rot = rotate_CD_matrix(cd, pa_aper)
-        r_dat['CD1_1'] = cd_rot[0,0]
-        r_dat['CD1_2'] = cd_rot[0,1]
-        r_dat['CD2_1'] = cd_rot[1,0]
-        r_dat['CD2_2'] = cd_rot[1,1]
+        r_dat['CD1_1'] = cd_rot[0, 0]
+        r_dat['CD1_2'] = cd_rot[0, 1]
+        r_dat['CD2_1'] = cd_rot[1, 0]
+        r_dat['CD2_2'] = cd_rot[1, 1]
 
         w = wcs.WCS(naxis=2)
         w.wcs.crpix = [r_dat['CRPIX1'], r_dat['CRPIX2']]
@@ -320,10 +330,12 @@ def WCS_def(xlen = 9216, ylen = 9232, gapy = 898.0, gapx1 = 534, gapx2 = 1309, r
                 x_pixs[i_pix] = x
                 y_pixs[i_pix] = y
                 pix_coor = np.array([x, y])
-                sc1 = calcaluteSLSRotSkyCoor(pix_xy=pix_coor, rot_angle=rotate_chip, xlen=xlen, ylen=ylen, w=w)
+                sc1 = calcaluteSLSRotSkyCoor(
+                    pix_xy=pix_coor, rot_angle=rotate_chip, xlen=xlen, ylen=ylen, w=w)
                 sky_coors.append((sc1[0, 0], sc1[0, 1]))
-        wcs_new = fit_wcs_from_points(xy=np.array([x_pixs, y_pixs]), 
-                                      world_coords=SkyCoord(sky_coors, frame="icrs", unit="deg"), 
+        wcs_new = fit_wcs_from_points(xy=np.array([x_pixs, y_pixs]),
+                                      world_coords=SkyCoord(
+                                          sky_coors, frame="icrs", unit="deg"),
                                       projection='TAN')
         r_dat['CD1_1'] = wcs_new.wcs.cd[0, 0]
         r_dat['CD1_2'] = wcs_new.wcs.cd[0, 1]
@@ -336,30 +348,31 @@ def WCS_def(xlen = 9216, ylen = 9232, gapy = 898.0, gapx1 = 534, gapx2 = 1309, r
         r_dat['CRVAL2'] = wcs_new.wcs.crval[1]
 
     else:
-        raise ValueError('In function WCS_def(): Either (row_num, col_num) or (xcen, ycen, pixel_size) should be given')
-    
-    return r_dat
+        raise ValueError(
+            'In function WCS_def(): Either (row_num, col_num) or (xcen, ycen, pixel_size) should be given')
 
+    return r_dat
 
 
-#TODO project_cycle is temporary, is not in header defined, delete in future
-def generatePrimaryHeader(xlen = 9216, ylen = 9232, pointing_id = '00000001', pointing_type_code='101', ra = 60, dec = -40, pixel_scale = 0.074, time_pt = None, im_type = 'SCI', exptime=150., sat_pos = [0.,0.,0.], sat_vel = [0., 0., 0.], project_cycle=6, run_counter=0, chip_name="01"):
+# TODO project_cycle is temporary, is not in header defined, delete in future
+def generatePrimaryHeader(xlen=9216, ylen=9232, pointing_id='00000001', pointing_type_code='101', ra=60, dec=-40, pixel_scale=0.074, time_pt=None, im_type='SCI', exptime=150., sat_pos=[0., 0., 0.], sat_vel=[0., 0., 0.], project_cycle=6, run_counter=0, chip_name="01"):
 
     # array_size1, array_size2, flux, sigma = int(argv[1]), int(argv[2]), 1000.0, 5.0
 
-    
     # k = (row_num-1)*6+col_num
     # ccdnum = str(k)
 
     datetime_obs = datetime.utcfromtimestamp(time_pt)
     datetime_obs = datetime_obs.replace(tzinfo=timezone.utc)
     # print(datetime_obs.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5])
-    datetime_obs = datetime.utcfromtimestamp(np.round(datetime_obs.timestamp(), 1))
+    datetime_obs = datetime.utcfromtimestamp(
+        np.round(datetime_obs.timestamp(), 1))
     # print(datetime_obs.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5])
     # date_obs = datetime_obs.strftime("%y%m%d")
     # time_obs = datetime_obs.strftime("%H%M%S%f")[:-5]
 
-    g_header_fn = os.path.split(os.path.realpath(__file__))[0] + '/csst_msc_l0_ms.fits'
+    g_header_fn = os.path.split(os.path.realpath(__file__))[
+        0] + '/csst_msc_l0_ms.fits'
     f = open(os.path.split(os.path.realpath(__file__))[0] + '/filter.lst')
     s = f.readline()
     s = s.strip("\n")
@@ -386,7 +399,6 @@ def generatePrimaryHeader(xlen = 9216, ylen = 9232, pointing_id = '00000001', po
     #     h_card = fits.card.Card(header_toml[h_key][key]['key'],header_toml[h_key][key]['example'],header_toml[h_key][key]['comment'])
     #     h_prim.append(h_card)
 
-
     # h_prim['PIXSIZE1'] = xlen
     # h_prim['PIXSIZE2'] = ylen
 
@@ -404,14 +416,15 @@ def generatePrimaryHeader(xlen = 9216, ylen = 9232, pointing_id = '00000001', po
 
     # # OBS_id = '1'+ obs_type[im_type] + str(int(project_cycle)) + pointNum.rjust(7,'0')
     # OBS_id = '1'+ obs_type[im_type] + str(int(project_cycle)) + str(int(run_counter)).rjust(2, '0') + pointNum.rjust(5,'0')
-    OBS_id = get_obs_id(img_type=im_type, project_cycle=project_cycle, run_counter=run_counter, pointing_id=pointing_id, pointing_type_code = pointing_type_code)
+    OBS_id = get_obs_id(img_type=im_type, project_cycle=project_cycle, run_counter=run_counter,
+                        pointing_id=pointing_id, pointing_type_code=pointing_type_code)
 
     # h_prim['OBJECT'] = str(int(project_cycle)) + pointNum.rjust(7, '0')
     h_prim['OBJECT'] = pointing_id
     h_prim['OBSID'] = OBS_id
     # h_prim['TELFOCUS'] = 'f/14'
     h_prim['EXPTIME'] = exptime
-    
+
     # # Define file types
     # file_type = {'SCI':'SCIE', 'BIAS':'BIAS', 'DARK':'DARK', 'FLAT':'FLAT', 'CRS':'CRS', 'CRD':'CRD','CALS':'CALS','CALF':'CALF'}
     # h_prim['FILETYPE'] = file_type[im_type]
@@ -420,8 +433,10 @@ def generatePrimaryHeader(xlen = 9216, ylen = 9232, pointing_id = '00000001', po
 
     co = coord.SkyCoord(ra, dec, unit='deg')
 
-    ra_hms = format(co.ra.hms.h, '02.0f') + format(co.ra.hms.m, '02.0f') + format(co.ra.hms.s, '02.1f')
-    dec_hms = format(co.dec.dms.d, '02.0f') + format(abs(co.dec.dms.m), '02.0f') + format(abs(co.dec.dms.s), '02.0f')
+    ra_hms = format(co.ra.hms.h, '02.0f') + format(co.ra.hms.m,
+                                                   '02.0f') + format(co.ra.hms.s, '02.1f')
+    dec_hms = format(co.dec.dms.d, '02.0f') + format(abs(co.dec.dms.m),
+                                                     '02.0f') + format(abs(co.dec.dms.s), '02.0f')
     if dec >= 0:
         h_prim['TARGET'] = ra_hms + '+' + dec_hms
     else:
@@ -435,8 +450,6 @@ def generatePrimaryHeader(xlen = 9216, ylen = 9232, pointing_id = '00000001', po
     h_prim['RA_PNT1'] = ra
     h_prim['DEC_PNT1'] = dec
 
-
-
     # h_prim['PIXSCAL1'] = pixel_scale
     # h_prim['PIXSCAL2'] = pixel_scale
 
@@ -452,11 +465,13 @@ def generatePrimaryHeader(xlen = 9216, ylen = 9232, pointing_id = '00000001', po
     # file_start_time = '20' + date[0:6] + time_obs[0:6]
     file_start_time = datetime_obs.strftime("%Y%m%d%H%M%S")
     end_time_str = str(tend.datetime)
-    file_end_time = end_time_str[0:4] + end_time_str[5:7]+end_time_str[8:10] + end_time_str[11:13] + end_time_str[14:16] + end_time_str[17:19]
+    file_end_time = end_time_str[0:4] + end_time_str[5:7]+end_time_str[8:10] + \
+        end_time_str[11:13] + end_time_str[14:16] + end_time_str[17:19]
     # h_prim['FILENAME'] = 'CSST_MSC_MS_' + im_type + '_' + file_start_time + '_' + file_end_time + '_' + OBS_id + '_' + CCDID[
     #     k - 1].rjust(2, '0') + '_L0_V01'
-    h_prim['FILENAME'] = 'CSST_MSC_MS_' + h_prim['FILETYPE'] + '_' + file_start_time + '_' + file_end_time + '_' + OBS_id + '_' + chip_name + '_L0_V01'
-
+    h_prim['FILENAME'] = 'CSST_MSC_MS_' + h_prim['FILETYPE'] + '_' + \
+        file_start_time + '_' + file_end_time + \
+        '_' + OBS_id + '_' + chip_name + '_L0_V01'
 
     h_prim['POSI0_X'] = sat_pos[0]
     h_prim['POSI0_Y'] = sat_pos[1]
@@ -467,21 +482,25 @@ def generatePrimaryHeader(xlen = 9216, ylen = 9232, pointing_id = '00000001', po
     h_prim['VELO0_Z'] = sat_vel[2]
     # h_prim['RA_PNT0'] = ra_hms
     # h_prim['DEC_PNT0'] = dec_hms
-    
+
     # Get version of CSSTSim Package
     from pkg_resources import get_distribution
     # h_prim['SIM_VER'] = (get_distribution("CSSTSim").version, "Version of CSST MSC simulation software")
     currentDateAndTime = datetime.now()
     compute_name = platform.node()
-    h_prim['FITSSWV'] = get_distribution("csst_msc_sim").version +'_' + currentDateAndTime.strftime("%Y%m%d") + '_' +compute_name
-    h_prim['EPOCH'] = round((Time(h_prim['EXPSTART'], format='mjd', scale='tcb')).jyear, 1)
+    h_prim['FITSSWV'] = get_distribution(
+        "csst_msc_sim").version + '_' + currentDateAndTime.strftime("%Y%m%d") + '_' + compute_name
+    h_prim['EPOCH'] = round(
+        (Time(h_prim['EXPSTART'], format='mjd', scale='tcb')).jyear, 1)
 
     return h_prim
 
-def generateExtensionHeader(chip, xlen = 9216, ylen = 9232,ra = 60, dec = -40, pa = -23.433, gain = 1.0, readout = 5.0, dark = 0.02, saturation=90000, pixel_scale = 0.074, pixel_size=1e-2, 
-                            extName='SCIE', row_num = None, col_num = None, xcen=None, ycen=None, timestamp = 1621915200,exptime = 150., readoutTime = 40., t_shutter_open = 1.3, t_shutter_close = 1.3):
 
-    e_header_fn = os.path.split(os.path.realpath(__file__))[0] + '/csst_msc_l0_ms.fits'
+def generateExtensionHeader(chip, xlen=9216, ylen=9232, ra=60, dec=-40, pa=-23.433, gain=1.0, readout=5.0, dark=0.02, saturation=90000, pixel_scale=0.074, pixel_size=1e-2,
+                            extName='SCIE', row_num=None, col_num=None, xcen=None, ycen=None, timestamp=1621915200, exptime=150., readoutTime=40., t_shutter_open=1.3, t_shutter_close=1.3):
+
+    e_header_fn = os.path.split(os.path.realpath(__file__))[
+        0] + '/csst_msc_l0_ms.fits'
     f = open(os.path.split(os.path.realpath(__file__))[0] + '/filter.lst')
     s = f.readline()
     s = s.strip("\n")
@@ -562,28 +581,35 @@ def generateExtensionHeader(chip, xlen = 9216, ylen = 9232,ra = 60, dec = -40, p
     t_shutter_os = tstart
     t_shutter_oe = Time(tstart.mjd + t_shutter_open / 86400., format="mjd")
     t_shutter_co = Time(tstart.mjd + exptime / 86400., format="mjd")
-    t_shutter_ce = Time(tstart.mjd + (exptime + t_shutter_close) / 86400., format="mjd")
-    t_shutter_os1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(t_shutter_os.unix).replace(tzinfo=timezone.utc).timestamp(), 1))
+    t_shutter_ce = Time(
+        tstart.mjd + (exptime + t_shutter_close) / 86400., format="mjd")
+    t_shutter_os1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(
+        t_shutter_os.unix).replace(tzinfo=timezone.utc).timestamp(), 1))
     h_ext['SHTOPEN0'] = t_shutter_os1.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5]
-    t_shutter_oe1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(t_shutter_oe.unix).replace(tzinfo=timezone.utc).timestamp(), 1))
+    t_shutter_oe1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(
+        t_shutter_oe.unix).replace(tzinfo=timezone.utc).timestamp(), 1))
     h_ext['SHTOPEN1'] = t_shutter_oe1.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5]
-    t_shutter_co1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(t_shutter_co.unix).replace(tzinfo=timezone.utc).timestamp(), 1))
+    t_shutter_co1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(
+        t_shutter_co.unix).replace(tzinfo=timezone.utc).timestamp(), 1))
     h_ext['SHTCLOS0'] = t_shutter_co1.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5]
-    t_shutter_ce1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(t_shutter_ce.unix).replace(tzinfo=timezone.utc).timestamp(), 1))
+    t_shutter_ce1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(
+        t_shutter_ce.unix).replace(tzinfo=timezone.utc).timestamp(), 1))
     h_ext['SHTCLOS1'] = t_shutter_ce1.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5]
-    
 
     tstart_read = Time(tstart.mjd + exptime / 86400., format="mjd")
-    tend_read = Time(tstart.mjd + (exptime + readoutTime) / 86400., format="mjd")
+    tend_read = Time(tstart.mjd + (exptime + readoutTime) /
+                     86400., format="mjd")
     # tstart1=tstart.datetime.replace(microsecond=round(tstart.datetime.microsecond, -5))
-    tstart1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(tstart_read.unix).replace(tzinfo=timezone.utc).timestamp(), 1))
+    tstart1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(
+        tstart_read.unix).replace(tzinfo=timezone.utc).timestamp(), 1))
     h_ext['ROTIME0'] = tstart1.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5]
     # tend_read1 = tend_read.datetime.replace(microsecond=round(tend_read.datetime.microsecond, -5))
-    tend_read1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(tend_read.unix).replace(tzinfo=timezone.utc).timestamp(), 1))
+    tend_read1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(
+        tend_read.unix).replace(tzinfo=timezone.utc).timestamp(), 1))
     h_ext['ROTIME1'] = tend_read1.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5]
     # h_ext['POS_ANG'] = pa
-    header_wcs = WCS_def(xlen=xlen, ylen=ylen, gapy=898.0, gapx1=534, gapx2=1309, ra_ref=ra, dec_ref=dec, pa=pa, pixel_scale=pixel_scale, pixel_size=pixel_size, 
-                         rotate_chip=chip.rotate_angle, filter = h_ext['FILTER'], row_num=row_num, col_num=col_num, xcen = xcen, ycen = ycen)
+    header_wcs = WCS_def(xlen=xlen, ylen=ylen, gapy=898.0, gapx1=534, gapx2=1309, ra_ref=ra, dec_ref=dec, pa=pa, pixel_scale=pixel_scale, pixel_size=pixel_size,
+                         rotate_chip=chip.rotate_angle, filter=h_ext['FILTER'], row_num=row_num, col_num=col_num, xcen=xcen, ycen=ycen)
 
     h_ext['CRPIX1'] = header_wcs['CRPIX1']
     h_ext['CRPIX2'] = header_wcs['CRPIX2']
@@ -604,7 +630,6 @@ def generateExtensionHeader(chip, xlen = 9216, ylen = 9232,ra = 60, dec = -40, p
     return h_ext
 
 
-
 def main(argv):
 
     xlen = int(argv[1])
@@ -621,17 +646,17 @@ def main(argv):
     dark = float(argv[12])
     fw = float(argv[13])
 
+    h_prim = generatePrimaryHeader(xlen=xlen, ylen=ylen, ra=ra, dec=dec, psize=pSize,
+                                   row_num=ccd_row_num, col_num=ccd_col_num, pointNum=pointingNum)
 
-
-    h_prim = generatePrimaryHeader(xlen = xlen, ylen = ylen,ra = ra, dec = dec, psize = pSize, row_num = ccd_row_num, col_num = ccd_col_num, pointNum = pointingNum)
-
-    h_ext = generateExtensionHeader(xlen = xlen, ylen = ylen,ra = ra, dec = dec, pa = pa_aper, gain = gain, readout = readout, dark = dark, saturation=fw, psize = pSize, row_num = ccd_row_num, col_num = ccd_col_num)
+    h_ext = generateExtensionHeader(xlen=xlen, ylen=ylen, ra=ra, dec=dec, pa=pa_aper, gain=gain,
+                                    readout=readout, dark=dark, saturation=fw, psize=pSize, row_num=ccd_row_num, col_num=ccd_col_num)
     hdu1 = fits.PrimaryHDU(header=h_prim)
-    hdu2 = fits.ImageHDU(np.zeros([ylen,xlen]),header = h_ext)
+    hdu2 = fits.ImageHDU(np.zeros([ylen, xlen]), header=h_ext)
 
-    hdul = fits.HDUList([hdu1,hdu2])
+    hdul = fits.HDUList([hdu1, hdu2])
 
-    hdul.writeto(h_prim['FILENAME']+'.fits',output_verify='ignore')
+    hdul.writeto(h_prim['FILENAME']+'.fits', output_verify='ignore')
 
 # if __name__ == "__main__":
 #     main(sys.argv)
diff --git a/ObservationSim/Config/Header/Readme.pdf b/observation_sim/config/header/Readme.pdf
similarity index 100%
rename from ObservationSim/Config/Header/Readme.pdf
rename to observation_sim/config/header/Readme.pdf
diff --git a/ObservationSim/Config/Header/__init__.py b/observation_sim/config/header/__init__.py
similarity index 100%
rename from ObservationSim/Config/Header/__init__.py
rename to observation_sim/config/header/__init__.py
diff --git a/ObservationSim/Config/Header/csst_msc_l0_ms.fits b/observation_sim/config/header/csst_msc_l0_ms.fits
similarity index 100%
rename from ObservationSim/Config/Header/csst_msc_l0_ms.fits
rename to observation_sim/config/header/csst_msc_l0_ms.fits
diff --git a/ObservationSim/Config/Header/extension_header.header b/observation_sim/config/header/extension_header.header
similarity index 100%
rename from ObservationSim/Config/Header/extension_header.header
rename to observation_sim/config/header/extension_header.header
diff --git a/ObservationSim/Config/Header/extension_header.param b/observation_sim/config/header/extension_header.param
similarity index 100%
rename from ObservationSim/Config/Header/extension_header.param
rename to observation_sim/config/header/extension_header.param
diff --git a/ObservationSim/Config/Header/filter.lst b/observation_sim/config/header/filter.lst
similarity index 100%
rename from ObservationSim/Config/Header/filter.lst
rename to observation_sim/config/header/filter.lst
diff --git a/ObservationSim/Config/Header/global_header.header b/observation_sim/config/header/global_header.header
similarity index 100%
rename from ObservationSim/Config/Header/global_header.header
rename to observation_sim/config/header/global_header.header
diff --git a/ObservationSim/Config/Header/global_header.param b/observation_sim/config/header/global_header.param
similarity index 100%
rename from ObservationSim/Config/Header/global_header.param
rename to observation_sim/config/header/global_header.param
diff --git a/ObservationSim/Instrument/Filter.py b/observation_sim/instruments/Filter.py
similarity index 58%
rename from ObservationSim/Instrument/Filter.py
rename to observation_sim/instruments/Filter.py
index efc58694b2a75b6016b4653689be89bf24fda151..6a01ca972d59ec767694de21009f769ae160c2ff 100755
--- a/ObservationSim/Instrument/Filter.py
+++ b/observation_sim/instruments/Filter.py
@@ -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,57 +53,67 @@ 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)
-            
+
         return bandpass_full, bandpass_sub_list
 
     def getPhotonE(self):
@@ -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))
diff --git a/ObservationSim/Instrument/FilterParam.py b/observation_sim/instruments/FilterParam.py
similarity index 52%
rename from ObservationSim/Instrument/FilterParam.py
rename to observation_sim/instruments/FilterParam.py
index 8f87b8fffd1f661b7c1eb2ef3eec352a5e24f94f..fe109274d48f88d71a8f97cfc1004aa4858f829b 100755
--- a/ObservationSim/Instrument/FilterParam.py
+++ b/observation_sim/instruments/FilterParam.py
@@ -1,6 +1,7 @@
 import galsim
 import numpy as np
 
+
 class FilterParam(object):
     def __init__(self, filter_dir=None, filter_param=None):
         self.param = self._filtParam(filter_param)
@@ -14,7 +15,7 @@ class FilterParam(object):
         TODO: subject to change
         Basic parameters of the CSSOS filters.
         """
-        # filter parameters: name: 
+        # filter parameters: name:
         # 1) effective wavelength
         # 2) effective width
         # 3) blue end
@@ -26,19 +27,20 @@ class FilterParam(object):
         # 8) dim end magnitude
         if filter_param == None:
             filtP = {
-                    "NUV":   [2867.7,   705.4,  2470.0,   3270.0,  0.1404, 0.004, 15.7, 25.4],
-                    "u":     [3601.1,   852.1,  3120.0,   4090.0,  0.2176, 0.021, 16.1, 25.4],
-                    "g":     [4754.5,  1569.8,  3900.0,   5620.0,  0.4640, 0.164, 17.2, 26.3],
-                    "r":     [6199.8,  1481.2,  5370.0,   7030.0,  0.5040, 0.207, 17.0, 26.0],
-                    "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]
-                    
-                    "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],
-                    "GI":    [0.0,        0.0,  6200.0,  10000.0,     1.0, 0.037, 14.0, 26.0],
-                    }
+                "NUV":   [2867.7,   705.4,  2470.0,   3270.0,  0.1404, 0.004, 15.7, 25.4],
+                "u":     [3601.1,   852.1,  3120.0,   4090.0,  0.2176, 0.021, 16.1, 25.4],
+                "g":     [4754.5,  1569.8,  3900.0,   5620.0,  0.4640, 0.164, 17.2, 26.3],
+                "r":     [6199.8,  1481.2,  5370.0,   7030.0,  0.5040, 0.207, 17.0, 26.0],
+                "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],
+                # [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],
+                "GI":    [0.0,        0.0,  6200.0,  10000.0,     1.0, 0.037, 14.0, 26.0],
+            }
         else:
             filtP = filter_param
 
@@ -48,10 +50,10 @@ class FilterParam(object):
         """
         read filters and save into Python dictionary
         NOTE: the wavelength unit must be in "Angstrom"
-        
+
         Parameters:
         Same as function 'seds'
-        
+
         Return:
         Same as function 'seds'
         """
@@ -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)
-            wave  = ifilt.wave_list
+            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
\ No newline at end of file
+        return filtype, filts
diff --git a/ObservationSim/Instrument/FocalPlane.py b/observation_sim/instruments/FocalPlane.py
similarity index 81%
rename from ObservationSim/Instrument/FocalPlane.py
rename to observation_sim/instruments/FocalPlane.py
index b3e309cf2a7b6f659794dece5de2ae326ee0757b..90c2e0e7372cc2d398ab694248364e8fb73da097 100755
--- a/ObservationSim/Instrument/FocalPlane.py
+++ b/observation_sim/instruments/FocalPlane.py
@@ -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
diff --git a/observation_sim/instruments/Telescope.py b/observation_sim/instruments/Telescope.py
new file mode 100755
index 0000000000000000000000000000000000000000..d6c1d2fabc50ab3540026b6655e58f55ad546794
--- /dev/null
+++ b/observation_sim/instruments/Telescope.py
@@ -0,0 +1,45 @@
+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
diff --git a/ObservationSim/Instrument/__init__.py b/observation_sim/instruments/__init__.py
similarity index 82%
rename from ObservationSim/Instrument/__init__.py
rename to observation_sim/instruments/__init__.py
index 9382b644e158ac51e146154936c506d3c599474a..75773a6e43e81a36d8363461aeea30ff0903c527 100755
--- a/ObservationSim/Instrument/__init__.py
+++ b/observation_sim/instruments/__init__.py
@@ -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
diff --git a/observation_sim/instruments/_util.py b/observation_sim/instruments/_util.py
new file mode 100755
index 0000000000000000000000000000000000000000..953d229d49e04e8818427d8c26fb9e12fbf80780
--- /dev/null
+++ b/observation_sim/instruments/_util.py
@@ -0,0 +1,134 @@
+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
diff --git a/observation_sim/instruments/chip/Chip.py b/observation_sim/instruments/chip/Chip.py
new file mode 100755
index 0000000000000000000000000000000000000000..e50b6640133512bba4da952d5e80613d01d6eda8
--- /dev/null
+++ b/observation_sim/instruments/chip/Chip.py
@@ -0,0 +1,280 @@
+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
diff --git a/ObservationSim/Instrument/Chip/__init__.py b/observation_sim/instruments/chip/__init__.py
similarity index 100%
rename from ObservationSim/Instrument/Chip/__init__.py
rename to observation_sim/instruments/chip/__init__.py
diff --git a/ObservationSim/Instrument/Chip/ChipUtils.py b/observation_sim/instruments/chip/chip_utils.py
similarity index 57%
rename from ObservationSim/Instrument/Chip/ChipUtils.py
rename to observation_sim/instruments/chip/chip_utils.py
index 3de5e02d48285a563c0f8b25d6bf6340808c0d23..cb16118e6916d39a850521f6f164c019cddccf3d 100644
--- a/ObservationSim/Instrument/Chip/ChipUtils.py
+++ b/observation_sim/instruments/chip/chip_utils.py
@@ -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,52 +21,79 @@ 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
         img_type_code = pointing.pointing_type_code
 
     h_prim = generatePrimaryHeader(
-        xlen=chip.npix_x, 
-        ylen=chip.npix_y, 
-        pointing_id = pointing.obs_id,
-        pointing_type_code = img_type_code, 
-        ra=pointing.ra, 
-        dec=pointing.dec, 
+        xlen=chip.npix_x,
+        ylen=chip.npix_y,
+        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],
@@ -76,16 +103,16 @@ def generateHeader(chip, pointing, img_type=None, img_type_code=None, project_cy
         chip_name=str(chip.chipID).rjust(2, '0'))
     h_ext = generateExtensionHeader(
         chip=chip,
-        xlen=chip.npix_x, 
-        ylen=chip.npix_y, 
-        ra=pointing.ra, 
-        dec=pointing.dec, 
-        pa=pointing.img_pa.deg, 
-        gain=chip.gain, 
-        readout=chip.read_noise, 
-        dark=chip.dark_noise, 
-        saturation=90000, 
-        pixel_scale=chip.pix_scale, 
+        xlen=chip.npix_x,
+        ylen=chip.npix_y,
+        ra=pointing.ra,
+        dec=pointing.dec,
+        pa=pointing.img_pa.deg,
+        gain=chip.gain,
+        readout=chip.read_noise,
+        dark=chip.dark_noise,
+        saturation=90000,
+        pixel_scale=chip.pix_scale,
         pixel_size=chip.pix_size,
         xcen=chip.x_cen,
         ycen=chip.y_cen,
@@ -93,15 +120,16 @@ def generateHeader(chip, pointing, img_type=None, img_type_code=None, project_cy
         timestamp=pointing.timestamp,
         exptime=pointing.exp_time,
         readoutTime=chip.readout_time,
-        t_shutter_open=pointing.t_shutter_open, 
+        t_shutter_open=pointing.t_shutter_open,
         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, 
-        pointing=pointing, 
-        img_type=img_type, 
+        chip=chip,
+        pointing=pointing,
+        img_type=img_type,
         img_type_code=img_type_code,
         project_cycle=project_cycle,
         run_counter=run_counter)
@@ -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:
@@ -130,24 +159,26 @@ def add_sky_background(img, filt, exptime, sky_map=None, tel=None):
         #     sky_map.addNoise(poisson_noise)
     elif img.array.shape != sky_map.shape:
         raise ValueError("The shape img and sky_map must be equal.")
-    elif tel is not None: # If sky_map is given in flux
+    elif tel is not None:  # If sky_map is given in flux
         sky_map = sky_map * tel.pupil_area * exptime
     img += sky_map
     return img, sky_map
 
+
 def get_flat(img, seed):
     flat_img = effects.MakeFlatSmooth(
-                GSBounds=img.bounds, 
-                seed=seed)
+        GSBounds=img.bounds,
+        seed=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, 
-        exTime=exptime+0.5*chip.readout_time, 
+        xLen=chip.npix_x, yLen=chip.npix_y,
+        exTime=exptime+0.5*chip.readout_time,
         cr_pixelRatio=0.003*(exptime+0.5*chip.readout_time)/600.,
-        gain=chip.gain, 
+        gain=chip.gain,
         attachedSizes=chip.attachedSizes,
         seed=seed)   # seed: obj-imaging:+0; bias:+1; dark:+2; flat:+3;
     img += cr_map
@@ -157,24 +188,27 @@ 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, 
-        ysize=chip.npix_y, 
-        sigma=0.01, 
+        xsize=chip.npix_x,
+        ysize=chip.npix_y,
+        sigma=0.01,
         seed=seed)
     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,53 +220,60 @@ 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
     bit_flag = bit_flag | (1 << 2)
 
     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,65 +285,81 @@ 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:
                 tx = ix
             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]
+            ty = iy
+            # 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)
     dy = int(ny/nsecy)
-    
+
     imgt = np.zeros([int(nsecx*nsecy), dy, dx])
     for iy in range(nsecy):
         for ix in range(nsecx):
@@ -320,17 +377,18 @@ def formatOutput(GSImage, nsecy = 2, nsecx=8):
                 imgt[chunkidx, :, :] = img[iy*dy:(iy+1)*dy, ix*dx:(ix+1)*dx]
             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
diff --git a/ObservationSim/Instrument/Chip/Effects.py b/observation_sim/instruments/chip/effects.py
similarity index 100%
rename from ObservationSim/Instrument/Chip/Effects.py
rename to observation_sim/instruments/chip/effects.py
diff --git a/ObservationSim/Instrument/Chip/libCTI/__init__.py b/observation_sim/instruments/chip/libBF/__init__.py
similarity index 100%
rename from ObservationSim/Instrument/Chip/libCTI/__init__.py
rename to observation_sim/instruments/chip/libBF/__init__.py
diff --git a/ObservationSim/Instrument/Chip/libBF/diffusion_X1.c b/observation_sim/instruments/chip/libBF/diffusion_X1.c
similarity index 100%
rename from ObservationSim/Instrument/Chip/libBF/diffusion_X1.c
rename to observation_sim/instruments/chip/libBF/diffusion_X1.c
diff --git a/ObservationSim/Instrument/Chip/libBF/nrutil.c b/observation_sim/instruments/chip/libBF/nrutil.c
similarity index 100%
rename from ObservationSim/Instrument/Chip/libBF/nrutil.c
rename to observation_sim/instruments/chip/libBF/nrutil.c
diff --git a/ObservationSim/Instrument/Chip/libBF/nrutil.h b/observation_sim/instruments/chip/libBF/nrutil.h
similarity index 100%
rename from ObservationSim/Instrument/Chip/libBF/nrutil.h
rename to observation_sim/instruments/chip/libBF/nrutil.h
diff --git a/ObservationSim/Instrument/Chip/libCTI/CTI_modeling.py b/observation_sim/instruments/chip/libCTI/CTI_modeling.py
similarity index 73%
rename from ObservationSim/Instrument/Chip/libCTI/CTI_modeling.py
rename to observation_sim/instruments/chip/libCTI/CTI_modeling.py
index fcb72adc9921a0fc08f4392e346c13b7595d18e7..6c840599d15fc24a779f554b4abd05527017bc84 100644
--- a/ObservationSim/Instrument/Chip/libCTI/CTI_modeling.py
+++ b/observation_sim/instruments/chip/libCTI/CTI_modeling.py
@@ -1,4 +1,4 @@
-from ctypes import CDLL, POINTER, c_int, c_double,c_float,c_long,c_char_p
+from ctypes import CDLL, POINTER, c_int, c_double, c_float, c_long, c_char_p
 from numpy.ctypeslib import ndpointer
 import numpy.ctypeslib as clb
 import numpy as np
@@ -10,12 +10,12 @@ import os
 
 lib_path = os.path.dirname(os.path.realpath(__file__))
 
-#lib_path += "/add_CTI.so"
+# lib_path += "/add_CTI.so"
 lib_path += "/libmoduleCTI.so"
 lib = CDLL(lib_path)
 CTI_simul = lib.__getattr__('CTI_simul')
-CTI_simul.argtypes = [POINTER(POINTER(c_int)),c_int,c_int,c_int,c_int,POINTER(c_float),POINTER(c_float),\
-                    c_float,c_float,c_float,c_int,POINTER(c_int),c_int,POINTER(POINTER(c_int))]
+CTI_simul.argtypes = [POINTER(POINTER(c_int)), c_int, c_int, c_int, c_int, POINTER(c_float), POINTER(c_float),
+                      c_float, c_float, c_float, c_int, POINTER(c_int), c_int, POINTER(POINTER(c_int))]
 '''
 get_trap_h = lib.__getattr__('save_trap_map')
 get_trap_h.argtypes = [POINTER(c_int), c_int, c_int, c_int, c_int, POINTER(c_float), c_float, c_float, c_char_p]
@@ -45,42 +45,50 @@ def bin2fits(bin_file,fits_dir,nsp,nx,ny,nmax):
             datai[j+1,:,:] = h
         fits.writeto(fits_dir+"/trap_"+str(i+1)+".fits",datai,overwrite=True)
 '''
-        
+
+
 def numpy_matrix_to_int_pointer(arr):
     int_pointer_array = (POINTER(c_int)*arr.shape[0])()
     for i in range(arr.shape[0]):
-        arr1 = np.array(arr[i].copy().tolist(),dtype=np.int32)
+        arr1 = np.array(arr[i].copy().tolist(), dtype=np.int32)
         int_pointer_array[i] = np.ctypeslib.as_ctypes(arr1)
     return int_pointer_array
-def pointer_to_numpy_matrix(arr_pointer,row,col):
-    arr = np.zeros((row,col))
+
+
+def pointer_to_numpy_matrix(arr_pointer, row, col):
+    arr = np.zeros((row, col))
     for i in range(row):
         for j in range(col):
-            arr[i,j] = arr_pointer[i][j]
+            arr[i, j] = arr_pointer[i][j]
     return arr
-def CTI_sim(im,nx,ny,noverscan,nsp,nmax,beta,w,c,t,rho_trap,trap_seeds,release_seed=0):
+
+
+def CTI_sim(im, nx, ny, noverscan, nsp, nmax, beta, w, c, t, rho_trap, trap_seeds, release_seed=0):
     image = im.T
-    nx_c,ny_c,noverscan_c,nsp_c,nmax_c = c_int(nx),c_int(ny),c_int(noverscan),c_int(nsp),c_int(nmax)
+    nx_c, ny_c, noverscan_c, nsp_c, nmax_c = c_int(nx), c_int(
+        ny), c_int(noverscan), c_int(nsp), c_int(nmax)
     ntotal = ny+noverscan
-    beta_c,w_c,c_c = c_float(beta),c_float(w),c_float(c)
+    beta_c, w_c, c_c = c_float(beta), c_float(w), c_float(c)
     t_p = np.ctypeslib.as_ctypes(t)
     rho_trap_p = np.ctypeslib.as_ctypes(rho_trap)
     image_p = numpy_matrix_to_int_pointer(image)
     trap_seeds1 = trap_seeds.astype(np.int32)
     trap_seeds_p = np.ctypeslib.as_ctypes(trap_seeds1)
     release_seed_c = c_int(release_seed)
-    image_cti = np.zeros((nx,ntotal))
+    image_cti = np.zeros((nx, ntotal))
     image_cti = image_cti.astype(np.int32)
     image_cti_p = numpy_matrix_to_int_pointer(image_cti)
     print(datetime.now())
-    CTI_simul(image_p,nx,ny,noverscan,nsp,rho_trap_p,t_p,beta,w,c,nmax,trap_seeds_p,release_seed_c,image_cti_p)
+    CTI_simul(image_p, nx, ny, noverscan, nsp, rho_trap_p, t_p, beta,
+              w, c, nmax, trap_seeds_p, release_seed_c, image_cti_p)
     print(datetime.now())
-    image_cti_result = np.zeros((nx,ntotal))
+    image_cti_result = np.zeros((nx, ntotal))
     for i in range(nx):
         for j in range(ntotal):
-            image_cti_result[i,j] = image_cti_p[i][j]
+            image_cti_result[i, j] = image_cti_p[i][j]
     return image_cti_result.T
 
+
 """
 if __name__ =='__main__':
     nx,ny,noverscan,nsp,nmax = 4608,4616,84,3,10
diff --git a/ObservationSim/Instrument/Chip/libCTI/Makefile b/observation_sim/instruments/chip/libCTI/Makefile
similarity index 100%
rename from ObservationSim/Instrument/Chip/libCTI/Makefile
rename to observation_sim/instruments/chip/libCTI/Makefile
diff --git a/ObservationSim/Instrument/data/__init__.py b/observation_sim/instruments/chip/libCTI/__init__.py
similarity index 100%
rename from ObservationSim/Instrument/data/__init__.py
rename to observation_sim/instruments/chip/libCTI/__init__.py
diff --git a/ObservationSim/Instrument/Chip/libCTI/readme b/observation_sim/instruments/chip/libCTI/readme
similarity index 100%
rename from ObservationSim/Instrument/Chip/libCTI/readme
rename to observation_sim/instruments/chip/libCTI/readme
diff --git a/ObservationSim/Instrument/Chip/libCTI/src/add_CTI.c b/observation_sim/instruments/chip/libCTI/src/add_CTI.c
similarity index 100%
rename from ObservationSim/Instrument/Chip/libCTI/src/add_CTI.c
rename to observation_sim/instruments/chip/libCTI/src/add_CTI.c
diff --git a/ObservationSim/Instrument/Chip/libCTI/src/creattraps.c b/observation_sim/instruments/chip/libCTI/src/creattraps.c
similarity index 100%
rename from ObservationSim/Instrument/Chip/libCTI/src/creattraps.c
rename to observation_sim/instruments/chip/libCTI/src/creattraps.c
diff --git a/ObservationSim/Instrument/Chip/libCTI/src/gammln.c b/observation_sim/instruments/chip/libCTI/src/gammln.c
similarity index 100%
rename from ObservationSim/Instrument/Chip/libCTI/src/gammln.c
rename to observation_sim/instruments/chip/libCTI/src/gammln.c
diff --git a/ObservationSim/Instrument/Chip/libCTI/src/gasdev.c b/observation_sim/instruments/chip/libCTI/src/gasdev.c
similarity index 100%
rename from ObservationSim/Instrument/Chip/libCTI/src/gasdev.c
rename to observation_sim/instruments/chip/libCTI/src/gasdev.c
diff --git a/ObservationSim/Instrument/Chip/libCTI/src/nrutil.c b/observation_sim/instruments/chip/libCTI/src/nrutil.c
similarity index 100%
rename from ObservationSim/Instrument/Chip/libCTI/src/nrutil.c
rename to observation_sim/instruments/chip/libCTI/src/nrutil.c
diff --git a/ObservationSim/Instrument/Chip/libCTI/src/nrutil.h b/observation_sim/instruments/chip/libCTI/src/nrutil.h
similarity index 100%
rename from ObservationSim/Instrument/Chip/libCTI/src/nrutil.h
rename to observation_sim/instruments/chip/libCTI/src/nrutil.h
diff --git a/ObservationSim/Instrument/Chip/libCTI/src/poidev.c b/observation_sim/instruments/chip/libCTI/src/poidev.c
similarity index 100%
rename from ObservationSim/Instrument/Chip/libCTI/src/poidev.c
rename to observation_sim/instruments/chip/libCTI/src/poidev.c
diff --git a/ObservationSim/Instrument/Chip/libCTI/src/ran1.c b/observation_sim/instruments/chip/libCTI/src/ran1.c
similarity index 100%
rename from ObservationSim/Instrument/Chip/libCTI/src/ran1.c
rename to observation_sim/instruments/chip/libCTI/src/ran1.c
diff --git a/ObservationSim/Instrument/Chip/libCTI/src/ran2.c b/observation_sim/instruments/chip/libCTI/src/ran2.c
similarity index 100%
rename from ObservationSim/Instrument/Chip/libCTI/src/ran2.c
rename to observation_sim/instruments/chip/libCTI/src/ran2.c
diff --git a/ObservationSim/Instrument/Chip/libCTI/src/sort.c b/observation_sim/instruments/chip/libCTI/src/sort.c
similarity index 100%
rename from ObservationSim/Instrument/Chip/libCTI/src/sort.c
rename to observation_sim/instruments/chip/libCTI/src/sort.c
diff --git a/ObservationSim/Instrument/data/ccd/__init__.py b/observation_sim/instruments/data/__init__.py
similarity index 100%
rename from ObservationSim/Instrument/data/ccd/__init__.py
rename to observation_sim/instruments/data/__init__.py
diff --git a/ObservationSim/Instrument/data/ccd/Astro_MB.txt b/observation_sim/instruments/data/ccd/Astro_MB.txt
similarity index 100%
rename from ObservationSim/Instrument/data/ccd/Astro_MB.txt
rename to observation_sim/instruments/data/ccd/Astro_MB.txt
diff --git a/ObservationSim/Instrument/data/ccd/Basic_NIR.txt b/observation_sim/instruments/data/ccd/Basic_NIR.txt
similarity index 100%
rename from ObservationSim/Instrument/data/ccd/Basic_NIR.txt
rename to observation_sim/instruments/data/ccd/Basic_NIR.txt
diff --git a/ObservationSim/Instrument/data/ccd/UV0.txt b/observation_sim/instruments/data/ccd/UV0.txt
similarity index 100%
rename from ObservationSim/Instrument/data/ccd/UV0.txt
rename to observation_sim/instruments/data/ccd/UV0.txt
diff --git a/ObservationSim/Instrument/data/field_distortion/__init__.py b/observation_sim/instruments/data/ccd/__init__.py
similarity index 100%
rename from ObservationSim/Instrument/data/field_distortion/__init__.py
rename to observation_sim/instruments/data/ccd/__init__.py
diff --git a/ObservationSim/Instrument/data/ccd/chip_definition.json b/observation_sim/instruments/data/ccd/chip_definition.json
similarity index 100%
rename from ObservationSim/Instrument/data/ccd/chip_definition.json
rename to observation_sim/instruments/data/ccd/chip_definition.json
diff --git a/ObservationSim/Instrument/data/field_distortion/FieldDistModelGlobal_mainFP_v1.0.pickle b/observation_sim/instruments/data/field_distortion/FieldDistModelGlobal_mainFP_v1.0.pickle
similarity index 100%
rename from ObservationSim/Instrument/data/field_distortion/FieldDistModelGlobal_mainFP_v1.0.pickle
rename to observation_sim/instruments/data/field_distortion/FieldDistModelGlobal_mainFP_v1.0.pickle
diff --git a/ObservationSim/Instrument/data/field_distortion/FieldDistModelGlobal_pr4_fgs1.pickle b/observation_sim/instruments/data/field_distortion/FieldDistModelGlobal_pr4_fgs1.pickle
similarity index 100%
rename from ObservationSim/Instrument/data/field_distortion/FieldDistModelGlobal_pr4_fgs1.pickle
rename to observation_sim/instruments/data/field_distortion/FieldDistModelGlobal_pr4_fgs1.pickle
diff --git a/ObservationSim/Instrument/data/field_distortion/FieldDistModelGlobal_pr4_fgs2.pickle b/observation_sim/instruments/data/field_distortion/FieldDistModelGlobal_pr4_fgs2.pickle
similarity index 100%
rename from ObservationSim/Instrument/data/field_distortion/FieldDistModelGlobal_pr4_fgs2.pickle
rename to observation_sim/instruments/data/field_distortion/FieldDistModelGlobal_pr4_fgs2.pickle
diff --git a/ObservationSim/Instrument/data/field_distortion/FieldDistModelGlobal_pr4_fgs3.pickle b/observation_sim/instruments/data/field_distortion/FieldDistModelGlobal_pr4_fgs3.pickle
similarity index 100%
rename from ObservationSim/Instrument/data/field_distortion/FieldDistModelGlobal_pr4_fgs3.pickle
rename to observation_sim/instruments/data/field_distortion/FieldDistModelGlobal_pr4_fgs3.pickle
diff --git a/ObservationSim/Instrument/data/field_distortion/FieldDistModelGlobal_pr4_fgs4.pickle b/observation_sim/instruments/data/field_distortion/FieldDistModelGlobal_pr4_fgs4.pickle
similarity index 100%
rename from ObservationSim/Instrument/data/field_distortion/FieldDistModelGlobal_pr4_fgs4.pickle
rename to observation_sim/instruments/data/field_distortion/FieldDistModelGlobal_pr4_fgs4.pickle
diff --git a/ObservationSim/Instrument/data/field_distortion/FieldDistModel_v2.0.pickle b/observation_sim/instruments/data/field_distortion/FieldDistModel_v2.0.pickle
similarity index 100%
rename from ObservationSim/Instrument/data/field_distortion/FieldDistModel_v2.0.pickle
rename to observation_sim/instruments/data/field_distortion/FieldDistModel_v2.0.pickle
diff --git a/ObservationSim/Instrument/data/filters/__init__.py b/observation_sim/instruments/data/field_distortion/__init__.py
similarity index 100%
rename from ObservationSim/Instrument/data/filters/__init__.py
rename to observation_sim/instruments/data/field_distortion/__init__.py
diff --git a/ObservationSim/Instrument/data/sls_conf/__init__.py b/observation_sim/instruments/data/filters/__init__.py
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/__init__.py
rename to observation_sim/instruments/data/filters/__init__.py
diff --git a/ObservationSim/Instrument/data/filters/fgs_sub.list b/observation_sim/instruments/data/filters/fgs_sub.list
similarity index 100%
rename from ObservationSim/Instrument/data/filters/fgs_sub.list
rename to observation_sim/instruments/data/filters/fgs_sub.list
diff --git a/ObservationSim/Instrument/data/filters/filter.list b/observation_sim/instruments/data/filters/filter.list
similarity index 100%
rename from ObservationSim/Instrument/data/filters/filter.list
rename to observation_sim/instruments/data/filters/filter.list
diff --git a/ObservationSim/Instrument/data/filters/g.txt b/observation_sim/instruments/data/filters/g.txt
similarity index 100%
rename from ObservationSim/Instrument/data/filters/g.txt
rename to observation_sim/instruments/data/filters/g.txt
diff --git a/ObservationSim/Instrument/data/filters/g_sub.list b/observation_sim/instruments/data/filters/g_sub.list
similarity index 100%
rename from ObservationSim/Instrument/data/filters/g_sub.list
rename to observation_sim/instruments/data/filters/g_sub.list
diff --git a/ObservationSim/Instrument/data/filters/gi_sub.list b/observation_sim/instruments/data/filters/gi_sub.list
similarity index 100%
rename from ObservationSim/Instrument/data/filters/gi_sub.list
rename to observation_sim/instruments/data/filters/gi_sub.list
diff --git a/ObservationSim/Instrument/data/filters/gu_sub.list b/observation_sim/instruments/data/filters/gu_sub.list
similarity index 100%
rename from ObservationSim/Instrument/data/filters/gu_sub.list
rename to observation_sim/instruments/data/filters/gu_sub.list
diff --git a/ObservationSim/Instrument/data/filters/gv_sub.list b/observation_sim/instruments/data/filters/gv_sub.list
similarity index 100%
rename from ObservationSim/Instrument/data/filters/gv_sub.list
rename to observation_sim/instruments/data/filters/gv_sub.list
diff --git a/ObservationSim/Instrument/data/filters/i.txt b/observation_sim/instruments/data/filters/i.txt
similarity index 100%
rename from ObservationSim/Instrument/data/filters/i.txt
rename to observation_sim/instruments/data/filters/i.txt
diff --git a/ObservationSim/Instrument/data/filters/i_sub.list b/observation_sim/instruments/data/filters/i_sub.list
similarity index 100%
rename from ObservationSim/Instrument/data/filters/i_sub.list
rename to observation_sim/instruments/data/filters/i_sub.list
diff --git a/ObservationSim/Instrument/data/filters/nuv.txt b/observation_sim/instruments/data/filters/nuv.txt
similarity index 100%
rename from ObservationSim/Instrument/data/filters/nuv.txt
rename to observation_sim/instruments/data/filters/nuv.txt
diff --git a/ObservationSim/Instrument/data/filters/nuv_sub.list b/observation_sim/instruments/data/filters/nuv_sub.list
similarity index 100%
rename from ObservationSim/Instrument/data/filters/nuv_sub.list
rename to observation_sim/instruments/data/filters/nuv_sub.list
diff --git a/ObservationSim/Instrument/data/filters/r.txt b/observation_sim/instruments/data/filters/r.txt
similarity index 100%
rename from ObservationSim/Instrument/data/filters/r.txt
rename to observation_sim/instruments/data/filters/r.txt
diff --git a/ObservationSim/Instrument/data/filters/r_sub.list b/observation_sim/instruments/data/filters/r_sub.list
similarity index 100%
rename from ObservationSim/Instrument/data/filters/r_sub.list
rename to observation_sim/instruments/data/filters/r_sub.list
diff --git a/ObservationSim/Instrument/data/filters/u.txt b/observation_sim/instruments/data/filters/u.txt
similarity index 100%
rename from ObservationSim/Instrument/data/filters/u.txt
rename to observation_sim/instruments/data/filters/u.txt
diff --git a/ObservationSim/Instrument/data/filters/u_sub.list b/observation_sim/instruments/data/filters/u_sub.list
similarity index 100%
rename from ObservationSim/Instrument/data/filters/u_sub.list
rename to observation_sim/instruments/data/filters/u_sub.list
diff --git a/ObservationSim/Instrument/data/filters/y.txt b/observation_sim/instruments/data/filters/y.txt
similarity index 100%
rename from ObservationSim/Instrument/data/filters/y.txt
rename to observation_sim/instruments/data/filters/y.txt
diff --git a/ObservationSim/Instrument/data/filters/y_sub.list b/observation_sim/instruments/data/filters/y_sub.list
similarity index 100%
rename from ObservationSim/Instrument/data/filters/y_sub.list
rename to observation_sim/instruments/data/filters/y_sub.list
diff --git a/ObservationSim/Instrument/data/filters/z.txt b/observation_sim/instruments/data/filters/z.txt
similarity index 100%
rename from ObservationSim/Instrument/data/filters/z.txt
rename to observation_sim/instruments/data/filters/z.txt
diff --git a/ObservationSim/Instrument/data/filters/z_sub.list b/observation_sim/instruments/data/filters/z_sub.list
similarity index 100%
rename from ObservationSim/Instrument/data/filters/z_sub.list
rename to observation_sim/instruments/data/filters/z_sub.list
diff --git a/ObservationSim/Instrument/data/mirror_ccdnote.txt b/observation_sim/instruments/data/mirror_ccdnote.txt
similarity index 100%
rename from ObservationSim/Instrument/data/mirror_ccdnote.txt
rename to observation_sim/instruments/data/mirror_ccdnote.txt
diff --git a/ObservationSim/Instrument/data/sls_conf/._CSST_GI1.conf b/observation_sim/instruments/data/sls_conf/._CSST_GI1.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/._CSST_GI1.conf
rename to observation_sim/instruments/data/sls_conf/._CSST_GI1.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/._CSST_GV1.conf b/observation_sim/instruments/data/sls_conf/._CSST_GV1.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/._CSST_GV1.conf
rename to observation_sim/instruments/data/sls_conf/._CSST_GV1.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GI1.conf b/observation_sim/instruments/data/sls_conf/CSST_GI1.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GI1.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GI1.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GI2.conf b/observation_sim/instruments/data/sls_conf/CSST_GI2.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GI2.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GI2.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GI3.conf b/observation_sim/instruments/data/sls_conf/CSST_GI3.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GI3.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GI3.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GI4.conf b/observation_sim/instruments/data/sls_conf/CSST_GI4.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GI4.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GI4.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GI5.conf b/observation_sim/instruments/data/sls_conf/CSST_GI5.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GI5.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GI5.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GI6.conf b/observation_sim/instruments/data/sls_conf/CSST_GI6.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GI6.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GI6.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GI7.conf b/observation_sim/instruments/data/sls_conf/CSST_GI7.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GI7.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GI7.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GI8.conf b/observation_sim/instruments/data/sls_conf/CSST_GI8.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GI8.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GI8.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GU1.conf b/observation_sim/instruments/data/sls_conf/CSST_GU1.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GU1.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GU1.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GU2.conf b/observation_sim/instruments/data/sls_conf/CSST_GU2.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GU2.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GU2.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GU3.conf b/observation_sim/instruments/data/sls_conf/CSST_GU3.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GU3.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GU3.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GU4.conf b/observation_sim/instruments/data/sls_conf/CSST_GU4.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GU4.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GU4.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GU5.conf b/observation_sim/instruments/data/sls_conf/CSST_GU5.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GU5.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GU5.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GU6.conf b/observation_sim/instruments/data/sls_conf/CSST_GU6.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GU6.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GU6.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GU7.conf b/observation_sim/instruments/data/sls_conf/CSST_GU7.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GU7.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GU7.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GU8.conf b/observation_sim/instruments/data/sls_conf/CSST_GU8.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GU8.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GU8.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GV1.conf b/observation_sim/instruments/data/sls_conf/CSST_GV1.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GV1.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GV1.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GV2.conf b/observation_sim/instruments/data/sls_conf/CSST_GV2.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GV2.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GV2.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GV3.conf b/observation_sim/instruments/data/sls_conf/CSST_GV3.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GV3.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GV3.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GV4.conf b/observation_sim/instruments/data/sls_conf/CSST_GV4.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GV4.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GV4.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GV5.conf b/observation_sim/instruments/data/sls_conf/CSST_GV5.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GV5.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GV5.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GV6.conf b/observation_sim/instruments/data/sls_conf/CSST_GV6.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GV6.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GV6.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GV7.conf b/observation_sim/instruments/data/sls_conf/CSST_GV7.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GV7.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GV7.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GV8.conf b/observation_sim/instruments/data/sls_conf/CSST_GV8.conf
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/CSST_GV8.conf
rename to observation_sim/instruments/data/sls_conf/CSST_GV8.conf
diff --git a/ObservationSim/Instrument/data/sls_conf/GI.Throughput.-1st.fits b/observation_sim/instruments/data/sls_conf/GI.Throughput.-1st.fits
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/GI.Throughput.-1st.fits
rename to observation_sim/instruments/data/sls_conf/GI.Throughput.-1st.fits
diff --git a/ObservationSim/Instrument/data/sls_conf/GI.Throughput.-2st.fits b/observation_sim/instruments/data/sls_conf/GI.Throughput.-2st.fits
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/GI.Throughput.-2st.fits
rename to observation_sim/instruments/data/sls_conf/GI.Throughput.-2st.fits
diff --git a/ObservationSim/Instrument/data/sls_conf/GI.Throughput.0st.fits b/observation_sim/instruments/data/sls_conf/GI.Throughput.0st.fits
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/GI.Throughput.0st.fits
rename to observation_sim/instruments/data/sls_conf/GI.Throughput.0st.fits
diff --git a/ObservationSim/Instrument/data/sls_conf/GI.Throughput.1st.fits b/observation_sim/instruments/data/sls_conf/GI.Throughput.1st.fits
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/GI.Throughput.1st.fits
rename to observation_sim/instruments/data/sls_conf/GI.Throughput.1st.fits
diff --git a/ObservationSim/Instrument/data/sls_conf/GI.Throughput.2st.fits b/observation_sim/instruments/data/sls_conf/GI.Throughput.2st.fits
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/GI.Throughput.2st.fits
rename to observation_sim/instruments/data/sls_conf/GI.Throughput.2st.fits
diff --git a/ObservationSim/Instrument/data/sls_conf/GU.Throughput.-1st.fits b/observation_sim/instruments/data/sls_conf/GU.Throughput.-1st.fits
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/GU.Throughput.-1st.fits
rename to observation_sim/instruments/data/sls_conf/GU.Throughput.-1st.fits
diff --git a/ObservationSim/Instrument/data/sls_conf/GU.Throughput.-2st.fits b/observation_sim/instruments/data/sls_conf/GU.Throughput.-2st.fits
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/GU.Throughput.-2st.fits
rename to observation_sim/instruments/data/sls_conf/GU.Throughput.-2st.fits
diff --git a/ObservationSim/Instrument/data/sls_conf/GU.Throughput.0st.fits b/observation_sim/instruments/data/sls_conf/GU.Throughput.0st.fits
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/GU.Throughput.0st.fits
rename to observation_sim/instruments/data/sls_conf/GU.Throughput.0st.fits
diff --git a/ObservationSim/Instrument/data/sls_conf/GU.Throughput.1st.fits b/observation_sim/instruments/data/sls_conf/GU.Throughput.1st.fits
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/GU.Throughput.1st.fits
rename to observation_sim/instruments/data/sls_conf/GU.Throughput.1st.fits
diff --git a/ObservationSim/Instrument/data/sls_conf/GU.Throughput.2st.fits b/observation_sim/instruments/data/sls_conf/GU.Throughput.2st.fits
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/GU.Throughput.2st.fits
rename to observation_sim/instruments/data/sls_conf/GU.Throughput.2st.fits
diff --git a/ObservationSim/Instrument/data/sls_conf/GV.Throughput.-1st.fits b/observation_sim/instruments/data/sls_conf/GV.Throughput.-1st.fits
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/GV.Throughput.-1st.fits
rename to observation_sim/instruments/data/sls_conf/GV.Throughput.-1st.fits
diff --git a/ObservationSim/Instrument/data/sls_conf/GV.Throughput.-2st.fits b/observation_sim/instruments/data/sls_conf/GV.Throughput.-2st.fits
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/GV.Throughput.-2st.fits
rename to observation_sim/instruments/data/sls_conf/GV.Throughput.-2st.fits
diff --git a/ObservationSim/Instrument/data/sls_conf/GV.Throughput.0st.fits b/observation_sim/instruments/data/sls_conf/GV.Throughput.0st.fits
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/GV.Throughput.0st.fits
rename to observation_sim/instruments/data/sls_conf/GV.Throughput.0st.fits
diff --git a/ObservationSim/Instrument/data/sls_conf/GV.Throughput.1st.fits b/observation_sim/instruments/data/sls_conf/GV.Throughput.1st.fits
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/GV.Throughput.1st.fits
rename to observation_sim/instruments/data/sls_conf/GV.Throughput.1st.fits
diff --git a/ObservationSim/Instrument/data/sls_conf/GV.Throughput.2st.fits b/observation_sim/instruments/data/sls_conf/GV.Throughput.2st.fits
similarity index 100%
rename from ObservationSim/Instrument/data/sls_conf/GV.Throughput.2st.fits
rename to observation_sim/instruments/data/sls_conf/GV.Throughput.2st.fits
diff --git a/ObservationSim/Instrument/data/throughputs/__init__.py b/observation_sim/instruments/data/sls_conf/__init__.py
similarity index 100%
rename from ObservationSim/Instrument/data/throughputs/__init__.py
rename to observation_sim/instruments/data/sls_conf/__init__.py
diff --git a/ObservationSim/MockObject/data/__init__.py b/observation_sim/instruments/data/throughputs/__init__.py
similarity index 100%
rename from ObservationSim/MockObject/data/__init__.py
rename to observation_sim/instruments/data/throughputs/__init__.py
diff --git a/ObservationSim/Instrument/data/throughputs/fgs_throughput.txt b/observation_sim/instruments/data/throughputs/fgs_throughput.txt
similarity index 100%
rename from ObservationSim/Instrument/data/throughputs/fgs_throughput.txt
rename to observation_sim/instruments/data/throughputs/fgs_throughput.txt
diff --git a/ObservationSim/Instrument/data/throughputs/g_throughput.txt b/observation_sim/instruments/data/throughputs/g_throughput.txt
similarity index 100%
rename from ObservationSim/Instrument/data/throughputs/g_throughput.txt
rename to observation_sim/instruments/data/throughputs/g_throughput.txt
diff --git a/ObservationSim/Instrument/data/throughputs/i_throughput.txt b/observation_sim/instruments/data/throughputs/i_throughput.txt
similarity index 100%
rename from ObservationSim/Instrument/data/throughputs/i_throughput.txt
rename to observation_sim/instruments/data/throughputs/i_throughput.txt
diff --git a/ObservationSim/Instrument/data/throughputs/nuv_throughput.txt b/observation_sim/instruments/data/throughputs/nuv_throughput.txt
similarity index 100%
rename from ObservationSim/Instrument/data/throughputs/nuv_throughput.txt
rename to observation_sim/instruments/data/throughputs/nuv_throughput.txt
diff --git a/ObservationSim/Instrument/data/throughputs/r_throughput.txt b/observation_sim/instruments/data/throughputs/r_throughput.txt
similarity index 100%
rename from ObservationSim/Instrument/data/throughputs/r_throughput.txt
rename to observation_sim/instruments/data/throughputs/r_throughput.txt
diff --git a/ObservationSim/Instrument/data/throughputs/sky_emiss_hubble_50_50_A.dat b/observation_sim/instruments/data/throughputs/sky_emiss_hubble_50_50_A.dat
similarity index 100%
rename from ObservationSim/Instrument/data/throughputs/sky_emiss_hubble_50_50_A.dat
rename to observation_sim/instruments/data/throughputs/sky_emiss_hubble_50_50_A.dat
diff --git a/ObservationSim/Instrument/data/throughputs/u_throughput.txt b/observation_sim/instruments/data/throughputs/u_throughput.txt
similarity index 100%
rename from ObservationSim/Instrument/data/throughputs/u_throughput.txt
rename to observation_sim/instruments/data/throughputs/u_throughput.txt
diff --git a/ObservationSim/Instrument/data/throughputs/y_throughput.txt b/observation_sim/instruments/data/throughputs/y_throughput.txt
similarity index 100%
rename from ObservationSim/Instrument/data/throughputs/y_throughput.txt
rename to observation_sim/instruments/data/throughputs/y_throughput.txt
diff --git a/ObservationSim/Instrument/data/throughputs/z_throughput.txt b/observation_sim/instruments/data/throughputs/z_throughput.txt
similarity index 100%
rename from ObservationSim/Instrument/data/throughputs/z_throughput.txt
rename to observation_sim/instruments/data/throughputs/z_throughput.txt
diff --git a/ObservationSim/Instrument/data/wfc-cr-attachpixel.dat b/observation_sim/instruments/data/wfc-cr-attachpixel.dat
similarity index 100%
rename from ObservationSim/Instrument/data/wfc-cr-attachpixel.dat
rename to observation_sim/instruments/data/wfc-cr-attachpixel.dat
diff --git a/ObservationSim/MockObject/CatalogBase.py b/observation_sim/mock_objects/CatalogBase.py
similarity index 97%
rename from ObservationSim/MockObject/CatalogBase.py
rename to observation_sim/mock_objects/CatalogBase.py
index a0a2d16d18e2bacb81ce5f8c835a51cd4e77bcdf..cd1b669997ed0ac00b27c991885898e283c87714 100644
--- a/ObservationSim/MockObject/CatalogBase.py
+++ b/observation_sim/mock_objects/CatalogBase.py
@@ -5,7 +5,7 @@ import cmath
 
 from astropy.table import Table
 from abc import abstractmethod, ABCMeta
-from ObservationSim.MockObject._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getABMAG
+from observation_sim.mock_objects._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getABMAG
 
 
 class CatalogBase(metaclass=ABCMeta):
diff --git a/ObservationSim/MockObject/FlatLED.py b/observation_sim/mock_objects/FlatLED.py
similarity index 80%
rename from ObservationSim/MockObject/FlatLED.py
rename to observation_sim/mock_objects/FlatLED.py
index 8cb835d2f78921084ec3376e20440969198ccf1f..a99e955c95401f8aafe52841cfe9d10633cb0125 100755
--- a/ObservationSim/MockObject/FlatLED.py
+++ b/observation_sim/mock_objects/FlatLED.py
@@ -1,7 +1,8 @@
 
 
 import galsim
-import os, sys
+import os
+import sys
 import numpy as np
 import time
 import math
@@ -9,12 +10,11 @@ import astropy.constants as cons
 from astropy.io import fits
 from scipy.interpolate import griddata
 from astropy.table import Table
-from ObservationSim.MockObject.SpecDisperser import SpecDisperser
+from observation_sim.mock_objects.SpecDisperser import SpecDisperser
 from scipy import interpolate
 import gc
 
-from ObservationSim.MockObject.MockObject import MockObject
-# from ObservationSim.Straylight import calculateSkyMap_split_g
+from observation_sim.mock_objects.MockObject import MockObject
 
 try:
     import importlib.resources as pkg_resources
@@ -27,13 +27,13 @@ except ImportError:
 LED_name = ['LED1', 'LED2', 'LED3', 'LED4', 'LED5', 'LED6', 'LED7', 'LED8', 'LED9', 'LED10', 'LED11', 'LED12', 'LED13',
             'LED14']
 cwaves_name = {'LED1': '275', 'LED2': '310', 'LED3': '430', 'LED4': '505', 'LED5': '545', 'LED6': '590', 'LED7': '670',
-          'LED8': '760', 'LED9': '940', 'LED10': '940', 'LED11': '1050', 'LED12': '1050',
-          'LED13': '340', 'LED14': '365'}
+               'LED8': '760', 'LED9': '940', 'LED10': '940', 'LED11': '1050', 'LED12': '1050',
+               'LED13': '340', 'LED14': '365'}
 
 cwaves = {'LED1': 2750, 'LED2': 3100, 'LED3': 4300, 'LED4': 5050, 'LED5': 5250, 'LED6': 5900, 'LED7': 6700,
           'LED8': 7600, 'LED9': 8800, 'LED10': 9400, 'LED11': 10500, 'LED12': 15500, 'LED13': 3400, 'LED14': 3650}
 cwaves_fwhm = {'LED1': 110, 'LED2': 120, 'LED3': 200, 'LED4': 300, 'LED5': 300, 'LED6': 130, 'LED7': 210,
-          'LED8': 260, 'LED9': 400, 'LED10': 370, 'LED11': 500, 'LED12': 1400, 'LED13': 90, 'LED14': 100}
+               'LED8': 260, 'LED9': 400, 'LED10': 370, 'LED11': 500, 'LED12': 1400, 'LED13': 90, 'LED14': 100}
 # LED_QE = {'LED1': 0.3, 'LED2': 0.4, 'LED13': 0.5, 'LED14': 0.5, 'LED10': 0.4}
 # e-/ms
 # fluxLED = {'LED1': 0.16478729, 'LED2': 0.084220931, 'LED3': 2.263360617, 'LED4': 2.190623489, 'LED5': 0.703504768,
@@ -43,17 +43,18 @@ cwaves_fwhm = {'LED1': 110, 'LED2': 120, 'LED3': 200, 'LED4': 300, 'LED5': 300,
 
 # e-/ms
 fluxLED = {'LED1': 15, 'LED2': 15, 'LED3': 12.5, 'LED4': 9, 'LED5': 9,
-           'LED6': 9, 'LED7': 9, 'LED8': 9, 'LED9': 9, 'LED10': 12.5, 'LED11': 15, 'LED12':15, 'LED13': 12.5,
+           'LED6': 9, 'LED7': 9, 'LED8': 9, 'LED9': 9, 'LED10': 12.5, 'LED11': 15, 'LED12': 15, 'LED13': 12.5,
            'LED14': 12.5}
 # fluxLEDL = {'LED1': 10, 'LED2': 10, 'LED3': 10, 'LED4': 10, 'LED5': 10,
 #            'LED6': 10, 'LED7': 10, 'LED8': 10, 'LED9': 10, 'LED10': 10, 'LED11': 10, 'LED12':10, 'LED13': 10,
 #            'LED14': 10}
 
-mirro_eff = {'GU':0.61, 'GV':0.8, 'GI':0.8}
+mirro_eff = {'GU': 0.61, 'GV': 0.8, 'GI': 0.8}
 # mirro_eff = {'GU':1, 'GV':1, 'GI':1}
 
+
 class FlatLED(MockObject):
-    def __init__(self, chip,filt, flatDir = None, logger=None):
+    def __init__(self, chip, filt, flatDir=None, logger=None):
         # self.led_type_list = led_type_list
         self.filt = filt
         self.chip = chip
@@ -62,18 +63,19 @@ class FlatLED(MockObject):
             self.flatDir = flatDir
         else:
             try:
-                with pkg_resources.files('ObservationSim.MockObject.data.led').joinpath("") as ledDir:
+                with pkg_resources.files('observation_sim.mock_objects.data.led').joinpath("") as ledDir:
                     self.flatDir = ledDir.as_posix()
             except AttributeError:
-                with pkg_resources.path('ObservationSim.MockObject.data.led', "") as ledDir:
+                with pkg_resources.path('observation_sim.mock_objects.data.led', "") as ledDir:
                     self.flatDir = ledDir.as_posix()
 
     ###
-    ### return LED flat, e/s
+    # return LED flat, e/s
     ###
     def getLEDImage(self, led_type='LED1'):
         # cwave = cwaves[led_type]
-        flat = fits.open(os.path.join(self.flatDir, 'model_' + cwaves_name[led_type] + 'nm.fits'))
+        flat = fits.open(os.path.join(self.flatDir, 'model_' +
+                         cwaves_name[led_type] + 'nm.fits'))
         xlen = flat[0].header['NAXIS1']
         ylen = 601
         x = np.linspace(0, self.chip.npix_x * 6, xlen)
@@ -95,21 +97,23 @@ class FlatLED(MockObject):
         i = self.chip.rowID - 1
         j = self.chip.colID - 1
         U = griddata(X_, Z_, (
-            M[self.chip.npix_y * i:self.chip.npix_y * (i + 1), self.chip.npix_x * j:self.chip.npix_x * (j + 1)],
+            M[self.chip.npix_y * i:self.chip.npix_y *
+                (i + 1), self.chip.npix_x * j:self.chip.npix_x * (j + 1)],
             N[self.chip.npix_y * i:self.chip.npix_y * (i + 1), self.chip.npix_x * j:self.chip.npix_x * (j + 1)]),
-                     method='linear')
+            method='linear')
         U = U/np.mean(U)
         flatImage = U*fluxLED[led_type]*1000
         gc.collect()
         return flatImage
 
-
         ###
-    ### return LED flat, e/s
+    # return LED flat, e/s
     ###
+
     def getLEDImage1(self, led_type='LED1'):
         # cwave = cwaves[led_type]
-        flat = fits.open(os.path.join(self.flatDir, 'model_' + cwaves_name[led_type] + 'nm.fits'))
+        flat = fits.open(os.path.join(self.flatDir, 'model_' +
+                         cwaves_name[led_type] + 'nm.fits'))
         xlen = flat[0].header['NAXIS1']
         ylen = 601
 
@@ -120,22 +124,23 @@ class FlatLED(MockObject):
         y = np.linspace(0, self.chip.npix_y, int(ylen/5.))
         xx, yy = np.meshgrid(x, y)
 
-        a1 = flat[0].data[int(ylen*i/5.):int(ylen*i/5.)+int(ylen/5.), int(xlen*j/6.):int(xlen*j/6.)+int(xlen/6.)]
+        a1 = flat[0].data[int(ylen*i/5.):int(ylen*i/5.)+int(ylen/5.),
+                          int(xlen*j/6.):int(xlen*j/6.)+int(xlen/6.)]
         # z = np.sin((xx+yy+xx**2+yy**2))
         # fInterp = interp2d(xx, yy, z, kind='linear')
 
         X_ = np.hstack((xx.flatten()[:, None], yy.flatten()[:, None]))
         Z_ = a1.flatten()
 
-        n_x = np.arange(0, self.chip.npix_x , 1)
+        n_x = np.arange(0, self.chip.npix_x, 1)
         n_y = np.arange(0, self.chip.npix_y, 1)
 
         M, N = np.meshgrid(n_x, n_y)
 
         U = griddata(X_, Z_, (
             M[0:self.chip.npix_y, 0:self.chip.npix_x],
-            N[0:self.chip.npix_y, 0:self.chip.npix_x ]),
-                     method='linear')
+            N[0:self.chip.npix_y, 0:self.chip.npix_x]),
+            method='linear')
         U = U/np.mean(U)
         flatImage = U*fluxLED[led_type]*1000
         gc.collect()
@@ -143,12 +148,13 @@ class FlatLED(MockObject):
 
     def drawObj_LEDFlat_img(self, led_type_list=['LED1'], exp_t_list=[0.1]):
         if len(led_type_list) > len(exp_t_list):
-            return np.ones([self.chip.npix_y,self.chip.npix_x])
+            return np.ones([self.chip.npix_y, self.chip.npix_x])
 
-        ledFlat = np.zeros([self.chip.npix_y,self.chip.npix_x])
+        ledFlat = np.zeros([self.chip.npix_y, self.chip.npix_x])
 
         ledStat = '00000000000000'
-        ledTimes = [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0]
+        ledTimes = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
 
         nledStat = '2'
         for i in np.arange(len(led_type_list)):
@@ -160,8 +166,10 @@ class FlatLED(MockObject):
             led_wave = cwaves[led_type]
             led_fwhm = cwaves_fwhm[led_type]
             led_spec = self.gaussian1d_profile_led(led_wave, led_fwhm)
-            speci = interpolate.interp1d(led_spec['WAVELENGTH'], led_spec['FLUX'])
-            w_list = np.arange(self.filt.blue_limit, self.filt.red_limit, 0.5) #A
+            speci = interpolate.interp1d(
+                led_spec['WAVELENGTH'], led_spec['FLUX'])
+            w_list = np.arange(self.filt.blue_limit,
+                               self.filt.red_limit, 0.5)  # A
 
             f_spec = speci(w_list)
             ccd_bp = self.chip._getChipEffCurve(self.chip.filter_type)
@@ -174,19 +182,21 @@ class FlatLED(MockObject):
             # print("DEBUG1:---------------",np.mean(unitFlatImg))
             ledFlat = ledFlat+unitFlatImg*exp_t
 
-            ledStat = ledStat[0:int(led_type[3:])-1]+nledStat+ledStat[int(led_type[3:]):]
+            ledStat = ledStat[0:int(led_type[3:])-1] + \
+                nledStat+ledStat[int(led_type[3:]):]
             ledTimes[int(led_type[3:])-1] = exp_t * 1000
             gc.collect()
         return ledFlat, ledStat, ledTimes
 
     def drawObj_LEDFlat_slitless(self, led_type_list=['LED1'], exp_t_list=[0.1]):
         if len(led_type_list) != len(exp_t_list):
-            return np.ones([self.chip.npix_y,self.chip.npix_x])
+            return np.ones([self.chip.npix_y, self.chip.npix_x])
 
-        ledFlat = np.zeros([self.chip.npix_y,self.chip.npix_x])
+        ledFlat = np.zeros([self.chip.npix_y, self.chip.npix_x])
 
         ledStat = '00000000000000'
-        ledTimes = [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0]
+        ledTimes = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
 
         nledStat = '2'
 
@@ -213,7 +223,8 @@ class FlatLED(MockObject):
                 flat_cube=self.chip.flat_cube, led_spec=led_spec)
 
             ledFlat = ledFlat + ledspec_map
-            ledStat = ledStat[0:int(led_type[3:])-1]+nledStat+ledStat[int(led_type[3:]):]
+            ledStat = ledStat[0:int(led_type[3:])-1] + \
+                nledStat+ledStat[int(led_type[3:]):]
             ledTimes[int(led_type[3:])-1] = exp_t * 1000
         return ledFlat, ledStat, ledTimes
 
@@ -223,7 +234,6 @@ class FlatLED(MockObject):
         elif self.chip.survey_type == "spectroscopic":
             return self.drawObj_LEDFlat_slitless(led_type_list=led_type_list, exp_t_list=exp_t_list)
 
-
     def gaussian1d_profile_led(self, xc=5050, fwhm=300):
         sigma = fwhm/2.355
         x_radii = int(5*sigma + 1)
@@ -232,9 +242,10 @@ class FlatLED(MockObject):
         xlist_[1:-1] = xlist
         xlist_[0] = 2000
         xlist_[-1] = 18000
-        ids1 = xlist>xc-fwhm
-        ids2 = xlist[ids1]<xc+fwhm
-        data = np.exp((-(xlist-xc)*(xlist-xc))/(2*sigma*sigma))/(np.sqrt(2*math.pi)*sigma)
+        ids1 = xlist > xc-fwhm
+        ids2 = xlist[ids1] < xc+fwhm
+        data = np.exp((-(xlist-xc)*(xlist-xc))/(2*sigma*sigma)) / \
+            (np.sqrt(2*math.pi)*sigma)
         scale = 1/np.trapz(data[ids1][ids2], xlist[ids1][ids2])
         data_ = np.zeros(len(xlist) + 2)
         data_[1:-1] = data*scale
@@ -242,8 +253,8 @@ class FlatLED(MockObject):
         return Table(np.array([xlist_.astype(np.float32), data_.astype(np.float32)]).T, names=('WAVELENGTH', 'FLUX'))
 
     def calculateLEDSpec(self, skyMap=None, blueLimit=4200, redLimit=6500,
-                                conf=[''], pixelSize=0.074, isAlongY=0,
-                                split_pos=3685, flat_cube=None, led_spec=None):
+                         conf=[''], pixelSize=0.074, isAlongY=0,
+                         split_pos=3685, flat_cube=None, led_spec=None):
 
         conf1 = conf[0]
         conf2 = conf[0]
@@ -297,7 +308,8 @@ class FlatLED(MockObject):
                     sub_x_s = k2
                     sub_x_e = sub_x_end_arr[j]
 
-                    skyImg_sub = galsim.Image(skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e])
+                    skyImg_sub = galsim.Image(
+                        skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e])
                     origin_sub = [sub_y_s, sub_x_s]
                     sub_x_center = (sub_x_s + sub_x_e) / 2.
 
@@ -321,11 +333,8 @@ class FlatLED(MockObject):
                             continue
                         fImg[bounds] = fImg[bounds] + ssImg[bounds]
 
-
-
         else:
 
-
             # sdp.compute_spec_orders()
             y_len = skyMap.shape[0]
             x_len = skyMap.shape[1]
@@ -352,7 +361,8 @@ class FlatLED(MockObject):
                     sub_x_e = sub_x_end_arr[j]
                     # print(i,j,sub_y_s, sub_y_e,sub_x_s,sub_x_e)
                     T1 = time.time()
-                    skyImg_sub = galsim.Image(skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e])
+                    skyImg_sub = galsim.Image(
+                        skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e])
                     origin_sub = [sub_y_s, sub_x_s]
                     sub_x_center = (sub_x_s + sub_x_e) / 2.
 
@@ -398,7 +408,8 @@ class FlatLED(MockObject):
 
                     T1 = time.time()
 
-                    skyImg_sub = galsim.Image(skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e])
+                    skyImg_sub = galsim.Image(
+                        skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e])
                     origin_sub = [sub_y_s, sub_x_s]
                     sub_x_center = (sub_x_s + sub_x_e) / 2.
 
@@ -426,14 +437,11 @@ class FlatLED(MockObject):
                     print('time: %s ms' % ((T2 - T1) * 1000))
 
         if isAlongY == 1:
-            fimg, tmx, tmy = SpecDisperser.rotate90(array_orig=fImg.array, xc=0, yc=0, isClockwise=0)
+            fimg, tmx, tmy = SpecDisperser.rotate90(
+                array_orig=fImg.array, xc=0, yc=0, isClockwise=0)
         else:
             fimg = fImg.array
 
         # fimg = fimg * pixelSize * pixelSize
 
         return fimg
-
-
-
-
diff --git a/ObservationSim/MockObject/Galaxy.py b/observation_sim/mock_objects/Galaxy.py
similarity index 96%
rename from ObservationSim/MockObject/Galaxy.py
rename to observation_sim/mock_objects/Galaxy.py
index 27d56380d98fb0b0872012396a7e1eaa1e94a2c2..c220621e35b1c6121edc2c22b83bb9410e02715e 100755
--- a/ObservationSim/MockObject/Galaxy.py
+++ b/observation_sim/mock_objects/Galaxy.py
@@ -2,9 +2,9 @@ import numpy as np
 import galsim
 from astropy.table import Table
 
-from ObservationSim.MockObject._util import eObs, integrate_sed_bandpass, getNormFactorForSpecWithABMAG
-from ObservationSim.MockObject.SpecDisperser import SpecDisperser
-from ObservationSim.MockObject.MockObject import MockObject
+from observation_sim.mock_objects._util import eObs, integrate_sed_bandpass, getNormFactorForSpecWithABMAG
+from observation_sim.mock_objects.SpecDisperser import SpecDisperser
+from observation_sim.mock_objects.MockObject import MockObject
 
 # import tracemalloc
 
diff --git a/ObservationSim/MockObject/MockObject.py b/observation_sim/mock_objects/MockObject.py
similarity index 81%
rename from ObservationSim/MockObject/MockObject.py
rename to observation_sim/mock_objects/MockObject.py
index 847e5b646ef50b088a9ae6674f477747800a0bbf..12e36124de22019c6382b3381fefdb8394eecc65 100755
--- a/ObservationSim/MockObject/MockObject.py
+++ b/observation_sim/mock_objects/MockObject.py
@@ -6,10 +6,10 @@ from astropy import wcs
 from astropy.table import Table
 import astropy.io.fits as fitsio
 
-from ObservationSim.MockObject._util import magToFlux, VC_A, convolveGaussXorders, convolveImg
-from ObservationSim.MockObject._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getObservedSED, \
+from observation_sim.mock_objects._util import magToFlux, VC_A, convolveGaussXorders, convolveImg
+from observation_sim.mock_objects._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getObservedSED, \
     getABMAG
-from ObservationSim.MockObject.SpecDisperser import SpecDisperser
+from observation_sim.mock_objects.SpecDisperser import SpecDisperser
 
 
 class MockObject(object):
@@ -17,21 +17,21 @@ class MockObject(object):
         self.param = param
         for key in self.param:
             setattr(self, key, self.param[key])
-        
+
         if self.param["star"] == 0:
             self.type = "galaxy"
         elif self.param["star"] == 1:
             self.type = "star"
         elif self.param["star"] == 2:
             self.type = "quasar"
-        ###mock_stamp_START
+        # mock_stamp_START
         elif self.param["star"] == 3:
             self.type = "stamp"
-        ###mock_stamp_END
-        ###for calibration
+        # mock_stamp_END
+        # for calibration
         elif self.param["star"] == 4:
             self.type = "calib"
-        ###END
+        # END
 
         self.sed = None
         self.fd_shear = None
@@ -72,19 +72,22 @@ class MockObject(object):
             if verbose:
                 print("\n")
                 print("Before field distortion:\n")
-                print("x = %.2f, y = %.2f\n" % (self.posImg.x, self.posImg.y), flush=True)
-            self.posImg, self.fd_shear = fdmodel.get_distorted(chip=chip, pos_img=self.posImg)
+                print("x = %.2f, y = %.2f\n" %
+                      (self.posImg.x, self.posImg.y), flush=True)
+            self.posImg, self.fd_shear = fdmodel.get_distorted(
+                chip=chip, pos_img=self.posImg)
             if verbose:
                 print("After field distortion:\n")
-                print("x = %.2f, y = %.2f\n" % (self.posImg.x, self.posImg.y), flush=True)
-        
+                print("x = %.2f, y = %.2f\n" %
+                      (self.posImg.x, self.posImg.y), flush=True)
+
         x, y = self.posImg.x + 0.5, self.posImg.y + 0.5
         self.x_nominal = int(np.floor(x + 0.5))
         self.y_nominal = int(np.floor(y + 0.5))
         dx = x - self.x_nominal
         dy = y - self.y_nominal
         self.offset = galsim.PositionD(dx, dy)
-        
+
         # Deal with chip rotation
         if chip_wcs is not None:
             self.chip_wcs = chip_wcs
@@ -108,7 +111,8 @@ class MockObject(object):
         # print("nphotons_tot = ", nphotons_tot)
 
         try:
-            full = integrate_sed_bandpass(sed=self.sed, bandpass=filt.bandpass_full)
+            full = integrate_sed_bandpass(
+                sed=self.sed, bandpass=filt.bandpass_full)
         except Exception as e:
             print(e)
             if self.logger:
@@ -121,7 +125,7 @@ class MockObject(object):
         else:
             folding_threshold = 5.e-3
         gsp = galsim.GSParams(folding_threshold=folding_threshold)
-        
+
         # Get real image position of object (deal with chip rotation w.r.t its center)
         self.real_pos = self.getRealPos(chip.img, global_x=self.posImg.x, global_y=self.posImg.y,
                                         img_real_wcs=self.chip_wcs)
@@ -153,7 +157,7 @@ class MockObject(object):
 
             # nphotons_sum += nphotons
             # print("nphotons_sub-band_%d = %.2f"%(i, nphotons))
-            
+
             # Get PSF model
             psf, pos_shear = psf_model.get_PSF(chip=chip, pos_img=pos_img, bandpass=bandpass,
                                                folding_threshold=folding_threshold)
@@ -166,21 +170,22 @@ class MockObject(object):
             if np.sum(np.isnan(stamp.array)) > 0:
                 continue
             stamp.setCenter(x_nominal, y_nominal)
-            bounds = stamp.bounds & galsim.BoundsI(0, chip.npix_x - 1, 0, chip.npix_y - 1)
+            bounds = stamp.bounds & galsim.BoundsI(
+                0, chip.npix_x - 1, 0, chip.npix_y - 1)
             if bounds.area() > 0:
                 chip.img.setOrigin(0, 0)
                 chip.img[bounds] += stamp[bounds]
                 is_updated = 1
                 chip.img.setOrigin(chip.bound.xmin, chip.bound.ymin)
                 del stamp
-        
+
         if is_updated == 0:
             # Return code 0: object has missed this detector
-            print("obj %s missed"%(self.id))
+            print("obj %s missed" % (self.id))
             if self.logger:
-                self.logger.info("obj %s missed"%(self.id))
+                self.logger.info("obj %s missed" % (self.id))
             return 0, pos_shear
-        return 1, pos_shear # Return code 1: draw sucesss
+        return 1, pos_shear  # Return code 1: draw sucesss
 
     def addSLStoChipImage(self, sdp=None, chip=None, xOrderSigPlus=None, local_wcs=None):
         spec_orders = sdp.compute_spec_orders()
@@ -193,7 +198,8 @@ class MockObject(object):
             nan_ids = np.isnan(img_s)
             if img_s[nan_ids].shape[0] > 0:
                 # img_s[nan_ids] = 0
-                print("DEBUG: before convolveGaussXorders specImg nan num is", img_s[nan_ids].shape[0])
+                print("DEBUG: before convolveGaussXorders specImg nan num is",
+                      img_s[nan_ids].shape[0])
             #########################################################
             img_s, orig_off = convolveGaussXorders(img_s, xOrderSigPlus[k])
             origin_order_x = v[1] - orig_off
@@ -219,7 +225,8 @@ class MockObject(object):
             stamp.wcs = local_wcs
             stamp.setOrigin(origin_order_x, origin_order_y)
 
-            bounds = stamp.bounds & galsim.BoundsI(0, chip.npix_x - 1, 0, chip.npix_y - 1)
+            bounds = stamp.bounds & galsim.BoundsI(
+                0, chip.npix_x - 1, 0, chip.npix_y - 1)
             if bounds.area() == 0:
                 continue
             chip.img.setOrigin(0, 0)
@@ -230,17 +237,18 @@ class MockObject(object):
             del stamp
         del spec_orders
 
-    def addSLStoChipImageWithPSF(self, sdp=None, chip=None, pos_img_local = [1,1], psf_model=None, bandNo = 1, grating_split_pos=3685, local_wcs=None, pos_img=None):
+    def addSLStoChipImageWithPSF(self, sdp=None, chip=None, pos_img_local=[1, 1], psf_model=None, bandNo=1, grating_split_pos=3685, local_wcs=None, pos_img=None):
         spec_orders = sdp.compute_spec_orders()
         for k, v in spec_orders.items():
             img_s = v[0]
             # print(bandNo,k)
             try:
-                psf, pos_shear = psf_model.get_PSF(chip, pos_img_local = pos_img_local, bandNo = bandNo, galsimGSObject=True, g_order = k, grating_split_pos=grating_split_pos)
+                psf, pos_shear = psf_model.get_PSF(
+                    chip, pos_img_local=pos_img_local, bandNo=bandNo, galsimGSObject=True, g_order=k, grating_split_pos=grating_split_pos)
             except:
                 psf, pos_shear = psf_model.get_PSF(chip=chip, pos_img=pos_img)
 
-            psf_img = psf.drawImage(nx=100, ny=100, wcs = local_wcs)
+            psf_img = psf.drawImage(nx=100, ny=100, wcs=local_wcs)
 
             psf_img_m = psf_img.array
 
@@ -263,7 +271,6 @@ class MockObject(object):
             origin_order_x = v[1] - orig_off[0]
             origin_order_y = v[2] - orig_off[1]
 
-
             specImg = galsim.ImageF(img_s)
             # photons = galsim.PhotonArray.makeFromImage(specImg)
             # photons.x += origin_order_x
@@ -278,7 +285,8 @@ class MockObject(object):
             specImg.wcs = local_wcs
             specImg.setOrigin(origin_order_x, origin_order_y)
 
-            bounds = specImg.bounds & galsim.BoundsI(0, chip.npix_x - 1, 0, chip.npix_y - 1)
+            bounds = specImg.bounds & galsim.BoundsI(
+                0, chip.npix_x - 1, 0, chip.npix_y - 1)
             if bounds.area() == 0:
                 continue
             chip.img.setOrigin(0, 0)
@@ -297,7 +305,8 @@ class MockObject(object):
             norm_thr_rang_ids = normFilter['SENSITIVITY'] > 0.001
             sedNormFactor = getNormFactorForSpecWithABMAG(ABMag=self.param['mag_use_normal'], spectrum=self.sed,
                                                           norm_thr=normFilter,
-                                                          sWave=np.floor(normFilter[norm_thr_rang_ids][0][0]),
+                                                          sWave=np.floor(
+                                                              normFilter[norm_thr_rang_ids][0][0]),
                                                           eWave=np.ceil(normFilter[norm_thr_rang_ids][-1][0]))
             if sedNormFactor == 0:
                 return 2, None
@@ -331,9 +340,9 @@ class MockObject(object):
                          'D': 5.5684364343742825, 'E': 16.260021029735388}
         grating_split_pos_chip = 0 + grating_split_pos
 
-        branges = np.zeros([len(bandpass_list),2])
+        branges = np.zeros([len(bandpass_list), 2])
 
-        if hasattr(psf_model,'bandranges'):
+        if hasattr(psf_model, 'bandranges'):
             if psf_model.bandranges is None:
                 return 2, None
             if len(psf_model.bandranges) != len(bandpass_list):
@@ -354,22 +363,24 @@ class MockObject(object):
             star = star.withFlux(tel.pupil_area * exptime)
             psf_tmp = galsim.Gaussian(sigma=0.002)
             star = galsim.Convolve(psf_tmp, star)
-            
-            starImg = star.drawImage(nx=60, ny=60, wcs=chip_wcs_local, offset=offset)
+
+            starImg = star.drawImage(
+                nx=60, ny=60, wcs=chip_wcs_local, offset=offset)
 
             origin_star = [y_nominal - (starImg.center.y - starImg.ymin),
                            x_nominal - (starImg.center.x - starImg.xmin)]
-            starImg.setOrigin(0,0)
+            starImg.setOrigin(0, 0)
             gal_origin = [origin_star[0], origin_star[1]]
-            gal_end = [origin_star[0] + starImg.array.shape[0] - 1, origin_star[1] + starImg.array.shape[1] - 1]
+            gal_end = [origin_star[0] + starImg.array.shape[0] -
+                       1, origin_star[1] + starImg.array.shape[1] - 1]
             if gal_origin[1] < grating_split_pos_chip < gal_end[1]:
                 subSlitPos = int(grating_split_pos_chip - gal_origin[1] + 1)
-                ## part img disperse
+                # part img disperse
 
                 subImg_p1 = starImg.array[:, 0:subSlitPos]
                 star_p1 = galsim.Image(subImg_p1)
                 origin_p1 = origin_star
-                star_p1.setOrigin(0,0)
+                star_p1.setOrigin(0, 0)
                 xcenter_p1 = min(x_nominal, grating_split_pos_chip - 1) - 0
                 ycenter_p1 = y_nominal - 0
 
@@ -382,11 +393,12 @@ class MockObject(object):
                                        flat_cube=flat_cube)
 
                 # self.addSLStoChipImage(sdp=sdp_p1, chip=chip, xOrderSigPlus=xOrderSigPlus, local_wcs=chip_wcs_local)
-                pos_shear=self.addSLStoChipImageWithPSF(sdp=sdp_p1, chip=chip, pos_img_local = [xcenter_p1,ycenter_p1],
-                                              psf_model=psf_model, bandNo = i+1, grating_split_pos=grating_split_pos,
-                                              local_wcs=chip_wcs_local, pos_img = pos_img)
+                pos_shear = self.addSLStoChipImageWithPSF(sdp=sdp_p1, chip=chip, pos_img_local=[xcenter_p1, ycenter_p1],
+                                                          psf_model=psf_model, bandNo=i+1, grating_split_pos=grating_split_pos,
+                                                          local_wcs=chip_wcs_local, pos_img=pos_img)
 
-                subImg_p2 = starImg.array[:, subSlitPos + 1:starImg.array.shape[1]]
+                subImg_p2 = starImg.array[:,
+                                          subSlitPos + 1:starImg.array.shape[1]]
                 star_p2 = galsim.Image(subImg_p2)
                 star_p2.setOrigin(0, 0)
                 origin_p2 = [origin_star[0], grating_split_pos_chip]
@@ -402,9 +414,9 @@ class MockObject(object):
                                        flat_cube=flat_cube)
 
                 # self.addSLStoChipImage(sdp=sdp_p2, chip=chip, xOrderSigPlus=xOrderSigPlus, local_wcs=chip_wcs_local)
-                pos_shear=self.addSLStoChipImageWithPSF(sdp=sdp_p2, chip=chip, pos_img_local=[xcenter_p2, ycenter_p2],
-                                              psf_model=psf_model, bandNo=i + 1, grating_split_pos=grating_split_pos,
-                                              local_wcs=chip_wcs_local, pos_img = pos_img)
+                pos_shear = self.addSLStoChipImageWithPSF(sdp=sdp_p2, chip=chip, pos_img_local=[xcenter_p2, ycenter_p2],
+                                                          psf_model=psf_model, bandNo=i + 1, grating_split_pos=grating_split_pos,
+                                                          local_wcs=chip_wcs_local, pos_img=pos_img)
 
                 del sdp_p1
                 del sdp_p2
@@ -417,9 +429,9 @@ class MockObject(object):
                                     isAlongY=0,
                                     flat_cube=flat_cube)
                 # self.addSLStoChipImage(sdp=sdp, chip=chip, xOrderSigPlus=xOrderSigPlus, local_wcs=chip_wcs_local)
-                pos_shear=self.addSLStoChipImageWithPSF(sdp=sdp, chip=chip, pos_img_local=[x_nominal, y_nominal],
-                                              psf_model=psf_model, bandNo=i + 1, grating_split_pos=grating_split_pos,
-                                              local_wcs=chip_wcs_local, pos_img = pos_img)
+                pos_shear = self.addSLStoChipImageWithPSF(sdp=sdp, chip=chip, pos_img_local=[x_nominal, y_nominal],
+                                                          psf_model=psf_model, bandNo=i + 1, grating_split_pos=grating_split_pos,
+                                                          local_wcs=chip_wcs_local, pos_img=pos_img)
                 del sdp
             elif grating_split_pos_chip >= gal_end[1]:
                 sdp = SpecDisperser(orig_img=starImg, xcenter=x_nominal - 0,
@@ -430,9 +442,9 @@ class MockObject(object):
                                     isAlongY=0,
                                     flat_cube=flat_cube)
                 # self.addSLStoChipImage(sdp=sdp, chip=chip, xOrderSigPlus=xOrderSigPlus, local_wcs=chip_wcs_local)
-                pos_shear=self.addSLStoChipImageWithPSF(sdp=sdp, chip=chip, pos_img_local=[x_nominal, y_nominal],
-                                              psf_model=psf_model, bandNo=i + 1, grating_split_pos=grating_split_pos,
-                                              local_wcs=chip_wcs_local, pos_img = pos_img)
+                pos_shear = self.addSLStoChipImageWithPSF(sdp=sdp, chip=chip, pos_img_local=[x_nominal, y_nominal],
+                                                          psf_model=psf_model, bandNo=i + 1, grating_split_pos=grating_split_pos,
+                                                          local_wcs=chip_wcs_local, pos_img=pos_img)
                 del sdp
             # del psf
         return 1, pos_shear
@@ -447,16 +459,15 @@ class MockObject(object):
         snr_obj = img_flux / sig_obj
         return snr_obj
 
-
-
     def drawObj_PSF(self, tel, pos_img, psf_model, bandpass_list, filt, chip, nphotons_tot=None, g1=0, g2=0,
-                          exptime=150., fd_shear=None, chip_output=None):
+                    exptime=150., fd_shear=None, chip_output=None):
         if nphotons_tot == None:
             nphotons_tot = self.getElectronFluxFilt(filt, tel, exptime)
         # print("nphotons_tot = ", nphotons_tot)
 
         try:
-            full = integrate_sed_bandpass(sed=self.sed, bandpass=filt.bandpass_full)
+            full = integrate_sed_bandpass(
+                sed=self.sed, bandpass=filt.bandpass_full)
         except Exception as e:
             print(e)
             if self.logger:
@@ -504,21 +515,21 @@ class MockObject(object):
                                                folding_threshold=folding_threshold)
             star_temp = psf.withFlux(nphotons)
 
-            if i==0:
+            if i == 0:
                 star = star_temp
             else:
                 star = star+star_temp
 
         pixelScale = 0.074
         stamp = star.drawImage(wcs=chip_wcs_local, offset=offset)
-        #stamp = star.drawImage(nx=256, ny=256, scale=pixelScale)
+        # stamp = star.drawImage(nx=256, ny=256, scale=pixelScale)
         if np.sum(np.isnan(stamp.array)) > 0:
             return None
 
-
         fn = chip_output.subdir + "/psfIDW"
         os.makedirs(fn, exist_ok=True)
-        fn = fn + "/ccd_{:}".format(chip.chipID)+"_psf_"+str(self.param['id'])+".fits"
+        fn = fn + "/ccd_{:}".format(chip.chipID) + \
+            "_psf_"+str(self.param['id'])+".fits"
         if fn != None:
             if os.path.exists(fn):
                 os.remove(fn)
diff --git a/ObservationSim/MockObject/Quasar.py b/observation_sim/mock_objects/Quasar.py
similarity index 94%
rename from ObservationSim/MockObject/Quasar.py
rename to observation_sim/mock_objects/Quasar.py
index 1cfd99d1402cea6c9a8798644a78ad96abc958de..b27cb8ce97a6dff472cc08ab9752dc22f05424e4 100755
--- a/ObservationSim/MockObject/Quasar.py
+++ b/observation_sim/mock_objects/Quasar.py
@@ -6,8 +6,8 @@ import astropy.constants as cons
 from astropy.table import Table
 from scipy import interpolate
 
-from ObservationSim.MockObject.MockObject import MockObject
-from ObservationSim.MockObject._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getObservedSED, getABMAG
+from observation_sim.mock_objects.MockObject import MockObject
+from observation_sim.mock_objects._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getObservedSED, getABMAG
 
 
 class Quasar(MockObject):
diff --git a/ObservationSim/MockObject/SpecDisperser/SpecDisperser.py b/observation_sim/mock_objects/SpecDisperser/SpecDisperser.py
similarity index 87%
rename from ObservationSim/MockObject/SpecDisperser/SpecDisperser.py
rename to observation_sim/mock_objects/SpecDisperser/SpecDisperser.py
index d4126f0c457dff809a06912c5c313c3dfda7adf8..6a1e3ef05c70fa418db91149eb1e60bf9dc8b81a 100644
--- a/ObservationSim/MockObject/SpecDisperser/SpecDisperser.py
+++ b/observation_sim/mock_objects/SpecDisperser/SpecDisperser.py
@@ -97,7 +97,6 @@ class SpecDisperser(object):
         self.grating_conf_file = conf
         self.ignoreBeam = ignoreBeam
 
-
     def compute_spec_orders(self):
 
         all_orders = OrderedDict()
@@ -121,16 +120,18 @@ class SpecDisperser(object):
         ytrace_beam, lam_beam = self.grating_conf.get_beam_trace(x=self.xcenter, y=self.ycenter, dx=(dx + xoff),
                                                                  beam=beam)
 
-        ### Account for pixel centering of the trace
+        # Account for pixel centering of the trace
         yfrac_beam = ytrace_beam - floor(ytrace_beam+0.5)
 
         ysens = lam_beam * 0
         lam_index = argsort(lam_beam)
         conf_sens = self.grating_conf.sens[beam]
 
-        lam_intep = np.linspace(self.band_start, self.band_end, int((self.band_end - self.band_start) / 0.1))
+        lam_intep = np.linspace(self.band_start, self.band_end, int(
+            (self.band_end - self.band_start) / 0.1))
 
-        thri = interpolate.interp1d(conf_sens['WAVELENGTH'], conf_sens['SENSITIVITY'])
+        thri = interpolate.interp1d(
+            conf_sens['WAVELENGTH'], conf_sens['SENSITIVITY'])
         spci = interpolate.interp1d(self.spec['WAVELENGTH'], self.spec['FLUX'])
 
         beam_thr = thri(lam_intep)
@@ -138,7 +139,7 @@ class SpecDisperser(object):
 
         bean_thr_spec = beam_thr * spec_sample
 
-        ###generate sensitivity file for aXe
+        # generate sensitivity file for aXe
         # ysensitivity = lam_beam * 0
         #
         # ysensitivity[lam_index] = interp.interp_conserve_c(lam_beam[lam_index], lam_intep,
@@ -155,7 +156,8 @@ class SpecDisperser(object):
         sensitivity_beam = ysens
 
         len_spec_x = len(dx)
-        len_spec_y = int(abs(ceil(ytrace_beam[-1]) - floor(ytrace_beam[0])) + 1)
+        len_spec_y = int(
+            abs(ceil(ytrace_beam[-1]) - floor(ytrace_beam[0])) + 1)
 
         beam_sh = (self.img_sh[0] + len_spec_y, self.img_sh[1] + len_spec_x)
         modelf = zeros(product(beam_sh), dtype=float)
@@ -169,7 +171,7 @@ class SpecDisperser(object):
 
         dypix = cast[int](np.floor(ytrace_beam - dyc[0] + x0[0] + 0.5))
 
-        frac_ids =  yfrac_beam<0
+        frac_ids = yfrac_beam < 0
 
         dypix[frac_ids] = dypix[frac_ids] - 1
         yfrac_beam[frac_ids] = 1+yfrac_beam[frac_ids]
@@ -199,7 +201,8 @@ class SpecDisperser(object):
         else:
             beam_flat = zeros([len(modelf), len(self.flat_cube)])
 
-            sub_flat_cube = zeros([len(self.flat_cube),beam_sh[0], beam_sh[1]])
+            sub_flat_cube = zeros(
+                [len(self.flat_cube), beam_sh[0], beam_sh[1]])
             sub_flat_cube[0] = sub_flat_cube[0] + 1.
 
             overlap_flag = 1
@@ -210,23 +213,28 @@ class SpecDisperser(object):
             sub_x_e = originOut_x + beam_sh[1] - 1
 
             beam_x_s = max(sub_x_s, 0)
-            if beam_x_s > self.flat_cube[0].shape[1] - 1: overlap_flag = 0
+            if beam_x_s > self.flat_cube[0].shape[1] - 1:
+                overlap_flag = 0
             if overlap_flag == 1:
                 beam_x_e = min(sub_x_e, self.flat_cube[0].shape[1] - 1)
-                if beam_x_e < 0: overlap_flag = 0
+                if beam_x_e < 0:
+                    overlap_flag = 0
 
             if overlap_flag == 1:
                 beam_y_s = max(sub_y_s, 0)
-                if beam_y_s > self.flat_cube[0].shape[0] - 1: overlap_flag = 0
+                if beam_y_s > self.flat_cube[0].shape[0] - 1:
+                    overlap_flag = 0
             if overlap_flag == 1:
                 beam_y_e = min(sub_y_e, self.flat_cube[0].shape[0] - 1)
-                if beam_y_e < 0: overlap_flag = 0
+                if beam_y_e < 0:
+                    overlap_flag = 0
 
             if overlap_flag == 1:
-                sub_flat_cube[:,beam_y_s-originOut_y:beam_y_e-originOut_y+1,beam_x_s-originOut_x:beam_x_e-originOut_x+1] = self.flat_cube[:,beam_y_s:beam_y_e+1,beam_x_s:beam_x_e+1]
+                sub_flat_cube[:, beam_y_s-originOut_y:beam_y_e-originOut_y+1, beam_x_s-originOut_x:beam_x_e -
+                              originOut_x+1] = self.flat_cube[:, beam_y_s:beam_y_e+1, beam_x_s:beam_x_e+1]
 
             for i in arange(0, len(self.flat_cube), 1):
-                beam_flat[:,i] = sub_flat_cube[i].flatten()
+                beam_flat[:, i] = sub_flat_cube[i].flatten()
 #            beam_flat = zeros([len(modelf), len(self.flat_cube)])
 #            flat_sh = self.flat_cube[0].shape
 #            for i in arange(0, beam_sh[0], 1):
@@ -243,7 +251,8 @@ class SpecDisperser(object):
                                                 flat_index[nonz], yfrac_beam[nonz],
                                                 sensitivity_beam[nonz],
                                                 modelf, x0,
-                                                array(self.img_sh, dtype=int64),
+                                                array(self.img_sh,
+                                                      dtype=int64),
                                                 array(beam_sh, dtype=int64),
                                                 beam_flat,
                                                 lam_beam[lam_index][nonz])
@@ -254,13 +263,15 @@ class SpecDisperser(object):
         if self.isAlongY == 1:
             model, _, _ = rotate90(array_orig=model, isClockwise=0)
 
-        return model, originOut_x, originOut_y, dxpix, dypix, lam_beam,ysens
+        return model, originOut_x, originOut_y, dxpix, dypix, lam_beam, ysens
 
     def writerSensitivityFile(self, conffile='', beam='', w=None, sens=None):
         orders = {'A': '1st', 'B': '0st', 'C': '2st', 'D': '-1st', 'E': '-2st'}
-        sens_file_name = conffile[0:-5] + '_sensitivity_' + orders[beam] + '.fits'
+        sens_file_name = conffile[0:-5] + \
+            '_sensitivity_' + orders[beam] + '.fits'
         if not os.path.exists(sens_file_name) == True:
-            senstivity_out = Table(array([w, sens]).T, names=('WAVELENGTH', 'SENSITIVITY'))
+            senstivity_out = Table(
+                array([w, sens]).T, names=('WAVELENGTH', 'SENSITIVITY'))
             senstivity_out.write(sens_file_name, format='fits')
 
 
@@ -284,7 +295,7 @@ class aXeConf():
             self.conf_file = conf_file
             self.count_beam_orders()
 
-            ## Global XOFF/YOFF offsets
+            # Global XOFF/YOFF offsets
             if 'XOFF' in self.conf.keys():
                 self.xoff = np.float(self.conf['XOFF'])
             else:
@@ -310,11 +321,11 @@ class aXeConf():
         conf = OrderedDict()
         lines = open(conf_file).readlines()
         for line in lines:
-            ## empty / commented lines
+            # empty / commented lines
             if (line.startswith('#')) | (line.strip() == '') | ('"' in line):
                 continue
 
-            ## split the line, taking out ; and # comments
+            # split the line, taking out ; and # comments
             spl = line.split(';')[0].split('#')[0].split()
             param = spl[0]
             if len(spl) > 2:
@@ -360,13 +371,14 @@ class aXeConf():
                 self.beams.append(beam)
                 self.dxlam[beam] = np.arange(self.conf['BEAM{0}'.format(beam)].min(),
                                              self.conf['BEAM{0}'.format(beam)].max(), dtype=int)
-                self.nx[beam] = int(self.dxlam[beam].max() - self.dxlam[beam].min()) + 1
+                self.nx[beam] = int(self.dxlam[beam].max() -
+                                    self.dxlam[beam].min()) + 1
                 self.sens[beam] = Table.read(
                     '{0}/{1}'.format(os.path.dirname(self.conf_file), self.conf['SENSITIVITY_{0}'.format(beam)]))
                 # self.sens[beam].wave = np.cast[np.double](self.sens[beam]['WAVELENGTH'])
                 # self.sens[beam].sens = np.cast[np.double](self.sens[beam]['SENSITIVITY'])
 
-                ### Need doubles for interpolating functions
+                # Need doubles for interpolating functions
                 for col in self.sens[beam].colnames:
                     data = np.cast[np.double](self.sens[beam][col])
                     self.sens[beam].remove_column(col)
@@ -394,22 +406,22 @@ class aXeConf():
             Evaluated field-dependent coefficients
 
         """
-        ## number of coefficients for a given polynomial order
-        ## 1:1, 2:3, 3:6, 4:10, order:order*(order+1)/2
+        # number of coefficients for a given polynomial order
+        # 1:1, 2:3, 3:6, 4:10, order:order*(order+1)/2
         if isinstance(coeffs, float):
             order = 1
         else:
             order = int(-1 + np.sqrt(1 + 8 * len(coeffs))) // 2
 
-        ## Build polynomial terms array
-        ## $a = a_0+a_1x_i+a_2y_i+a_3x_i^2+a_4x_iy_i+a_5yi^2+$ ...
+        # Build polynomial terms array
+        # $a = a_0+a_1x_i+a_2y_i+a_3x_i^2+a_4x_iy_i+a_5yi^2+$ ...
         xy = []
         for p in range(order):
             for px in range(p + 1):
                 # print 'x**%d y**%d' %(p-px, px)
                 xy.append(xi ** (p - px) * yi ** (px))
 
-        ## Evaluate the polynomial, allowing for N-dimensional inputs
+        # Evaluate the polynomial, allowing for N-dimensional inputs
         a = np.sum((np.array(xy).T * coeffs).T, axis=0)
 
         return a
@@ -445,26 +457,27 @@ class aXeConf():
             .. math:: dp = (u \sqrt{1+u^2} + \mathrm{arcsinh}\ u) / (4\cdot \mathrm{DYDX}[2])
 
         """
-        ## dp is the arc length along the trace
-        ## $\lambda = dldp_0 + dldp_1 dp + dldp_2 dp^2$ ...
+        # dp is the arc length along the trace
+        # $\lambda = dldp_0 + dldp_1 dp + dldp_2 dp^2$ ...
 
         poly_order = len(dydx) - 1
         if (poly_order == 2):
             if np.abs(np.unique(dydx[2])).max() == 0:
                 poly_order = 1
 
-        if poly_order == 0:  ## dy=0
+        if poly_order == 0:  # dy=0
             dp = dx
-        elif poly_order == 1:  ## constant dy/dx
+        elif poly_order == 1:  # constant dy/dx
             dp = np.sqrt(1 + dydx[1] ** 2) * (dx)
-        elif poly_order == 2:  ## quadratic trace
+        elif poly_order == 2:  # quadratic trace
             u0 = dydx[1] + 2 * dydx[2] * (0)
             dp0 = (u0 * np.sqrt(1 + u0 ** 2) + np.arcsinh(u0)) / (4 * dydx[2])
             u = dydx[1] + 2 * dydx[2] * (dx)
-            dp = (u * np.sqrt(1 + u ** 2) + np.arcsinh(u)) / (4 * dydx[2]) - dp0
+            dp = (u * np.sqrt(1 + u ** 2) + np.arcsinh(u)) / \
+                (4 * dydx[2]) - dp0
         else:
-            ## high order shape, numerical integration along trace
-            ## (this can be slow)
+            # high order shape, numerical integration along trace
+            # (this can be slow)
             xmin = np.minimum((dx).min(), 0)
             xmax = np.maximum((dx).max(), 0)
             xfull = np.arange(xmin, xmax)
@@ -472,11 +485,12 @@ class aXeConf():
             for i in range(1, poly_order):
                 dyfull += i * dydx[i] * (xfull - 0.5) ** (i - 1)
 
-            ## Integrate from 0 to dx / -dx
+            # Integrate from 0 to dx / -dx
             dpfull = xfull * 0.
             lt0 = xfull < 0
             if lt0.sum() > 1:
-                dpfull[lt0] = np.cumsum(np.sqrt(1 + dyfull[lt0][::-1] ** 2))[::-1]
+                dpfull[lt0] = np.cumsum(
+                    np.sqrt(1 + dyfull[lt0][::-1] ** 2))[::-1]
                 dpfull[lt0] *= -1
 
             #
@@ -520,10 +534,12 @@ class aXeConf():
         NORDER = self.orders[beam] + 1
 
         xi, yi = x - self.xoff, y - self.yoff
-        xoff_beam = self.field_dependent(xi, yi, self.conf['XOFF_{0}'.format(beam)])
-        yoff_beam = self.field_dependent(xi, yi, self.conf['YOFF_{0}'.format(beam)])
+        xoff_beam = self.field_dependent(
+            xi, yi, self.conf['XOFF_{0}'.format(beam)])
+        yoff_beam = self.field_dependent(
+            xi, yi, self.conf['YOFF_{0}'.format(beam)])
 
-        ## y offset of trace (DYDX)
+        # y offset of trace (DYDX)
         dydx = np.zeros(NORDER)  # 0 #+1.e-80
         dydx = [0] * NORDER
 
@@ -538,7 +554,7 @@ class aXeConf():
         for i in range(NORDER):
             dy += dydx[i] * (dx - xoff_beam) ** i
 
-        ## wavelength solution    
+        # wavelength solution
         dldp = np.zeros(NORDER)
         dldp = [0] * NORDER
 
@@ -556,7 +572,7 @@ class aXeConf():
         # ## dp is the arc length along the trace
         # ## $\lambda = dldp_0 + dldp_1 dp + dldp_2 dp^2$ ...
         # if self.conf['DYDX_ORDER_%s' %(beam)] == 0:   ## dy=0
-        #     dp = dx-xoff_beam                      
+        #     dp = dx-xoff_beam
         # elif self.conf['DYDX_ORDER_%s' %(beam)] == 1: ## constant dy/dx
         #     dp = np.sqrt(1+dydx[1]**2)*(dx-xoff_beam)
         # elif self.conf['DYDX_ORDER_%s' %(beam)] == 2: ## quadratic trace
@@ -573,7 +589,7 @@ class aXeConf():
         #     dyfull = 0
         #     for i in range(1, NORDER):
         #         dyfull += i*dydx[i]*(xfull-0.5)**(i-1)
-        #     
+        #
         #     ## Integrate from 0 to dx / -dx
         #     dpfull = xfull*0.
         #     lt0 = xfull <= 0
@@ -584,10 +600,10 @@ class aXeConf():
         #     gt0 = xfull >= 0
         #     if gt0.sum() > 0:
         #         dpfull[gt0] = np.cumsum(np.sqrt(1+dyfull[gt0]**2))
-        #       
+        #
         #     dp = np.interp(dx-xoff_beam, xfull, dpfull)
 
-        ## Evaluate dldp    
+        # Evaluate dldp
         lam = dp * 0.
         for i in range(NORDER):
             lam += dldp[i] * dp ** i
@@ -619,7 +635,8 @@ class aXeConf():
             if 'XOFF_{0}'.format(beam) not in self.conf.keys():
                 continue
 
-            xoff = self.field_dependent(x0, x1, self.conf['XOFF_{0}'.format(beam)])
+            xoff = self.field_dependent(
+                x0, x1, self.conf['XOFF_{0}'.format(beam)])
             dy, lam = self.get_beam_trace(x0, x1, dx=dx, beam=beam)
             xlim = self.conf['BEAM{0}'.format(beam)]
             ok = (dx >= xlim[0]) & (dx <= xlim[1])
@@ -627,7 +644,8 @@ class aXeConf():
                         alpha=0.5, edgecolor='None')
             plt.text(np.median(dx[ok]), np.median(dy[ok]) + 1, beam,
                      ha='center', va='center', fontsize=14)
-            print('Beam {0}, lambda=({1:.1f} - {2:.1f})'.format(beam, lam[ok].min(), lam[ok].max()))
+            print('Beam {0}, lambda=({1:.1f} - {2:.1f})'.format(beam,
+                  lam[ok].min(), lam[ok].max()))
 
         plt.grid()
         plt.xlabel(r'$\Delta x$')
@@ -650,7 +668,7 @@ class aXeConf():
 #     Returns
 #     -------
 #     conf : `~grizli.grismconf.aXeConf`
-#         Configuration file object.  Runs `conf.get_beams()` to read the 
+#         Configuration file object.  Runs `conf.get_beams()` to read the
 #         sensitivity curves.
 #     """
 #     conf = aXeConf(conf_file)
diff --git a/ObservationSim/MockObject/SpecDisperser/__init__.py b/observation_sim/mock_objects/SpecDisperser/__init__.py
similarity index 100%
rename from ObservationSim/MockObject/SpecDisperser/__init__.py
rename to observation_sim/mock_objects/SpecDisperser/__init__.py
diff --git a/ObservationSim/MockObject/SpecDisperser/disperse_c/__init__.py b/observation_sim/mock_objects/SpecDisperser/disperse_c/__init__.py
similarity index 100%
rename from ObservationSim/MockObject/SpecDisperser/disperse_c/__init__.py
rename to observation_sim/mock_objects/SpecDisperser/disperse_c/__init__.py
diff --git a/ObservationSim/MockObject/SpecDisperser/disperse_c/disperse.pyx b/observation_sim/mock_objects/SpecDisperser/disperse_c/disperse.pyx
similarity index 100%
rename from ObservationSim/MockObject/SpecDisperser/disperse_c/disperse.pyx
rename to observation_sim/mock_objects/SpecDisperser/disperse_c/disperse.pyx
diff --git a/ObservationSim/MockObject/SpecDisperser/disperse_c/interp.pyx b/observation_sim/mock_objects/SpecDisperser/disperse_c/interp.pyx
similarity index 100%
rename from ObservationSim/MockObject/SpecDisperser/disperse_c/interp.pyx
rename to observation_sim/mock_objects/SpecDisperser/disperse_c/interp.pyx
diff --git a/ObservationSim/MockObject/SpecDisperser/setup_c.py b/observation_sim/mock_objects/SpecDisperser/setup_c.py
similarity index 100%
rename from ObservationSim/MockObject/SpecDisperser/setup_c.py
rename to observation_sim/mock_objects/SpecDisperser/setup_c.py
diff --git a/ObservationSim/MockObject/Stamp.py b/observation_sim/mock_objects/Stamp.py
similarity index 77%
rename from ObservationSim/MockObject/Stamp.py
rename to observation_sim/mock_objects/Stamp.py
index 1da5cd481478d3327291e57b0f5fdfc570c00cf0..51de71c9b42cbcbc54f5a02045c4901030597aa3 100644
--- a/ObservationSim/MockObject/Stamp.py
+++ b/observation_sim/mock_objects/Stamp.py
@@ -1,13 +1,15 @@
-import os, sys
+import os
+import sys
 import numpy as np
 import galsim
 import astropy.constants as cons
 from astropy.table import Table
 from scipy import interpolate
 
-from ObservationSim.MockObject.MockObject import MockObject
-from ObservationSim.MockObject.SpecDisperser import SpecDisperser
-from ObservationSim.MockObject._util import eObs, integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getObservedSED, getABMAG,convolveGaussXorders
+from observation_sim.mock_objects.MockObject import MockObject
+from observation_sim.mock_objects.SpecDisperser import SpecDisperser
+from observation_sim.mock_objects._util import eObs, integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getObservedSED, getABMAG, convolveGaussXorders
+
 
 class Stamp(MockObject):
     def __init__(self, param, logger=None):
@@ -22,17 +24,17 @@ class Stamp(MockObject):
         if nphotons_tot == None:
             nphotons_tot = self.getElectronFluxFilt(filt, tel, exptime)
 
-
         try:
-            full = integrate_sed_bandpass(sed=self.sed, bandpass=filt.bandpass_full)
+            full = integrate_sed_bandpass(
+                sed=self.sed, bandpass=filt.bandpass_full)
         except Exception as e:
             print(e)
             self.logger.error(e)
             return False
 
-        #nphotons_sum = 0
-        #photons_list = []
-        #xmax, ymax = 0, 0
+        # nphotons_sum = 0
+        # photons_list = []
+        # xmax, ymax = 0, 0
 
         if self.getMagFilter(filt) <= 15:
             folding_threshold = 5.e-4
@@ -72,17 +74,18 @@ class Stamp(MockObject):
                 nphotons = ratio * nphotons_tot
             else:
                 continue
-            #nphotons_sum += nphotons
+            # nphotons_sum += nphotons
 
-            psf, pos_shear = psf_model.get_PSF(chip=chip, pos_img=pos_img, bandpass=bandpass, folding_threshold=folding_threshold)
+            psf, pos_shear = psf_model.get_PSF(
+                chip=chip, pos_img=pos_img, bandpass=bandpass, folding_threshold=folding_threshold)
 
-            _gal  = self.param['image']
-            galImg= galsim.ImageF(_gal, scale=self.param['pixScale'])
-            gal_temp= galsim.InterpolatedImage(galImg)
-            gal_temp= gal_temp.shear(gal_shear)
-            gal_temp= gal_temp.withFlux(nphotons)
+            _gal = self.param['image']
+            galImg = galsim.ImageF(_gal, scale=self.param['pixScale'])
+            gal_temp = galsim.InterpolatedImage(galImg)
+            gal_temp = gal_temp.shear(gal_shear)
+            gal_temp = gal_temp.withFlux(nphotons)
 
-            gal_temp= galsim.Convolve(psf, gal_temp)
+            gal_temp = galsim.Convolve(psf, gal_temp)
 
             if i == 0:
                 gal = gal_temp
@@ -95,7 +98,8 @@ class Stamp(MockObject):
             return 2, pos_shear
 
         stamp.setCenter(x_nominal, y_nominal)
-        bounds = stamp.bounds & galsim.BoundsI(0, chip.npix_x - 1, 0, chip.npix_y - 1)
+        bounds = stamp.bounds & galsim.BoundsI(
+            0, chip.npix_x - 1, 0, chip.npix_y - 1)
 
         if bounds.area() > 0:
             chip.img.setOrigin(0, 0)
@@ -105,22 +109,22 @@ class Stamp(MockObject):
             del stamp
 
         if is_updated == 0:
-            print("fits obj %s missed"%(self.id))
+            print("fits obj %s missed" % (self.id))
             if self.logger:
-                self.logger.info("fits obj %s missed"%(self.id))
+                self.logger.info("fits obj %s missed" % (self.id))
             return 0, pos_shear
 
         return 1, pos_shear
 
-
     def drawObj_slitless(self, tel, pos_img, psf_model, bandpass_list, filt, chip, nphotons_tot=None, g1=0, g2=0,
                          exptime=150., normFilter=None, grating_split_pos=3685, fd_shear=None):
         if normFilter is not None:
             norm_thr_rang_ids = normFilter['SENSITIVITY'] > 0.001
             sedNormFactor = getNormFactorForSpecWithABMAG(ABMag=self.param['mag_use_normal'], spectrum=self.sed,
-                                                        norm_thr=normFilter,
-                                                        sWave=np.floor(normFilter[norm_thr_rang_ids][0][0]),
-                                                        eWave=np.ceil(normFilter[norm_thr_rang_ids][-1][0]))
+                                                          norm_thr=normFilter,
+                                                          sWave=np.floor(
+                                                              normFilter[norm_thr_rang_ids][0][0]),
+                                                          eWave=np.ceil(normFilter[norm_thr_rang_ids][-1][0]))
             if sedNormFactor == 0:
                 return 2, None
         else:
@@ -140,7 +144,6 @@ class Stamp(MockObject):
 
         chip_wcs_local = self.chip_wcs.local(self.real_pos)
 
-
         if self.getMagFilter(filt) <= 15:
             folding_threshold = 5.e-4
         else:
@@ -150,7 +153,8 @@ class Stamp(MockObject):
 
         flat_cube = chip.flat_cube
 
-        xOrderSigPlus = {'A':1.3909419820029296,'B':1.4760376591236062,'C':4.035447379743442,'D':5.5684364343742825,'E':16.260021029735388}
+        xOrderSigPlus = {'A': 1.3909419820029296, 'B': 1.4760376591236062,
+                         'C': 4.035447379743442, 'D': 5.5684364343742825, 'E': 16.260021029735388}
         grating_split_pos_chip = 0 + grating_split_pos
 
         branges = np.zeros([len(bandpass_list), 2])
@@ -174,9 +178,9 @@ class Stamp(MockObject):
 
             # psf, pos_shear = psf_model.get_PSF(chip=chip, pos_img=pos_img, bandpass=bandpass, folding_threshold=folding_threshold)
 
-            _gal  = self.param['image']
-            galImg= galsim.ImageF(_gal, scale=self.param['pixScale'])
-            gal   = galsim.InterpolatedImage(galImg)
+            _gal = self.param['image']
+            galImg = galsim.ImageF(_gal, scale=self.param['pixScale'])
+            gal = galsim.InterpolatedImage(galImg)
 
             # (TEST) Random knots
             # knots = galsim.RandomKnots(npoints=100, profile=disk)
@@ -196,40 +200,43 @@ class Stamp(MockObject):
             #     # if fd_shear is not None:
             #     #     gal = gal.shear(fd_shear)
 
-            starImg = gal.drawImage(wcs=chip_wcs_local, offset=offset,method = 'real_space')
+            starImg = gal.drawImage(
+                wcs=chip_wcs_local, offset=offset, method='real_space')
 
             origin_star = [y_nominal - (starImg.center.y - starImg.ymin),
                            x_nominal - (starImg.center.x - starImg.xmin)]
             starImg.setOrigin(0, 0)
             gal_origin = [origin_star[0], origin_star[1]]
-            gal_end = [origin_star[0] + starImg.array.shape[0] - 1, origin_star[1] + starImg.array.shape[1] - 1]
+            gal_end = [origin_star[0] + starImg.array.shape[0] -
+                       1, origin_star[1] + starImg.array.shape[1] - 1]
 
             if gal_origin[1] < grating_split_pos_chip < gal_end[1]:
                 subSlitPos = int(grating_split_pos_chip - gal_origin[1] + 1)
-                ## part img disperse
+                # part img disperse
 
                 subImg_p1 = starImg.array[:, 0:subSlitPos]
                 star_p1 = galsim.Image(subImg_p1)
                 star_p1.setOrigin(0, 0)
                 origin_p1 = origin_star
-                xcenter_p1 = min(x_nominal,grating_split_pos_chip-1) - 0
+                xcenter_p1 = min(x_nominal, grating_split_pos_chip-1) - 0
                 ycenter_p1 = y_nominal-0
 
                 sdp_p1 = SpecDisperser(orig_img=star_p1, xcenter=xcenter_p1,
-                                    ycenter=ycenter_p1, origin=origin_p1,
-                                    tar_spec=normalSED,
-                                    band_start=brange[0], band_end=brange[1],
-                                    conf=chip.sls_conf[0],
-                                    isAlongY=0,
-                                    flat_cube=flat_cube)
+                                       ycenter=ycenter_p1, origin=origin_p1,
+                                       tar_spec=normalSED,
+                                       band_start=brange[0], band_end=brange[1],
+                                       conf=chip.sls_conf[0],
+                                       isAlongY=0,
+                                       flat_cube=flat_cube)
 
                 # self.addSLStoChipImage(sdp=sdp_p1, chip=chip, xOrderSigPlus = xOrderSigPlus, local_wcs=chip_wcs_local)
                 pos_shear = self.addSLStoChipImageWithPSF(sdp=sdp_p1, chip=chip, pos_img_local=[xcenter_p1, ycenter_p1],
                                                           psf_model=psf_model, bandNo=i + 1,
                                                           grating_split_pos=grating_split_pos,
-                                                          local_wcs=chip_wcs_local, pos_img = pos_img)
+                                                          local_wcs=chip_wcs_local, pos_img=pos_img)
 
-                subImg_p2 = starImg.array[:, subSlitPos+1:starImg.array.shape[1]]
+                subImg_p2 = starImg.array[:,
+                                          subSlitPos+1:starImg.array.shape[1]]
                 star_p2 = galsim.Image(subImg_p2)
                 star_p2.setOrigin(0, 0)
                 origin_p2 = [origin_star[0], grating_split_pos_chip]
@@ -248,11 +255,11 @@ class Stamp(MockObject):
                 pos_shear = self.addSLStoChipImageWithPSF(sdp=sdp_p2, chip=chip, pos_img_local=[xcenter_p2, ycenter_p2],
                                                           psf_model=psf_model, bandNo=i + 1,
                                                           grating_split_pos=grating_split_pos,
-                                                          local_wcs=chip_wcs_local, pos_img = pos_img)
+                                                          local_wcs=chip_wcs_local, pos_img=pos_img)
 
                 del sdp_p1
                 del sdp_p2
-            elif grating_split_pos_chip<=gal_origin[1]:
+            elif grating_split_pos_chip <= gal_origin[1]:
                 sdp = SpecDisperser(orig_img=starImg, xcenter=x_nominal - 0,
                                     ycenter=y_nominal - 0, origin=origin_star,
                                     tar_spec=normalSED,
@@ -264,9 +271,9 @@ class Stamp(MockObject):
                 pos_shear = self.addSLStoChipImageWithPSF(sdp=sdp, chip=chip, pos_img_local=[x_nominal, y_nominal],
                                                           psf_model=psf_model, bandNo=i + 1,
                                                           grating_split_pos=grating_split_pos,
-                                                          local_wcs=chip_wcs_local, pos_img = pos_img)
+                                                          local_wcs=chip_wcs_local, pos_img=pos_img)
                 del sdp
-            elif grating_split_pos_chip>=gal_end[1]:
+            elif grating_split_pos_chip >= gal_end[1]:
                 sdp = SpecDisperser(orig_img=starImg, xcenter=x_nominal - 0,
                                     ycenter=y_nominal - 0, origin=origin_star,
                                     tar_spec=normalSED,
@@ -278,7 +285,7 @@ class Stamp(MockObject):
                 pos_shear = self.addSLStoChipImageWithPSF(sdp=sdp, chip=chip, pos_img_local=[x_nominal, y_nominal],
                                                           psf_model=psf_model, bandNo=i + 1,
                                                           grating_split_pos=grating_split_pos,
-                                                          local_wcs=chip_wcs_local, pos_img = pos_img)
+                                                          local_wcs=chip_wcs_local, pos_img=pos_img)
                 del sdp
 
             # print(self.y_nominal, starImg.center.y, starImg.ymin)
diff --git a/ObservationSim/MockObject/Star.py b/observation_sim/mock_objects/Star.py
similarity index 88%
rename from ObservationSim/MockObject/Star.py
rename to observation_sim/mock_objects/Star.py
index 04fc88ea7a3e7369b4d98f74fdb5531616e6d5ec..c27b4bab7036874913088a156f07b137dd340f13 100755
--- a/ObservationSim/MockObject/Star.py
+++ b/observation_sim/mock_objects/Star.py
@@ -6,8 +6,8 @@ import astropy.constants as cons
 from astropy.table import Table
 from scipy import interpolate
 
-from ObservationSim.MockObject._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getObservedSED, getABMAG, tag_sed
-from ObservationSim.MockObject.MockObject import MockObject
+from observation_sim.mock_objects._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getObservedSED, getABMAG, tag_sed
+from observation_sim.mock_objects.MockObject import MockObject
 
 
 class Star(MockObject):
diff --git a/ObservationSim/MockObject/__init__.py b/observation_sim/mock_objects/__init__.py
similarity index 72%
rename from ObservationSim/MockObject/__init__.py
rename to observation_sim/mock_objects/__init__.py
index 261107321d91c55eb6424d4dcdbceddfc4957ea3..0a655e14de1cc73602fcf8b3f38b57d038e92902 100755
--- a/ObservationSim/MockObject/__init__.py
+++ b/observation_sim/mock_objects/__init__.py
@@ -5,5 +5,3 @@ from .Quasar import Quasar
 from .Star import Star
 from .Stamp import Stamp
 from .FlatLED import FlatLED
-# from .SkybackgroundMap import *
-# from .CosmicRay import CosmicRay
diff --git a/ObservationSim/MockObject/_util.py b/observation_sim/mock_objects/_util.py
similarity index 62%
rename from ObservationSim/MockObject/_util.py
rename to observation_sim/mock_objects/_util.py
index 02aee7700f411d53bf05850bfee514d3f4898f45..f5b0c06db23e4f4a1bd85e0dae3f3b413bbf79c4 100755
--- a/ObservationSim/MockObject/_util.py
+++ b/observation_sim/mock_objects/_util.py
@@ -7,16 +7,19 @@ import galsim
 
 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
+H_PLANK = 6.626196e-27  # Plank constant: erg s
 
-def comoving_dist(z, om_m=0.3111, om_L=0.6889, h=0.6766): 
+
+def comoving_dist(z, om_m=0.3111, om_L=0.6889, h=0.6766):
     # Return comving distance in pc
-    H0 = h*100. # km / (s Mpc)
+    H0 = h*100.  # km / (s Mpc)
+
     def dist_int(z):
         return 1./np.sqrt(om_m*(1.+z)**3 + om_L)
     res, err = integrate.quad(dist_int, 0., z)
     return [res * (VC_M/1e3/H0) * 1e6, err * (VC_M/1e3/H0) * 1e6]
 
+
 def magToFlux(mag):
     """
     flux of a given AB magnitude
@@ -30,6 +33,7 @@ def magToFlux(mag):
     flux = 10**(-0.4*(mag+48.6))
     return flux
 
+
 def extAv(nav, seed=1212123):
     """
     Generate random intrinsic extinction Av
@@ -39,7 +43,7 @@ def extAv(nav, seed=1212123):
     tau = 0.4
     peak, a = 0.1, 0.5
     b = a*(tau-peak)
-    pav = lambda av: (a*av+b)*np.exp(-av/tau)
+    def pav(av): return (a*av+b)*np.exp(-av/tau)
     avmin, avmax = 0., 3.
     avs = np.linspace(avmin, avmax, int((avmax-avmin)/0.001)+1)
     norm = np.trapz(pav(avs), avs)
@@ -66,18 +70,20 @@ def seds(sedlistn, seddir="./", unit="A"):
     reds = {}
     sedlist = seddir + sedlistn
     sedn = open(sedlist).read().splitlines()
-    sedtype = range(1,len(sedn)+1)
+    sedtype = range(1, len(sedn)+1)
     for i in range(len(sedn)):
         xxx = sedn[i].split()
         isedn = seddir+xxx[0]
         itype = sedtype[i]
         ised = np.loadtxt(isedn)
-        if unit=="nm": ised[:,0] *= 10.0
+        if unit == "nm":
+            ised[:, 0] *= 10.0
         seds[itype] = ised
         reds[itype] = int(xxx[1])
 
     return seds, reds
 
+
 def sed_assign(phz, btt, rng):
     """
     assign SED template to a galaxy.
@@ -106,6 +112,8 @@ def sed_assign(phz, btt, rng):
     return sedtype
 
 ###########################################
+
+
 def tflux(filt, sed, redshift=0.0, av=0.0, redden=0):
     """
     calculate the theoretical SED for given filter set and template
@@ -130,44 +138,47 @@ def tflux(filt, sed, redshift=0.0, av=0.0, redden=0):
         SED in observed frame
     """
     z = redshift + 1.0
-    sw, sf = sed[:,0], sed[:,1]
+    sw, sf = sed[:, 0], sed[:, 1]
     # reddening
     sf = reddening(sw, sf, av=av, model=redden)
     sw, sf = sw*z, sf*(z**3)
     # lyman forest correction
     sf = lyman_forest(sw, sf, redshift)
-    
+
     sedxx = (sw.copy(), sf.copy())
-    
+
     sw = VC_A/sw
-    sf = sf*(VC_A/sw**2) # convert flux unit to erg/s/cm^s/Hz
+    sf = sf*(VC_A/sw**2)  # convert flux unit to erg/s/cm^s/Hz
     sw, sf = sw[::-1], sf[::-1]
     sfun = interp1d(sw, sf, kind='linear')
 
-    fwave, fresp = filt[:,0], filt[:,1]
+    fwave, fresp = filt[:, 0], filt[:, 1]
     fwave = VC_A/fwave
     fwave, fresp = fwave[::-1], fresp[::-1]
     tflux = sfun(fwave)
 
     zpflux = 3.631*1.0e-20
 
-    tflux = np.trapz(tflux*fresp/fwave,fwave)/np.trapz(zpflux*fresp/fwave,fwave)
-    #tflux = np.trapz(tflux*fresp,fwave)/np.trapz(zpflux*fresp,fwave)
+    tflux = np.trapz(tflux*fresp/fwave, fwave) / \
+        np.trapz(zpflux*fresp/fwave, fwave)
+    # tflux = np.trapz(tflux*fresp,fwave)/np.trapz(zpflux*fresp,fwave)
 
     return tflux, sedxx
 
 ###########################################
+
+
 def lyman_forest(wavelen, flux, z):
     """
     Compute the Lyman forest mean absorption of an input spectrum,
     according to D_A and D_B evolution from Madau (1995).
     The waveeln and flux are in observed frame
     """
-    if z<=0:
+    if z <= 0:
         flux0 = flux
     else:
         nw = 200
-        istep = np.linspace(0,nw-1,nw)
+        istep = np.linspace(0, nw-1, nw)
         w1a, w2a = 1050.0*(1.0+z), 1170.0*(1.0+z)
         w1b, w2b = 920.0*(1.0+z), 1015.0*(1.0+z)
         wstepa = (w2a-w1a)/float(nw)
@@ -177,20 +188,25 @@ def lyman_forest(wavelen, flux, z):
         ptaua = np.exp(-3.6e-03*(wtempa/1216.0)**3.46)
 
         wtempb = w1b + istep*wstepb
-        ptaub = np.exp(-1.7e-3*(wtempb/1026.0)**3.46\
-                       -1.2e-3*(wtempb/972.50)**3.46\
-                       -9.3e-4*(wtempb/950.00)**3.46)
+        ptaub = np.exp(-1.7e-3*(wtempb/1026.0)**3.46
+                       - 1.2e-3*(wtempb/972.50)**3.46
+                       - 9.3e-4*(wtempb/950.00)**3.46)
 
         da = (1.0/(120.0*(1.0+z)))*np.trapz(ptaua, wtempa)
         db = (1.0/(95.0*(1.0+z)))*np.trapz(ptaub, wtempb)
 
-        if da>1.0: da=1.0
-        if db>1.0: db=1.0
-        if da<0.0: da=0.0
-        if db<0.0: db=0.0
+        if da > 1.0:
+            da = 1.0
+        if db > 1.0:
+            db = 1.0
+        if da < 0.0:
+            da = 0.0
+        if db < 0.0:
+            db = 0.0
         flux0 = flux.copy()
-        id0 = wavelen<=1026.0*(1.0+z)
-        id1 = np.logical_and(wavelen<1216.0*(1.0+z),wavelen>=1026.0*(1.0+z))
+        id0 = wavelen <= 1026.0*(1.0+z)
+        id1 = np.logical_and(wavelen < 1216.0*(1.0+z),
+                             wavelen >= 1026.0*(1.0+z))
         flux0[id0] = db*flux[id0]
         flux0[id1] = da*flux[id1]
 
@@ -220,128 +236,131 @@ def reddening(sw, sf, av=0.0, model=0):
     Return:
     reddening-corrected flux or observed flux
     """
-    if model==0 or av==0.0:
-        flux=sf
-    elif model==1: # Allen (1976) for the Milky Way
-        lambda0 = np.array([1000, 1110, 1250, 1430, 1670, \
-                            2000, 2220, 2500, 2850, 3330, \
-                            3650, 4000, 4400, 5000, 5530, \
+    if model == 0 or av == 0.0:
+        flux = sf
+    elif model == 1:  # Allen (1976) for the Milky Way
+        lambda0 = np.array([1000, 1110, 1250, 1430, 1670,
+                            2000, 2220, 2500, 2850, 3330,
+                            3650, 4000, 4400, 5000, 5530,
                             6700, 9000, 10000, 20000, 100000], dtype=float)
-        kR = np.array([4.20, 3.70, 3.30, 3.00, 2.70, \
-                       2.80, 2.90, 2.30, 1.97, 1.69, \
-                       1.58, 1.45, 1.32, 1.13, 1.00, \
-                       0.74, 0.46, 0.38, 0.11, 0.00],dtype=float)
+        kR = np.array([4.20, 3.70, 3.30, 3.00, 2.70,
+                       2.80, 2.90, 2.30, 1.97, 1.69,
+                       1.58, 1.45, 1.32, 1.13, 1.00,
+                       0.74, 0.46, 0.38, 0.11, 0.00], dtype=float)
         ext0 = InterpolatedUnivariateSpline(lambda0, kR, k=1)
         A_lambda = av*ext0(sw)
-        A_lambda[A_lambda<0.0] = 0.0
+        A_lambda[A_lambda < 0.0] = 0.0
         flux = sf*10**(-0.4*A_lambda)
-    elif model==2: # Seaton (1979) fit by Fitzpatrick (1986) for the Milky Way
-        Rv=3.1
+    elif model == 2:  # Seaton (1979) fit by Fitzpatrick (1986) for the Milky Way
+        Rv = 3.1
         al0, ga, c1, c2, c3, c4 = 4.595, 1.051, -0.38, 0.74, 3.96, 0.26
-        ff11 = __red(1100.0,al0,ga,c1,c2,c3,c4)
-        ff12 = __red(1200.0,al0,ga,c1,c2,c3,c4)
-        slope=(ff12-ff11)/100.0
-        lambda0 = np.array([3650, 4000, 4400, 5000, 5530, \
+        ff11 = __red(1100.0, al0, ga, c1, c2, c3, c4)
+        ff12 = __red(1200.0, al0, ga, c1, c2, c3, c4)
+        slope = (ff12-ff11)/100.0
+        lambda0 = np.array([3650, 4000, 4400, 5000, 5530,
                             6700, 9000, 10000, 20000, 100000], dtype=float)
-        kR = np.array([1.58, 1.45, 1.32, 1.13, 1.00, \
-                       0.74, 0.46, 0.38, 0.11, 0.00],dtype=float)
+        kR = np.array([1.58, 1.45, 1.32, 1.13, 1.00,
+                       0.74, 0.46, 0.38, 0.11, 0.00], dtype=float)
         fun = interp1d(lambda0, kR, kind='linear')
 
-        sw0 = sw[sw<1200.0]
+        sw0 = sw[sw < 1200.0]
         A_lambda0 = (ff11+(sw0-1100.0)*slope)/Rv+1.0
-        sw1 = sw[np.logical_and(sw>=1200.0, sw<=3650.0)]
-        ff = __red(sw1,al0,ga,c1,c2,c3,c4)
+        sw1 = sw[np.logical_and(sw >= 1200.0, sw <= 3650.0)]
+        ff = __red(sw1, al0, ga, c1, c2, c3, c4)
         A_lambda1 = ff/Rv+1.0
-        sw2 = sw[np.logical_and(sw>3650.0, sw<=100000.0)]
+        sw2 = sw[np.logical_and(sw > 3650.0, sw <= 100000.0)]
         A_lambda2 = fun(sw2)
-        A_lambda3 = sw[sw>100000.0]*0.0
-        A_lambda = av*np.hstack([A_lambda0,A_lambda1,A_lambda2,A_lambda3])
-        A_lambda[A_lambda<0.0] = 0.0
+        A_lambda3 = sw[sw > 100000.0]*0.0
+        A_lambda = av*np.hstack([A_lambda0, A_lambda1, A_lambda2, A_lambda3])
+        A_lambda[A_lambda < 0.0] = 0.0
         flux = sf*10**(-0.4*A_lambda)
-    elif model==3: # Fitzpatrick (1986) for the Large Magellanic Cloud (LMC)
-        Rv=3.1
+    elif model == 3:  # Fitzpatrick (1986) for the Large Magellanic Cloud (LMC)
+        Rv = 3.1
         al0, ga, c1, c2, c3, c4 = 4.608, 0.994, -0.69, 0.89, 2.55, 0.50
-        ff11 = __red(1100.0,al0,ga,c1,c2,c3,c4)
-        ff12 = __red(1200.0,al0,ga,c1,c2,c3,c4)
-        slope=(ff12-ff11)/100.0
-        lambda0 = np.array([3330, 3650, 4000, 4400, 5000, 5530, \
+        ff11 = __red(1100.0, al0, ga, c1, c2, c3, c4)
+        ff12 = __red(1200.0, al0, ga, c1, c2, c3, c4)
+        slope = (ff12-ff11)/100.0
+        lambda0 = np.array([3330, 3650, 4000, 4400, 5000, 5530,
                             6700, 9000, 10000, 20000, 100000], dtype=float)
-        kR = np.array([1.682, 1.58, 1.45, 1.32, 1.13, 1.00, \
-                       0.74, 0.46, 0.38, 0.11, 0.00],dtype=float)
+        kR = np.array([1.682, 1.58, 1.45, 1.32, 1.13, 1.00,
+                       0.74, 0.46, 0.38, 0.11, 0.00], dtype=float)
         fun = interp1d(lambda0, kR, kind='linear')
 
-        sw0 = sw[sw<1200.0]
+        sw0 = sw[sw < 1200.0]
         A_lambda0 = (ff11+(sw0-1100.0)*slope)/Rv+1.0
-        sw1 = sw[np.logical_and(sw>=1200.0, sw<=3330.0)]
-        ff = __red(sw1,al0,ga,c1,c2,c3,c4)
+        sw1 = sw[np.logical_and(sw >= 1200.0, sw <= 3330.0)]
+        ff = __red(sw1, al0, ga, c1, c2, c3, c4)
         A_lambda1 = ff/Rv+1.0
-        sw2 = sw[np.logical_and(sw>3330.0, sw<=100000.0)]
+        sw2 = sw[np.logical_and(sw > 3330.0, sw <= 100000.0)]
         A_lambda2 = fun(sw2)
-        A_lambda3 = sw[sw>100000.0]*0.0
-        A_lambda = av*np.hstack([A_lambda0,A_lambda1,A_lambda2,A_lambda3])
-        A_lambda[A_lambda<0.0] = 0.0
+        A_lambda3 = sw[sw > 100000.0]*0.0
+        A_lambda = av*np.hstack([A_lambda0, A_lambda1, A_lambda2, A_lambda3])
+        A_lambda[A_lambda < 0.0] = 0.0
         flux = sf*10**(-0.4*A_lambda)
-    elif model==4: # Prevot et al (1984) and Bouchet (1985) for the Small Magellanic Cloud (SMC)
+    # Prevot et al (1984) and Bouchet (1985) for the Small Magellanic Cloud (SMC)
+    elif model == 4:
         Rv = 2.72
-        lambda0 = np.array([1275, 1330, 1385, 1435, 1490, 1545, \
-                            1595, 1647, 1700, 1755, 1810, 1860, \
-                            1910, 2000, 2115, 2220, 2335, 2445, \
-                            2550, 2665, 2778, 2890, 2995, 3105, \
+        lambda0 = np.array([1275, 1330, 1385, 1435, 1490, 1545,
+                            1595, 1647, 1700, 1755, 1810, 1860,
+                            1910, 2000, 2115, 2220, 2335, 2445,
+                            2550, 2665, 2778, 2890, 2995, 3105,
                             3704, 4255, 5291, 12500, 16500, 22000], dtype=float)
-        kR = np.array([13.54, 12.52, 11.51, 10.80, 9.84, 9.28, \
-                        9.06, 8.49, 8.01, 7.71, 7.17, 6.90, 6.76, \
-                        6.38, 5.85, 5.30, 4.53, 4.24, 3.91, 3.49, \
-                        3.15, 3.00, 2.65, 2.29, 1.81, 1.00, 0.00, \
-                        -2.02, -2.36, -2.47],dtype=float)
+        kR = np.array([13.54, 12.52, 11.51, 10.80, 9.84, 9.28,
+                       9.06, 8.49, 8.01, 7.71, 7.17, 6.90, 6.76,
+                       6.38, 5.85, 5.30, 4.53, 4.24, 3.91, 3.49,
+                       3.15, 3.00, 2.65, 2.29, 1.81, 1.00, 0.00,
+                       -2.02, -2.36, -2.47], dtype=float)
         kR = kR/Rv+1.0
         ext0 = InterpolatedUnivariateSpline(lambda0, kR, k=1)
         A_lambda = av*ext0(sw)
-        A_lambda[A_lambda<0.0] = 0.0
+        A_lambda[A_lambda < 0.0] = 0.0
         flux = sf*10**(-0.4*A_lambda)
-    elif model==5: # Calzetti et al (2000) for starburst galaxies
+    elif model == 5:  # Calzetti et al (2000) for starburst galaxies
         Rv = 4.05
-        sw = sw*1.0e-04           #wavelength in microns
+        sw = sw*1.0e-04  # wavelength in microns
 
-        fun1 = lambda x: 2.659*(-2.156+1.509/x-0.198/x**2+0.011/x**3)+Rv
-        fun2 = lambda x: 2.659*(-1.857+1.040/x)+Rv
+        def fun1(x): return 2.659*(-2.156+1.509/x-0.198/x**2+0.011/x**3)+Rv
+        def fun2(x): return 2.659*(-1.857+1.040/x)+Rv
 
         ff11, ff12 = fun1(0.11), fun1(0.12)
-        slope1=(ff12-ff11)/0.01
+        slope1 = (ff12-ff11)/0.01
         ff99, ff100 = fun2(2.19), fun2(2.2)
-        slope2=(ff100-ff99)/0.01
+        slope2 = (ff100-ff99)/0.01
 
-        sw0 = sw[sw<0.12]
-        sw1 = sw[np.logical_and(sw>=0.12, sw<=0.63)]
-        sw2 = sw[np.logical_and(sw>0.63, sw<=2.2)]
-        sw3 = sw[sw>2.2]
+        sw0 = sw[sw < 0.12]
+        sw1 = sw[np.logical_and(sw >= 0.12, sw <= 0.63)]
+        sw2 = sw[np.logical_and(sw > 0.63, sw <= 2.2)]
+        sw3 = sw[sw > 2.2]
         k_lambda0 = ff11+(sw0-0.11)*slope1
         k_lambda1, k_lambda2 = fun1(sw1), fun2(sw2)
         k_lambda3 = ff99+(sw3-2.19)*slope2
-        A_lambda = av*np.hstack([k_lambda0,k_lambda1,k_lambda2,k_lambda3])/Rv
-        A_lambda[A_lambda<0.0] = 0.0
+        A_lambda = av*np.hstack([k_lambda0, k_lambda1,
+                                k_lambda2, k_lambda3])/Rv
+        A_lambda[A_lambda < 0.0] = 0.0
         flux = sf*10**(-0.4*A_lambda)
-    elif model==6: # Reddy et al (2015) for satr forming galaxies
+    elif model == 6:  # Reddy et al (2015) for satr forming galaxies
         Rv = 2.505
         sw = sw*1.0e-04
 
-        fun1 = lambda x: -5.726+4.004/x-0.525/x**2+0.029/x**3+Rv
-        fun2 = lambda x: -2.672-0.010/x+1.532/x**2-0.412/x**3+Rv
+        def fun1(x): return -5.726+4.004/x-0.525/x**2+0.029/x**3+Rv
+        def fun2(x): return -2.672-0.010/x+1.532/x**2-0.412/x**3+Rv
 
         ff11, ff12 = fun1(0.14), fun1(0.15)
-        slope1=(ff12-ff11)/0.01
+        slope1 = (ff12-ff11)/0.01
         ff99, ff100 = fun2(2.84), fun2(2.85)
-        slope2=(ff100-ff99)/0.01
+        slope2 = (ff100-ff99)/0.01
 
-        sw0 = sw[sw<0.15]
-        sw1 = sw[np.logical_and(sw>=0.15, sw<0.60)]
-        sw2 = sw[np.logical_and(sw>=0.60, sw<2.85)]
-        sw3 = sw[sw>=2.85]
+        sw0 = sw[sw < 0.15]
+        sw1 = sw[np.logical_and(sw >= 0.15, sw < 0.60)]
+        sw2 = sw[np.logical_and(sw >= 0.60, sw < 2.85)]
+        sw3 = sw[sw >= 2.85]
         k_lambda0 = ff11+(sw0-0.14)*slope1
         k_lambda1, k_lambda2 = fun1(sw1), fun2(sw2)
         k_lambda3 = ff99+(sw3-2.84)*slope2
-        A_lambda = av*np.hstack([k_lambda0,k_lambda1,k_lambda2,k_lambda3])/Rv
-        A_lambda[A_lambda<0.0] = 0.0
-        flux  = sf*10**(-0.4*A_lambda)
+        A_lambda = av*np.hstack([k_lambda0, k_lambda1,
+                                k_lambda2, k_lambda3])/Rv
+        A_lambda[A_lambda < 0.0] = 0.0
+        flux = sf*10**(-0.4*A_lambda)
 
     else:
         raise ValueError("!!! Please select a proper reddening model")
@@ -349,25 +368,30 @@ def reddening(sw, sf, av=0.0, model=0):
     return flux
 
 ###########################################
-def __red(alan,al0,ga,c1,c2,c3,c4):
 
-    fun1 = lambda x: c3/(((x-(al0**2/x))**2)+ga*ga)
-    fun2 = lambda x,cc: cc*(0.539*((x-5.9)**2)+0.0564*((x-5.9)**3))
-    fun = lambda x,cc: c1+c2*x+fun1(x)+fun2(x,cc)
 
-    ala = alan*1.0e-04 #wavelength in microns
+def __red(alan, al0, ga, c1, c2, c3, c4):
+
+    def fun1(x): return c3/(((x-(al0**2/x))**2)+ga*ga)
+    def fun2(x, cc): return cc*(0.539*((x-5.9)**2)+0.0564*((x-5.9)**3))
+    def fun(x, cc): return c1+c2*x+fun1(x)+fun2(x, cc)
+
+    ala = alan*1.0e-04  # wavelength in microns
     p = 1.0/ala
-    if np.size(p)>1:
-        p1, p2 = p[p>=5.9], p[p<5.9]
-        ff = np.append(fun(p1,c4), fun(p2,0.0))
-    elif np.size(p)==1:
-        if p<5.9: c4 = 0.0
+    if np.size(p) > 1:
+        p1, p2 = p[p >= 5.9], p[p < 5.9]
+        ff = np.append(fun(p1, c4), fun(p2, 0.0))
+    elif np.size(p) == 1:
+        if p < 5.9:
+            c4 = 0.0
         ff = fun(p, c4)
     else:
         return
     return ff
 
 ###########################################
+
+
 def sed2mag(mag_i, sedCat, filter_list, redshift=0.0, av=0.0, redden=0):
 
     # load the filters
@@ -378,19 +402,23 @@ def sed2mag(mag_i, sedCat, filter_list, redshift=0.0, av=0.0, redden=0):
         if filter_list[k].filter_type == 'i':
             nid = k
         bandpass = filter_list[k].bandpass_full
-        ktrans = np.transpose(np.array([bandpass.wave_list*10.0, bandpass.func(bandpass.wave_list)]))
-        aflux[k], isedObs = tflux(ktrans, sedCat, redshift=redshift, av=av, redden=redden)
+        ktrans = np.transpose(
+            np.array([bandpass.wave_list*10.0, bandpass.func(bandpass.wave_list)]))
+        aflux[k], isedObs = tflux(
+            ktrans, sedCat, redshift=redshift, av=av, redden=redden)
 
     # normalize to i-band
     aflux = aflux / aflux[nid]
 
     # magnitudes in all filters
     amag = -2.5*np.log10(aflux) + mag_i
-    spec = galsim.LookupTable(x=np.array(isedObs[0]), f=np.array(isedObs[1]), interpolant='nearest')
+    spec = galsim.LookupTable(x=np.array(isedObs[0]), f=np.array(
+        isedObs[1]), interpolant='nearest')
     isedObs = galsim.SED(spec, wave_type='A', flux_type='1', fast=False)
     return amag, isedObs
 
-def eObs(e1,e2,g1,g2):
+
+def eObs(e1, e2, g1, g2):
     """
     Calculate the sheared (observed) ellipticity using the 
     intrinsic ellipticity and cosmic shear components.
@@ -424,7 +452,7 @@ def eObs(e1,e2,g1,g2):
         e = complex(e1[i], e2[i])
         g = complex(g1[i], g2[i])
         e, gg = abs(e), abs(g)
-        if gg<=1.0:
+        if gg <= 1.0:
             tt = e + g
             bb = 1.0 + e*g.conjugate()
             eobs = tt/bb
@@ -432,27 +460,34 @@ def eObs(e1,e2,g1,g2):
             tt = 1.0 + g*e.conjugate()
             bb = e.conjugate() + g.conjugate()
             eobs = tt/bb
-    
+
     # derive the orientation
         dd = 0.5*np.arctan(abs(eobs.imag/eobs.real))*180.0/np.pi
-        if eobs.imag>0 and eobs.real>0: dd = dd
-        if eobs.imag>0 and eobs.real<0: dd = 90.0 - dd
-        if eobs.imag<0 and eobs.real>0: dd =  0.0 - dd
-        if eobs.imag<0 and eobs.real<0: dd = dd - 90.0
+        if eobs.imag > 0 and eobs.real > 0:
+            dd = dd
+        if eobs.imag > 0 and eobs.real < 0:
+            dd = 90.0 - dd
+        if eobs.imag < 0 and eobs.real > 0:
+            dd = 0.0 - dd
+        if eobs.imag < 0 and eobs.real < 0:
+            dd = dd - 90.0
 
         e1obs += [eobs.real]
         e2obs += [eobs.imag]
         eeobs += [abs(eobs)]
         theta += [dd]
 
-    e1obs,e2obs,eeobs,theta = np.array(e1obs),np.array(e2obs),np.array(eeobs),np.array(theta)
-    if nobj == 1: e1obs,e2obs,eeobs,theta = e1obs[0],e2obs[0],eeobs[0],theta[0]
-    
+    e1obs, e2obs, eeobs, theta = np.array(e1obs), np.array(
+        e2obs), np.array(eeobs), np.array(theta)
+    if nobj == 1:
+        e1obs, e2obs, eeobs, theta = e1obs[0], e2obs[0], eeobs[0], theta[0]
+
     return e1obs, e2obs, eeobs, theta
 
+
 def getObservedSED(sedCat, redshift=0.0, av=0.0, redden=0):
     z = redshift + 1.0
-    sw, sf = sedCat[:,0], sedCat[:,1]
+    sw, sf = sedCat[:, 0], sedCat[:, 1]
     # reddening
     sf = reddening(sw, sf, av=av, model=redden)
     # sw, sf = sw*z, sf*(z**3)
@@ -464,28 +499,33 @@ def getObservedSED(sedCat, redshift=0.0, av=0.0, redden=0):
     isedObs = (sw.copy(), sf.copy())
     return isedObs
 
+
 def integrate_sed_bandpass(sed, bandpass):
-    wave = np.linspace(bandpass.blue_limit, bandpass.red_limit, 1000) # in nm
+    wave = np.linspace(bandpass.blue_limit, bandpass.red_limit, 1000)  # in nm
     flux_normalized = sed(wave)*bandpass(wave)
     # print('in integrate_sed_bandpass', bandpass.blue_limit, bandpass.red_limit)
-    int_flux = np.trapz(y=flux_normalized, x=wave) * 10. # convert to photons s-1 m-2 A-1
+    int_flux = np.trapz(y=flux_normalized, x=wave) * \
+        10.  # convert to photons s-1 m-2 A-1
     return int_flux
 
+
 def getABMAG(interFlux, bandpass):
-    throughtput = Table(np.array(np.array([bandpass.wave_list*10.0, bandpass.func(bandpass.wave_list)])).T, names=(['WAVELENGTH', 'SENSITIVITY']))
+    throughtput = Table(np.array(np.array([bandpass.wave_list*10.0, bandpass.func(
+        bandpass.wave_list)])).T, names=(['WAVELENGTH', 'SENSITIVITY']))
     sWave = bandpass.blue_limit*10.0
     eWave = bandpass.red_limit*10.0
     # print('in getABMAG', sWave, eWave)
     ABMAG_zero = getABMagAverageVal(
-        ABmag=0, 
-        norm_thr=throughtput, 
-        sWave=sWave, 
+        ABmag=0,
+        norm_thr=throughtput,
+        sWave=sWave,
         eWave=eWave)
     flux_ave = interFlux / (eWave-sWave)
     ABMAG_spec = -2.5 * np.log10(flux_ave/ABMAG_zero)
     return ABMAG_spec
 
-def getABMagAverageVal(ABmag=20.,norm_thr=None, sWave=6840, eWave=8250):
+
+def getABMagAverageVal(ABmag=20., norm_thr=None, sWave=6840, eWave=8250):
     """
     norm_thr: astropy.table, 2 colum, 'WAVELENGTH', 'SENSITIVITY'
 
@@ -496,15 +536,16 @@ def getABMagAverageVal(ABmag=20.,norm_thr=None, sWave=6840, eWave=8250):
     inverseLambda = norm_thr['SENSITIVITY']/norm_thr['WAVELENGTH']
     norm_thr_i = interpolate.interp1d(norm_thr['WAVELENGTH'], inverseLambda)
 
-    x = np.linspace(sWave,eWave, int(eWave)-int(sWave)+1)
+    x = np.linspace(sWave, eWave, int(eWave)-int(sWave)+1)
     y = norm_thr_i(x)
-    AverageLamdaInverse = np.trapz(y,x)/(eWave-sWave)
+    AverageLamdaInverse = np.trapz(y, x)/(eWave-sWave)
     norm = 54798696332.52474 * pow(10.0, -0.4 * ABmag) * AverageLamdaInverse
     # print('AverageLamdaInverse = ', AverageLamdaInverse)
     # print('norm = ', norm)
 
     return norm
 
+
 def getNormFactorForSpecWithABMAG(ABMag=20., spectrum=None, norm_thr=None, sWave=6840, eWave=8250):
     """
     Use AB magnitude system (zero point, fv = 3631 janskys) in the normal band(norm_thr) normalize the spectrum by inpute ABMag
@@ -520,17 +561,19 @@ def getNormFactorForSpecWithABMAG(ABMag=20., spectrum=None, norm_thr=None, sWave
         the normalization factor   flux of AB system(fix a band  and magnitude ) /the flux of inpute spectrum(fix a band) 
     """
     spectrumi = interpolate.interp1d(spectrum['WAVELENGTH'], spectrum['FLUX'])
-    norm_thri = interpolate.interp1d(norm_thr['WAVELENGTH'], norm_thr['SENSITIVITY'])
+    norm_thri = interpolate.interp1d(
+        norm_thr['WAVELENGTH'], norm_thr['SENSITIVITY'])
 
-    x = np.linspace(sWave,eWave, int(eWave)-int(sWave)+1)
+    x = np.linspace(sWave, eWave, int(eWave)-int(sWave)+1)
 
     y_spec = spectrumi(x)
     y_thr = norm_thri(x)
 
     y = y_spec*y_thr
 
-    specAve = np.trapz(y,x)/(eWave-sWave)
-    norm = getABMagAverageVal(ABmag=ABMag, norm_thr=norm_thr, sWave=sWave, eWave=eWave)
+    specAve = np.trapz(y, x)/(eWave-sWave)
+    norm = getABMagAverageVal(
+        ABmag=ABMag, norm_thr=norm_thr, sWave=sWave, eWave=eWave)
 
     if specAve == 0:
         return 0
@@ -551,12 +594,14 @@ def tag_sed(h5file, model_tag, teff=5000, logg=2, feh=0):
         close_feh = 99
     else:
         close_feh = feh_grid[np.argmin(np.abs(feh_grid - feh))]
-    path = model_tag_str + f"_teff_{close_teff:.1f}_logg_{close_logg:.2f}_feh_{close_feh:.1f}"
+    path = model_tag_str + \
+        f"_teff_{close_teff:.1f}_logg_{close_logg:.2f}_feh_{close_feh:.1f}"
     wave = np.array(h5file["wave"][model_tag_str][()]).ravel()
     flux = np.array(h5file["sed"][path][()]).ravel()
     return path, wave, flux
 
-def convolveGaussXorders(img=None, sigma = 1):
+
+def convolveGaussXorders(img=None, sigma=1):
     from astropy.modeling.models import Gaussian2D
     from scipy import signal
     offset = int(np.ceil(sigma*10))
@@ -571,14 +616,13 @@ def convolveGaussXorders(img=None, sigma = 1):
     convImg = signal.fftconvolve(img, psf, mode='full', axes=None)
     return convImg, offset
 
-def convolveImg(img=None, psf = None):
+
+def convolveImg(img=None, psf=None):
     from astropy.modeling.models import Gaussian2D
     from scipy import signal
 
     convImg = signal.fftconvolve(img, psf, mode='full', axes=None)
     offset_x = int(psf.shape[1]/2. + 0.5) - 1
     offset_y = int(psf.shape[0]/2. + 0.5) - 1
-    offset = [offset_x,offset_y]
+    offset = [offset_x, offset_y]
     return convImg, offset
-
-
diff --git a/ObservationSim/MockObject/data/led/__init__.py b/observation_sim/mock_objects/data/__init__.py
similarity index 100%
rename from ObservationSim/MockObject/data/led/__init__.py
rename to observation_sim/mock_objects/data/__init__.py
diff --git a/ObservationSim/Straylight/data/__init__.py b/observation_sim/mock_objects/data/led/__init__.py
old mode 100755
new mode 100644
similarity index 100%
rename from ObservationSim/Straylight/data/__init__.py
rename to observation_sim/mock_objects/data/led/__init__.py
diff --git a/ObservationSim/MockObject/data/led/model_1050nm.fits b/observation_sim/mock_objects/data/led/model_1050nm.fits
similarity index 100%
rename from ObservationSim/MockObject/data/led/model_1050nm.fits
rename to observation_sim/mock_objects/data/led/model_1050nm.fits
diff --git a/ObservationSim/MockObject/data/led/model_275nm.fits b/observation_sim/mock_objects/data/led/model_275nm.fits
similarity index 100%
rename from ObservationSim/MockObject/data/led/model_275nm.fits
rename to observation_sim/mock_objects/data/led/model_275nm.fits
diff --git a/ObservationSim/MockObject/data/led/model_310nm.fits b/observation_sim/mock_objects/data/led/model_310nm.fits
similarity index 100%
rename from ObservationSim/MockObject/data/led/model_310nm.fits
rename to observation_sim/mock_objects/data/led/model_310nm.fits
diff --git a/ObservationSim/MockObject/data/led/model_340nm.fits b/observation_sim/mock_objects/data/led/model_340nm.fits
similarity index 100%
rename from ObservationSim/MockObject/data/led/model_340nm.fits
rename to observation_sim/mock_objects/data/led/model_340nm.fits
diff --git a/ObservationSim/MockObject/data/led/model_365nm.fits b/observation_sim/mock_objects/data/led/model_365nm.fits
similarity index 100%
rename from ObservationSim/MockObject/data/led/model_365nm.fits
rename to observation_sim/mock_objects/data/led/model_365nm.fits
diff --git a/ObservationSim/MockObject/data/led/model_430nm.fits b/observation_sim/mock_objects/data/led/model_430nm.fits
similarity index 100%
rename from ObservationSim/MockObject/data/led/model_430nm.fits
rename to observation_sim/mock_objects/data/led/model_430nm.fits
diff --git a/ObservationSim/MockObject/data/led/model_505nm.fits b/observation_sim/mock_objects/data/led/model_505nm.fits
similarity index 100%
rename from ObservationSim/MockObject/data/led/model_505nm.fits
rename to observation_sim/mock_objects/data/led/model_505nm.fits
diff --git a/ObservationSim/MockObject/data/led/model_545nm.fits b/observation_sim/mock_objects/data/led/model_545nm.fits
similarity index 100%
rename from ObservationSim/MockObject/data/led/model_545nm.fits
rename to observation_sim/mock_objects/data/led/model_545nm.fits
diff --git a/ObservationSim/MockObject/data/led/model_590nm.fits b/observation_sim/mock_objects/data/led/model_590nm.fits
similarity index 100%
rename from ObservationSim/MockObject/data/led/model_590nm.fits
rename to observation_sim/mock_objects/data/led/model_590nm.fits
diff --git a/ObservationSim/MockObject/data/led/model_670nm.fits b/observation_sim/mock_objects/data/led/model_670nm.fits
similarity index 100%
rename from ObservationSim/MockObject/data/led/model_670nm.fits
rename to observation_sim/mock_objects/data/led/model_670nm.fits
diff --git a/ObservationSim/MockObject/data/led/model_760nm.fits b/observation_sim/mock_objects/data/led/model_760nm.fits
similarity index 100%
rename from ObservationSim/MockObject/data/led/model_760nm.fits
rename to observation_sim/mock_objects/data/led/model_760nm.fits
diff --git a/ObservationSim/MockObject/data/led/model_940nm.fits b/observation_sim/mock_objects/data/led/model_940nm.fits
similarity index 100%
rename from ObservationSim/MockObject/data/led/model_940nm.fits
rename to observation_sim/mock_objects/data/led/model_940nm.fits
diff --git a/ObservationSim/sim_steps/__init__.py b/observation_sim/sim_steps/__init__.py
similarity index 100%
rename from ObservationSim/sim_steps/__init__.py
rename to observation_sim/sim_steps/__init__.py
diff --git a/observation_sim/sim_steps/add_LED_flat.py b/observation_sim/sim_steps/add_LED_flat.py
new file mode 100644
index 0000000000000000000000000000000000000000..76bcdbd5459fdf0eb7e41bc652acc36e48f2fcb5
--- /dev/null
+++ b/observation_sim/sim_steps/add_LED_flat.py
@@ -0,0 +1,59 @@
+import numpy as np
+from observation_sim.mock_objects import FlatLED
+import galsim
+
+from astropy.time import Time
+from datetime import datetime, timezone
+
+import gc
+
+
+def add_LED_Flat(self, chip, filt, tel, pointing, catalog, obs_param):
+
+    if not hasattr(self, 'h_ext'):
+        _, _ = self.prepare_headers(chip=chip, pointing=pointing)
+    chip_wcs = galsim.FitsWCS(header=self.h_ext)
+    pf_map = np.zeros_like(chip.img.array)
+    if obs_param["LED_TYPE"] is not None:
+        if len(obs_param["LED_TYPE"]) != 0:
+            print("LED OPEN--------")
+
+            led_obj = FlatLED(chip, filt)
+            led_flat, ledstat, letts = led_obj.drawObj_LEDFlat(
+                led_type_list=obs_param["LED_TYPE"], exp_t_list=obs_param["LED_TIME"])
+            pf_map = led_flat
+            self.updateHeaderInfo(header_flag='ext', keys=[
+                                  'LEDSTAT'], values=[ledstat])
+            self.updateHeaderInfo(header_flag='ext', keys=['LEDT01', 'LEDT02', 'LEDT03', 'LEDT04', 'LEDT05', 'LEDT06',
+                                  'LEDT07', 'LEDT08', 'LEDT09', 'LEDT10', 'LEDT11', 'LEDT12', 'LEDT13', 'LEDT14'], values=letts)
+
+    if obs_param["shutter_effect"] == True:
+        pf_map = pf_map * chip.shutter_img
+        pf_map = np.array(pf_map, dtype='float32')
+        self.updateHeaderInfo(header_flag='ext', keys=[
+                              'SHTSTAT'], values=[True])
+    else:
+        self.updateHeaderInfo(header_flag='ext', keys=['SHTSTAT', 'SHTOPEN1', 'SHTCLOS0'], values=[
+                              True, self.h_ext['SHTCLOS1'], self.h_ext['SHTOPEN0']])
+
+    chip.img = chip.img + pf_map
+
+    # renew header info
+    datetime_obs = datetime.utcfromtimestamp(pointing.timestamp)
+    datetime_obs = datetime_obs.replace(tzinfo=timezone.utc)
+    t_obs = Time(datetime_obs)
+
+    # ccd刷新2s,等待0.5s,开灯后等待0.5s,开始曝光
+    t_obs_renew = Time(t_obs.mjd - (2.) / 86400., format="mjd")
+
+    t_obs_utc = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(
+        t_obs_renew.unix).replace(tzinfo=timezone.utc).timestamp(), 1))
+    self.updateHeaderInfo(header_flag='prim', keys=[
+                          'DATE-OBS'], values=[t_obs_utc.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5]])
+
+    # dark time :
+    self.updateHeaderInfo(header_flag='ext', keys=[
+                          'DARKTIME'], values=[pointing.exp_time])
+
+    gc.collect()
+    return chip, filt, tel, pointing
diff --git a/ObservationSim/sim_steps/add_brighter_fatter_CTE.py b/observation_sim/sim_steps/add_brighter_fatter_CTE.py
similarity index 59%
rename from ObservationSim/sim_steps/add_brighter_fatter_CTE.py
rename to observation_sim/sim_steps/add_brighter_fatter_CTE.py
index ec8a31ad37f0b81199e58ddd81c3e7183bb36f1e..d235b4161f16c5da15d7e4c22f629f86fc00b5e5 100644
--- a/ObservationSim/sim_steps/add_brighter_fatter_CTE.py
+++ b/observation_sim/sim_steps/add_brighter_fatter_CTE.py
@@ -1,15 +1,17 @@
 import numpy as np
 import galsim
-from ObservationSim.Instrument.Chip import ChipUtils as chip_utils
-from ObservationSim.Instrument.Chip.libCTI.CTI_modeling import CTI_sim
+from observation_sim.instruments.chip import chip_utils
+from observation_sim.instruments.chip.libCTI.CTI_modeling import CTI_sim
+
 
 def add_brighter_fatter(self, chip, filt, tel, pointing, catalog, obs_param):
     chip.img = chip_utils.add_brighter_fatter(img=chip.img)
     return chip, filt, tel, pointing
 
+
 def apply_CTE(self, chip, filt, tel, pointing, catalog, obs_param):
     self.chip_output.Log_info("  Apply CTE Effect")
-    ### 2*8 -> 1*16 img-layout
+    # 2*8 -> 1*16 img-layout
     img = chip_utils.formatOutput(GSImage=chip.img)
     chip.nsecy = 1
     chip.nsecx = 16
@@ -20,23 +22,26 @@ def apply_CTE(self, chip, filt, tel, pointing, catalog, obs_param):
     dy = int(ny/chip.nsecy)
     newimg = galsim.Image(nx, int(ny+chip.overscan_y), init_value=0)
     for ichannel in range(16):
-        print('\n***add CTI effects: pointing-{:} chip-{:} channel-{:}***'.format(pointing.id, chip.chipID, ichannel+1))
+        print('\n***add CTI effects: pointing-{:} chip-{:} channel-{:}***'.format(
+            pointing.id, chip.chipID, ichannel+1))
         noverscan, nsp, nmax = chip.overscan_y, 3, 10
         beta, w, c = 0.478, 84700, 0
-        t = np.array([0.74, 7.7, 37],dtype=np.float32)
-        rho_trap = np.array([0.6, 1.6, 1.4],dtype=np.float32)
-        trap_seeds = np.array([0, 1000, 10000],dtype=np.int32) + ichannel + chip.chipID*16
-        release_seed = 50 + ichannel + pointing.id*30  + chip.chipID*16
-        newimg.array[:, 0+ichannel*dx:dx+ichannel*dx] = CTI_sim(img_arr[:, 0+ichannel*dx:dx+ichannel*dx],dx,dy,noverscan,nsp,nmax,beta,w,c,t,rho_trap,trap_seeds,release_seed)
+        t = np.array([0.74, 7.7, 37], dtype=np.float32)
+        rho_trap = np.array([0.6, 1.6, 1.4], dtype=np.float32)
+        trap_seeds = np.array(
+            [0, 1000, 10000], dtype=np.int32) + ichannel + chip.chipID*16
+        release_seed = 50 + ichannel + pointing.id*30 + chip.chipID*16
+        newimg.array[:, 0+ichannel*dx:dx+ichannel*dx] = CTI_sim(
+            img_arr[:, 0+ichannel*dx:dx+ichannel*dx], dx, dy, noverscan, nsp, nmax, beta, w, c, t, rho_trap, trap_seeds, release_seed)
     newimg.wcs = img.wcs
     del img
     img = newimg
 
-    ### 1*16 -> 2*8 img-layout
+    # 1*16 -> 2*8 img-layout
     chip.img = chip_utils.formatRevert(GSImage=img)
     chip.nsecy = 2
     chip.nsecx = 8
-    
+
     # [TODO] make overscan_y == 0
     chip.overscan_y = 0
-    return chip, filt, tel, pointing
\ No newline at end of file
+    return chip, filt, tel, pointing
diff --git a/ObservationSim/sim_steps/add_cosmic_rays.py b/observation_sim/sim_steps/add_cosmic_rays.py
similarity index 85%
rename from ObservationSim/sim_steps/add_cosmic_rays.py
rename to observation_sim/sim_steps/add_cosmic_rays.py
index 147fa064b2b2be157aae77848a971ba83d57dbfb..77a470a3a4630175087ad8b2871df717ac36ab1b 100644
--- a/ObservationSim/sim_steps/add_cosmic_rays.py
+++ b/observation_sim/sim_steps/add_cosmic_rays.py
@@ -1,8 +1,9 @@
-from ObservationSim.Instrument.Chip import ChipUtils as chip_utils
+from observation_sim.instruments.chip import chip_utils
+
 
 def add_cosmic_rays(self, chip, filt, tel, pointing, catalog, obs_param):
     self.chip_output.Log_info("  Adding Cosmic-Ray")
-    
+
     # Get exposure time
     if (obs_param) and ("exptime" in obs_param) and (obs_param["exptime"] is not None):
         exptime = obs_param["exptime"]
@@ -10,9 +11,9 @@ def add_cosmic_rays(self, chip, filt, tel, pointing, catalog, obs_param):
         exptime = pointing.exp_time
 
     chip.img, crmap_gsimg, cr_event_num = chip_utils.add_cosmic_rays(
-        img=chip.img, 
-        chip=chip, 
-        exptime=exptime, 
+        img=chip.img,
+        chip=chip,
+        exptime=exptime,
         seed=self.overall_config["random_seeds"]["seed_CR"]+pointing.id*30+chip.chipID)
     # Save cosmic ray image
     if (obs_param) and ("save_cosmic_img" in obs_param) and (obs_param["save_cosmic_img"] is not None):
@@ -27,4 +28,4 @@ def add_cosmic_rays(self, chip, filt, tel, pointing, catalog, obs_param):
                 project_cycle=self.overall_config["project_cycle"],
                 run_counter=self.overall_config["run_counter"]
             )
-    return chip, filt, tel, pointing
\ No newline at end of file
+    return chip, filt, tel, pointing
diff --git a/ObservationSim/sim_steps/add_objects.py b/observation_sim/sim_steps/add_objects.py
similarity index 98%
rename from ObservationSim/sim_steps/add_objects.py
rename to observation_sim/sim_steps/add_objects.py
index 1ec800106b20d2036d5e34ac41965b0d0ad830b0..d66194adcfcd9cb4907380d94a131691704d6ae0 100644
--- a/ObservationSim/sim_steps/add_objects.py
+++ b/observation_sim/sim_steps/add_objects.py
@@ -4,8 +4,8 @@ import psutil
 import traceback
 import numpy as np
 import galsim
-from ObservationSim._util import get_shear_field
-from ObservationSim.PSF import PSFGauss, FieldDistortion, PSFInterp, PSFInterpSLS
+from observation_sim._util import get_shear_field
+from observation_sim.PSF import PSFGauss, FieldDistortion, PSFInterp, PSFInterpSLS
 
 from astropy.time import Time
 from datetime import datetime, timezone
diff --git a/observation_sim/sim_steps/add_pattern_noise.py b/observation_sim/sim_steps/add_pattern_noise.py
new file mode 100644
index 0000000000000000000000000000000000000000..fc091c5c09b033583509bbec70d942ba39cd5cd3
--- /dev/null
+++ b/observation_sim/sim_steps/add_pattern_noise.py
@@ -0,0 +1,85 @@
+from numpy.random import Generator, PCG64
+from observation_sim.instruments.chip import chip_utils
+from observation_sim.instruments.chip import effects
+
+
+def apply_PRNU(self, chip, filt, tel, pointing, catalog, obs_param):
+    chip.img *= chip.prnu_img
+    if self.overall_config["output_setting"]["prnu_output"] == True:
+        chip.prnu_img.write("%s/FlatImg_PRNU_%s.fits" %
+                            (self.chip_output.subdir, str(chip.chipID).rjust(2, '0')))
+    return chip, filt, tel, pointing
+
+
+def add_poisson_and_dark(self, chip, filt, tel, pointing, catalog, obs_param):
+    # Add dark current & Poisson noise
+    # Get exposure time
+    if (obs_param) and ("exptime" in obs_param) and (obs_param["exptime"] is not None):
+        exptime = obs_param["exptime"]
+    else:
+        exptime = pointing.exp_time
+
+    if obs_param["add_dark"] == True:
+        chip.img, _ = chip_utils.add_poisson(img=chip.img,
+                                             chip=chip,
+                                             exptime=pointing.exp_time,
+                                             poisson_noise=chip.poisson_noise,
+                                             InputDark=None)
+    else:
+        chip.img, _ = chip_utils.add_poisson(img=chip.img,
+                                             chip=self,
+                                             exptime=exptime,
+                                             poisson_noise=chip.poisson_noise,
+                                             dark_noise=0.)
+    return chip, filt, tel, pointing
+
+
+def add_detector_defects(self, chip, filt, tel, pointing, catalog, obs_param):
+    # Add Hot Pixels or/and Dead Pixels
+    rgbadpix = Generator(
+        PCG64(int(self.overall_config["random_seeds"]["seed_defective"]+chip.chipID)))
+    badfraction = 5E-5*(rgbadpix.random()*0.5+0.7)
+    chip.img = effects.DefectivePixels(
+        chip.img,
+        IfHotPix=obs_param["hot_pixels"],
+        IfDeadPix=obs_param["dead_pixels"],
+        fraction=badfraction,
+        seed=self.overall_config["random_seeds"]["seed_defective"]+chip.chipID, biaslevel=0)
+    # Apply Bad columns
+    if obs_param["bad_columns"] == True:
+        chip.img = effects.BadColumns(chip.img,
+                                      seed=self.overall_config["random_seeds"]["seed_badcolumns"],
+                                      chipid=chip.chipID)
+    return chip, filt, tel, pointing
+
+
+def add_nonlinearity(self, chip, filt, tel, pointing, catalog, obs_param):
+    self.chip_output.Log_info("  Applying Non-Linearity on the chip image")
+    chip.img = effects.NonLinearity(GSImage=chip.img,
+                                    beta1=5.e-7,
+                                    beta2=0)
+    return chip, filt, tel, pointing
+
+
+def add_blooming(self, chip, filt, tel, pointing, catalog, obs_param):
+    self.chip_output.Log_info("  Applying CCD Saturation & Blooming")
+    chip.img = effects.SaturBloom(GSImage=chip.img,
+                                  nsect_x=1,
+                                  nsect_y=1,
+                                  fullwell=int(chip.full_well))
+    return chip, filt, tel, pointing
+
+
+def add_bias(self, chip, filt, tel, pointing, catalog, obs_param):
+    self.chip_output.Log_info(
+        "  Adding Bias level and 16-channel non-uniformity")
+    if obs_param["bias_16channel"] == True:
+        chip.img = effects.AddBiasNonUniform16(chip.img,
+                                               bias_level=float(
+                                                   chip.bias_level),
+                                               nsecy=chip.nsecy,
+                                               nsecx=chip.nsecx,
+                                               seed=self.overall_config["random_seeds"]["seed_biasNonUniform"]+chip.chipID)
+    elif obs_param["bias_16channel"] == False:
+        chip.img += self.bias_level
+    return chip, filt, tel, pointing
diff --git a/ObservationSim/sim_steps/add_sky_background.py b/observation_sim/sim_steps/add_sky_background.py
similarity index 55%
rename from ObservationSim/sim_steps/add_sky_background.py
rename to observation_sim/sim_steps/add_sky_background.py
index 563fad892d9d5b46f86cd5a12ab2b64dfca0308b..ab013f34b12bca3c8b88144d96bc56c548a372b4 100644
--- a/ObservationSim/sim_steps/add_sky_background.py
+++ b/observation_sim/sim_steps/add_sky_background.py
@@ -1,72 +1,79 @@
 import numpy as np
 import galsim
-from ObservationSim.Straylight import calculateSkyMap_split_g
-from ObservationSim.Instrument import FilterParam
+from observation_sim.sky_background import calculateSkyMap_split_g
+from observation_sim.instruments import FilterParam
 
 from astropy.time import Time
 from datetime import datetime, timezone
 
+
 def add_sky_background_sci(self, chip, filt, tel, pointing, catalog, obs_param):
-    
+
     # Get exposure time
     if (obs_param) and ("exptime" in obs_param) and (obs_param["exptime"] is not None):
         exptime = obs_param["exptime"]
     else:
         exptime = pointing.exp_time
-    
+
     flat_normal = np.ones_like(chip.img.array)
     if obs_param["flat_fielding"] == True:
-        flat_normal = flat_normal * chip.flat_img.array / np.mean(chip.flat_img.array)
+        flat_normal = flat_normal * chip.flat_img.array / \
+            np.mean(chip.flat_img.array)
     if obs_param["shutter_effect"] == True:
         flat_normal = flat_normal * chip.shutter_img
         flat_normal = np.array(flat_normal, dtype='float32')
-        self.updateHeaderInfo(header_flag='ext', keys = ['SHTSTAT'], values = [True])
+        self.updateHeaderInfo(header_flag='ext', keys=[
+                              'SHTSTAT'], values=[True])
     else:
-        self.updateHeaderInfo(header_flag='ext', keys = ['SHTSTAT','SHTOPEN1','SHTCLOS0'], values = [True,self.h_ext['SHTCLOS1'],self.h_ext['SHTOPEN0']])
-    
+        self.updateHeaderInfo(header_flag='ext', keys=['SHTSTAT', 'SHTOPEN1', 'SHTCLOS0'], values=[
+                              True, self.h_ext['SHTCLOS1'], self.h_ext['SHTOPEN0']])
+
     if obs_param["enable_straylight_model"]:
         # Filter.sky_background, Filter.zodical_spec will be updated
         filt.setFilterStrayLightPixel(
-            jtime = pointing.jdt,
-            sat_pos = np.array([pointing.sat_x, pointing.sat_y, pointing.sat_z]),
-            pointing_radec = np.array([pointing.ra,pointing.dec]),
-            sun_pos = np.array([pointing.sun_x, pointing.sun_y, pointing.sun_z]))
-        self.chip_output.Log_info("================================================")
-        self.chip_output.Log_info("sky background + stray light pixel flux value: %.5f"%(filt.sky_background))
-    
+            jtime=pointing.jdt,
+            sat_pos=np.array([pointing.sat_x, pointing.sat_y, pointing.sat_z]),
+            pointing_radec=np.array([pointing.ra, pointing.dec]),
+            sun_pos=np.array([pointing.sun_x, pointing.sun_y, pointing.sun_z]))
+        self.chip_output.Log_info(
+            "================================================")
+        self.chip_output.Log_info(
+            "sky background + stray light pixel flux value: %.5f" % (filt.sky_background))
+
     if chip.survey_type == "photometric":
-        sky_map = filt.getSkyNoise(exptime = exptime)
+        sky_map = filt.getSkyNoise(exptime=exptime)
         sky_map = sky_map * np.ones_like(chip.img.array) * flat_normal
         sky_map = galsim.Image(array=sky_map)
     else:
         # chip.loadSLSFLATCUBE(flat_fn='flat_cube.fits')
         sky_map = calculateSkyMap_split_g(
-                skyMap=flat_normal,
-                blueLimit=filt.blue_limit,
-                redLimit=filt.red_limit,
-                conf=chip.sls_conf,
-                pixelSize=chip.pix_scale,
-                isAlongY=0,
-                flat_cube=chip.flat_cube, 
-                zoldial_spec = filt.zodical_spec)
+            skyMap=flat_normal,
+            blueLimit=filt.blue_limit,
+            redLimit=filt.red_limit,
+            conf=chip.sls_conf,
+            pixelSize=chip.pix_scale,
+            isAlongY=0,
+            flat_cube=chip.flat_cube,
+            zoldial_spec=filt.zodical_spec)
         sky_map = (sky_map + filt.sky_background)*exptime
-    
+
     # sky_map = sky_map * tel.pupil_area * obs_param["exptime"]
     chip.img += sky_map
     return chip, filt, tel, pointing
 
+
 def add_sky_flat_calibration(self, chip, filt, tel, pointing, catalog, obs_param):
 
     if not hasattr(self, 'h_ext'):
         _, _ = self.prepare_headers(chip=chip, pointing=pointing)
-    chip_wcs = galsim.FitsWCS(header = self.h_ext)
+    chip_wcs = galsim.FitsWCS(header=self.h_ext)
 
     # Get exposure time
     if (obs_param) and ("exptime" in obs_param) and (obs_param["exptime"] is not None):
         exptime = obs_param["exptime"]
     else:
         exptime = pointing.exp_time
-    
+
     skyback_level = obs_param["flat_level"]
 
     filter_param = FilterParam()
@@ -75,27 +82,33 @@ def add_sky_flat_calibration(self, chip, filt, tel, pointing, catalog, obs_param
 
     flat_normal = np.ones_like(chip.img.array)
     if obs_param["flat_fielding"] == True:
-        flat_normal = flat_normal * chip.flat_img.array / np.mean(chip.flat_img.array)
+        flat_normal = flat_normal * chip.flat_img.array / \
+            np.mean(chip.flat_img.array)
     if obs_param["shutter_effect"] == True:
         flat_normal = flat_normal * chip.shutter_img
         flat_normal = np.array(flat_normal, dtype='float32')
-        if self.overall_config["output_setting"]["shutter_output"] == True:    # output 16-bit shutter effect image with pixel value <=65535
+        # output 16-bit shutter effect image with pixel value <=65535
+        if self.overall_config["output_setting"]["shutter_output"] == True:
             shutt_gsimg = galsim.ImageUS(chip.shutter_img*6E4)
-            shutt_gsimg.write("%s/ShutterEffect_%s_1.fits" % (self.chip_output.subdir, str(chip.chipID).rjust(2, '0')))
-        self.updateHeaderInfo(header_flag='ext', keys = ['SHTSTAT'], values = [True])
+            shutt_gsimg.write("%s/ShutterEffect_%s_1.fits" %
+                              (self.chip_output.subdir, str(chip.chipID).rjust(2, '0')))
+        self.updateHeaderInfo(header_flag='ext', keys=[
+                              'SHTSTAT'], values=[True])
     else:
-        self.updateHeaderInfo(header_flag='ext', keys = ['SHTSTAT','SHTOPEN1','SHTCLOS0'], values = [True,self.h_ext['SHTCLOS1'],self.h_ext['SHTOPEN0']])
-    
+        self.updateHeaderInfo(header_flag='ext', keys=['SHTSTAT', 'SHTOPEN1', 'SHTCLOS0'], values=[
+                              True, self.h_ext['SHTCLOS1'], self.h_ext['SHTOPEN0']])
 
     if chip.survey_type == "photometric":
-        sky_map = flat_normal * np.ones_like(chip.img.array) * norm_scaler * filter_param.param[chip.filter_type][5] / tel.pupil_area * exptime
+        sky_map = flat_normal * np.ones_like(chip.img.array) * norm_scaler * \
+            filter_param.param[chip.filter_type][5] / tel.pupil_area * exptime
     elif chip.survey_type == "spectroscopic":
         # flat_normal = np.ones_like(chip.img.array)
         if obs_param["flat_fielding"] == True:
-            
-            flat_normal = flat_normal * chip.flat_img.array / np.mean(chip.flat_img.array)
+
+            flat_normal = flat_normal * chip.flat_img.array / \
+                np.mean(chip.flat_img.array)
         if obs_param["shutter_effect"] == True:
-            
+
             flat_normal = flat_normal * chip.shutter_img
             flat_normal = np.array(flat_normal, dtype='float32')
         sky_map = calculateSkyMap_split_g(
@@ -107,36 +120,42 @@ def add_sky_flat_calibration(self, chip, filt, tel, pointing, catalog, obs_param
             isAlongY=0,
             flat_cube=chip.flat_cube)
         sky_map = sky_map * norm_scaler * exptime
-    
+
     chip.img += sky_map
     return chip, filt, tel, pointing
 
+
 def add_sky_background(self, chip, filt, tel, pointing, catalog, obs_param):
     if not hasattr(self, 'h_ext'):
         _, _ = self.prepare_headers(chip=chip, pointing=pointing)
-    chip_wcs = galsim.FitsWCS(header = self.h_ext)
+    chip_wcs = galsim.FitsWCS(header=self.h_ext)
 
     if "flat_level" not in obs_param or "flat_level_filt" not in obs_param:
-        chip, filt, tel, pointing = self.add_sky_background_sci(chip, filt, tel, pointing, catalog, obs_param)
+        chip, filt, tel, pointing = self.add_sky_background_sci(
+            chip, filt, tel, pointing, catalog, obs_param)
     else:
-        if obs_param.get('flat_level') is None or obs_param.get('flat_level_filt')is None:
-            chip, filt, tel, pointing = self.add_sky_background_sci(chip, filt, tel, pointing, catalog, obs_param)
+        if obs_param.get('flat_level') is None or obs_param.get('flat_level_filt') is None:
+            chip, filt, tel, pointing = self.add_sky_background_sci(
+                chip, filt, tel, pointing, catalog, obs_param)
         else:
-            chip, filt, tel, pointing = self.add_sky_flat_calibration(chip, filt, tel, pointing, catalog, obs_param)
+            chip, filt, tel, pointing = self.add_sky_flat_calibration(
+                chip, filt, tel, pointing, catalog, obs_param)
 
     # renew header info
     datetime_obs = datetime.utcfromtimestamp(pointing.timestamp)
     datetime_obs = datetime_obs.replace(tzinfo=timezone.utc)
     t_obs = Time(datetime_obs)
-    
-    ##ccd刷新2s,等待0.5s,开始曝光
-    t_obs_renew = Time(t_obs.mjd - (2.+0.5) / 86400., format="mjd")
 
-    t_obs_utc = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(t_obs_renew.unix).replace(tzinfo=timezone.utc).timestamp(), 1))
-    self.updateHeaderInfo(header_flag='prim', keys = ['DATE-OBS'], values = [t_obs_utc.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5]])
+    # ccd刷新2s,等待0.5s,开始曝光
+    t_obs_renew = Time(t_obs.mjd - (2.+0.5) / 86400., format="mjd")
 
-    #dark time : 曝光时间+刷新后等带时间0.5s+关闭快门时间1.5s+管快门后读出前等待0.5s
-    self.updateHeaderInfo(header_flag='ext', keys = ['DARKTIME'], values = [0.+0.0+0.0+pointing.exp_time])
+    t_obs_utc = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(
+        t_obs_renew.unix).replace(tzinfo=timezone.utc).timestamp(), 1))
+    self.updateHeaderInfo(header_flag='prim', keys=[
+                          'DATE-OBS'], values=[t_obs_utc.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5]])
 
+    # dark time : 曝光时间+刷新后等带时间0.5s+关闭快门时间1.5s+管快门后读出前等待0.5s
+    self.updateHeaderInfo(header_flag='ext', keys=['DARKTIME'], values=[
+                          0.+0.0+0.0+pointing.exp_time])
 
-    return chip, filt, tel, pointing
\ No newline at end of file
+    return chip, filt, tel, pointing
diff --git a/observation_sim/sim_steps/prepare_headers.py b/observation_sim/sim_steps/prepare_headers.py
new file mode 100644
index 0000000000000000000000000000000000000000..e8c41741710bd2c24512aa3e73a0ff7c1edf24d5
--- /dev/null
+++ b/observation_sim/sim_steps/prepare_headers.py
@@ -0,0 +1,52 @@
+from observation_sim.config.header import generatePrimaryHeader, generateExtensionHeader
+
+
+def prepare_headers(self, chip, pointing):
+    self.h_prim = generatePrimaryHeader(
+        xlen=chip.npix_x,
+        ylen=chip.npix_y,
+        pointing_id=pointing.obs_id,
+        pointing_type_code=pointing.pointing_type_code,
+        ra=pointing.ra,
+        dec=pointing.dec,
+        pixel_scale=chip.pix_scale,
+        time_pt=pointing.timestamp,
+        exptime=pointing.exp_time,
+        im_type=pointing.pointing_type,
+        sat_pos=[pointing.sat_x, pointing.sat_y, pointing.sat_z],
+        sat_vel=[pointing.sat_vx, pointing.sat_vy, pointing.sat_vz],
+        project_cycle=self.overall_config["project_cycle"],
+        run_counter=self.overall_config["run_counter"],
+        chip_name=str(chip.chipID).rjust(2, '0'))
+    self.h_ext = generateExtensionHeader(
+        chip=chip,
+        xlen=chip.npix_x,
+        ylen=chip.npix_y,
+        ra=pointing.ra,
+        dec=pointing.dec,
+        pa=pointing.img_pa.deg,
+        gain=chip.gain,
+        readout=chip.read_noise,
+        dark=chip.dark_noise,
+        saturation=90000,
+        pixel_scale=chip.pix_scale,
+        pixel_size=chip.pix_size,
+        xcen=chip.x_cen,
+        ycen=chip.y_cen,
+        extName=pointing.pointing_type,
+        timestamp=pointing.timestamp,
+        exptime=pointing.exp_time,
+        readoutTime=chip.readout_time,
+        t_shutter_open=pointing.t_shutter_open,
+        t_shutter_close=pointing.t_shutter_close)
+
+    return self.h_prim, self.h_ext
+
+
+def updateHeaderInfo(self, header_flag='prim', keys=['key'], values=[0]):
+    if header_flag == 'prim':
+        for key, value in zip(keys, values):
+            self.h_prim[key] = value
+    if header_flag == 'ext':
+        for key, value in zip(keys, values):
+            self.h_ext[key] = value
diff --git a/ObservationSim/sim_steps/readout_output.py b/observation_sim/sim_steps/readout_output.py
similarity index 57%
rename from ObservationSim/sim_steps/readout_output.py
rename to observation_sim/sim_steps/readout_output.py
index 080baeda5b20298a31bdbe0931e7f5a63d2b8161..8ef872fd6d9348f3f46491486010fa41af935c6f 100644
--- a/ObservationSim/sim_steps/readout_output.py
+++ b/observation_sim/sim_steps/readout_output.py
@@ -2,66 +2,76 @@ import os
 import galsim
 import numpy as np
 from astropy.io import fits
-from ObservationSim.Instrument.Chip import ChipUtils as chip_utils
-from ObservationSim.Instrument.Chip import Effects
+from observation_sim.instruments.chip import chip_utils
+from observation_sim.instruments.chip import effects
 
 from astropy.time import Time
 from datetime import datetime, timezone
 
+
 def add_prescan_overscan(self, chip, filt, tel, pointing, catalog, obs_param):
     self.chip_output.Log_info("Apply pre/over-scan")
     chip.img = chip_utils.AddPreScan(GSImage=chip.img,
-                                    pre1=chip.prescan_x,
-                                    pre2=chip.prescan_y,
-                                    over1=chip.overscan_x,
-                                    over2=chip.overscan_y)
+                                     pre1=chip.prescan_x,
+                                     pre2=chip.prescan_y,
+                                     over1=chip.overscan_x,
+                                     over2=chip.overscan_y)
 
     if obs_param["add_dark"] == True:
         ny = int(chip.npix_y/2)
         base_dark = (ny-1)*(chip.readout_time/ny)*chip.dark_noise
-        chip.img.array[(chip.prescan_y+ny):-(chip.prescan_y+ny),:] = base_dark
+        chip.img.array[(chip.prescan_y+ny):-(chip.prescan_y+ny), :] = base_dark
     return chip, filt, tel, pointing
 
+
 def add_readout_noise(self, chip, filt, tel, pointing, catalog, obs_param):
-    seed = int(self.overall_config["random_seeds"]["seed_readout"]) + pointing.id*30 + chip.chipID
+    seed = int(self.overall_config["random_seeds"]
+               ["seed_readout"]) + pointing.id*30 + chip.chipID
     rng_readout = galsim.BaseDeviate(seed)
-    readout_noise = galsim.GaussianNoise(rng=rng_readout, sigma=chip.read_noise)
+    readout_noise = galsim.GaussianNoise(
+        rng=rng_readout, sigma=chip.read_noise)
     chip.img.addNoise(readout_noise)
     return chip, filt, tel, pointing
 
+
 def apply_gain(self, chip, filt, tel, pointing, catalog, obs_param):
     self.chip_output.Log_info("  Applying Gain")
     if obs_param["gain_16channel"] == True:
-        chip.img, chip.gain_channel = Effects.ApplyGainNonUniform16(chip.img, 
-                                                                   gain=chip.gain, 
-                                                                   nsecy = chip.nsecy, 
-                                                                   nsecx=chip.nsecx, 
-                                                                   seed=self.overall_config["random_seeds"]["seed_gainNonUniform"]+chip.chipID)
+        chip.img, chip.gain_channel = effects.ApplyGainNonUniform16(chip.img,
+                                                                    gain=chip.gain,
+                                                                    nsecy=chip.nsecy,
+                                                                    nsecx=chip.nsecx,
+                                                                    seed=self.overall_config["random_seeds"]["seed_gainNonUniform"]+chip.chipID)
     elif obs_param["gain_16channel"] == False:
         chip.img /= chip.gain
     return chip, filt, tel, pointing
 
+
 def quantization_and_output(self, chip, filt, tel, pointing, catalog, obs_param):
 
     if not hasattr(self, 'h_ext'):
         _, _ = self.prepare_headers(chip=chip, pointing=pointing)
-        self.updateHeaderInfo(header_flag='ext', keys = ['SHTSTAT','SHTOPEN1','SHTCLOS0','SHTCLOS1','EXPTIME'], values = [False,self.h_ext['SHTOPEN0'],self.h_ext['SHTOPEN0'],self.h_ext['SHTOPEN0'],0.0])
+        self.updateHeaderInfo(header_flag='ext', keys=['SHTSTAT', 'SHTOPEN1', 'SHTCLOS0', 'SHTCLOS1', 'EXPTIME'], values=[
+                              False, self.h_ext['SHTOPEN0'], self.h_ext['SHTOPEN0'], self.h_ext['SHTOPEN0'], 0.0])
         # renew header info
         datetime_obs = datetime.utcfromtimestamp(pointing.timestamp)
         datetime_obs = datetime_obs.replace(tzinfo=timezone.utc)
         t_obs = Time(datetime_obs)
-    
-        ##ccd刷新2s,等待0.5s,开灯后等待0.5s,开始曝光
+
+        # ccd刷新2s,等待0.5s,开灯后等待0.5s,开始曝光
         t_obs_renew = Time(t_obs.mjd - 2. / 86400., format="mjd")
 
-        t_obs_utc = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(t_obs_renew.unix).replace(tzinfo=timezone.utc).timestamp(), 1))
-        self.updateHeaderInfo(header_flag='prim', keys = ['DATE-OBS'], values = [t_obs_utc.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5]])
-    
+        t_obs_utc = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(
+            t_obs_renew.unix).replace(tzinfo=timezone.utc).timestamp(), 1))
+        self.updateHeaderInfo(header_flag='prim', keys=[
+                              'DATE-OBS'], values=[t_obs_utc.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5]])
+
     gains1 = list(chip.gain_channel[0:8])
     gains2 = list(chip.gain_channel[8:])
     gains2.reverse()
-    gains = np.append(gains1,gains2)
-    self.updateHeaderInfo(header_flag='ext', keys = ['GAIN01','GAIN02','GAIN03','GAIN04','GAIN05','GAIN06','GAIN07','GAIN08','GAIN09','GAIN10','GAIN11','GAIN12','GAIN13','GAIN14','GAIN15','GAIN16'], values = gains)
+    gains = np.append(gains1, gains2)
+    self.updateHeaderInfo(header_flag='ext', keys=['GAIN01', 'GAIN02', 'GAIN03', 'GAIN04', 'GAIN05', 'GAIN06', 'GAIN07',
+                          'GAIN08', 'GAIN09', 'GAIN10', 'GAIN11', 'GAIN12', 'GAIN13', 'GAIN14', 'GAIN15', 'GAIN16'], values=gains)
 
     if obs_param["format_output"] == True:
         self.chip_output.Log_info("  Apply 1*16 format")
@@ -73,20 +83,21 @@ def quantization_and_output(self, chip, filt, tel, pointing, catalog, obs_param)
     chip.img.replaceNegative(replace_value=0)
     chip.img.quantize()
     chip.img = galsim.Image(chip.img.array, dtype=np.uint16)
-    fname = os.path.join(self.chip_output.subdir, self.h_prim['FILENAME'] + '.fits')
+    fname = os.path.join(self.chip_output.subdir,
+                         self.h_prim['FILENAME'] + '.fits')
 
     f_name_size = 68
-    if(len(self.h_prim['FILENAME'])>f_name_size):
-        self.updateHeaderInfo(header_flag='prim', keys = ['FILENAME'], values = [self.h_prim['FILENAME'][0:f_name_size]])
-        
-    
-    
+    if (len(self.h_prim['FILENAME']) > f_name_size):
+        self.updateHeaderInfo(header_flag='prim', keys=['FILENAME'], values=[
+                              self.h_prim['FILENAME'][0:f_name_size]])
+
     hdu1 = fits.PrimaryHDU(header=self.h_prim)
- 
-    self.updateHeaderInfo(header_flag='ext', keys = ['DATASECT'], values = [str(chip.img.array.shape[1]) + 'x' + str(chip.img.array.shape[0])])
+
+    self.updateHeaderInfo(header_flag='ext', keys=['DATASECT'], values=[
+                          str(chip.img.array.shape[1]) + 'x' + str(chip.img.array.shape[0])])
     hdu2 = fits.ImageHDU(chip.img.array, header=self.h_ext)
     hdu2.header.comments["XTENSION"] = "image extension"
-    
+
     hdu = fits.HDUList([hdu1, hdu2])
     hdu[0].add_datasum(when='data unit checksum')
     hdu[0].add_checksum(when='HDU checksum', override_datasum=True)
diff --git a/ObservationSim/Straylight/SkybackgroundMap.py b/observation_sim/sky_background/SkybackgroundMap.py
similarity index 78%
rename from ObservationSim/Straylight/SkybackgroundMap.py
rename to observation_sim/sky_background/SkybackgroundMap.py
index 2b4e204bf77d5f2783bc193e08dccf66042646b5..1532784be4382ceb057c086b587d60fdbd46547e 100644
--- a/ObservationSim/Straylight/SkybackgroundMap.py
+++ b/observation_sim/sky_background/SkybackgroundMap.py
@@ -1,5 +1,5 @@
-from ObservationSim.MockObject.SpecDisperser import SpecDisperser
-from ObservationSim.MockObject.SpecDisperser import rotate90
+from observation_sim.mock_objects.SpecDisperser import SpecDisperser
+from observation_sim.mock_objects.SpecDisperser import rotate90
 
 import galsim
 import numpy as np
@@ -20,10 +20,10 @@ except ImportError:
     import importlib_resources as pkg_resources
 
 
-###calculate sky map by sky SED
+# calculate sky map by sky SED
 
 def calculateSkyMap_split_g(skyMap=None, blueLimit=4200, redLimit=6500, skyfn='sky_emiss_hubble_50_50_A.dat', conf=[''], pixelSize=0.074, isAlongY=0,
-                            split_pos=3685, flat_cube = None, zoldial_spec = None):
+                            split_pos=3685, flat_cube=None, zoldial_spec=None):
     # skyMap = np.ones([yLen, xLen], dtype='float32')
     #
     # if isAlongY == 1:
@@ -45,19 +45,21 @@ def calculateSkyMap_split_g(skyMap=None, blueLimit=4200, redLimit=6500, skyfn='s
 
     fImg = galsim.Image(fimg)
     try:
-        with pkg_resources.files('ObservationSim.Straylight.data.sky').joinpath(skyfn) as data_path:
+        with pkg_resources.files('observation_sim.sky_background.data.sky').joinpath(skyfn) as data_path:
             skySpec = np.loadtxt(data_path)
     except AttributeError:
-        with pkg_resources.path('ObservationSim.Straylight.data.sky', skyfn) as data_path:
+        with pkg_resources.path('observation_sim.sky_background.data.sky', skyfn) as data_path:
             skySpec = np.loadtxt(data_path)
     # skySpec = np.loadtxt(skyfn)
-    spec = Table(np.array([skySpec[:, 0], skySpec[:, 1]]).T, names=('WAVELENGTH', 'FLUX'))
+    spec = Table(np.array([skySpec[:, 0], skySpec[:, 1]]
+                          ).T, names=('WAVELENGTH', 'FLUX'))
 
     if zoldial_spec is not None:
         deltL = 0.5
         lamb = np.arange(2000, 11000, deltL)
 
-        speci = interpolate.interp1d(zoldial_spec['WAVELENGTH'], zoldial_spec['FLUX'])
+        speci = interpolate.interp1d(
+            zoldial_spec['WAVELENGTH'], zoldial_spec['FLUX'])
 
         y = speci(lamb)
         # erg/s/cm2/A --> photo/s/m2/A
@@ -65,7 +67,7 @@ def calculateSkyMap_split_g(skyMap=None, blueLimit=4200, redLimit=6500, skyfn='s
         spec = Table(np.array([lamb, s_flux]).T, names=('WAVELENGTH', 'FLUX'))
     if isAlongY == 0:
         directParm = 0
-    if isAlongY ==1:
+    if isAlongY == 1:
         directParm = 1
 
     if split_pos >= skyImg.array.shape[directParm]:
@@ -90,25 +92,26 @@ def calculateSkyMap_split_g(skyMap=None, blueLimit=4200, redLimit=6500, skyfn='s
         sub_x_end_arr = sub_x_start_arr + delt_x
         sub_x_end_arr[-1] = min(sub_x_end_arr[-1], x_len)
 
-        for i,k1 in enumerate(sub_y_start_arr):
+        for i, k1 in enumerate(sub_y_start_arr):
             sub_y_s = k1
             sub_y_e = sub_y_end_arr[i]
 
             sub_y_center = (sub_y_s+sub_y_e)/2.
 
-            for j,k2 in enumerate(sub_x_start_arr):
+            for j, k2 in enumerate(sub_x_start_arr):
                 sub_x_s = k2
                 sub_x_e = sub_x_end_arr[j]
 
-                skyImg_sub = galsim.Image(skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e])
+                skyImg_sub = galsim.Image(
+                    skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e])
                 origin_sub = [sub_y_s, sub_x_s]
                 sub_x_center = (sub_x_s + sub_x_e) / 2.
 
                 sdp = SpecDisperser(orig_img=skyImg_sub, xcenter=sub_x_center, ycenter=sub_y_center, origin=origin_sub,
-                                tar_spec=spec,
-                                band_start=tbstart, band_end=tbend,
-                                conf=conf2,
-                                flat_cube=flat_cube, ignoreBeam=['D','E'])
+                                    tar_spec=spec,
+                                    band_start=tbstart, band_end=tbend,
+                                    conf=conf2,
+                                    flat_cube=flat_cube, ignoreBeam=['D', 'E'])
 
                 spec_orders = sdp.compute_spec_orders()
 
@@ -141,9 +144,7 @@ def calculateSkyMap_split_g(skyMap=None, blueLimit=4200, redLimit=6500, skyfn='s
         #     if bounds.area() == 0:
         #         continue
         #     fImg[bounds] = fImg[bounds] + ssImg[bounds]
-        
 
-        
     else:
 
         # skyImg1 = galsim.Image(skyImg.array[:, 0:split_pos])
@@ -165,32 +166,33 @@ def calculateSkyMap_split_g(skyMap=None, blueLimit=4200, redLimit=6500, skyfn='s
         sub_y_start_arr = np.arange(0, y_len, delt_y)
         sub_y_end_arr = sub_y_start_arr + delt_y
         sub_y_end_arr[-1] = min(sub_y_end_arr[-1], y_len)
-        
+
         delt_x = split_pos-0
         sub_x_start_arr = np.arange(0, split_pos, delt_x)
         sub_x_end_arr = sub_x_start_arr + delt_x
         sub_x_end_arr[-1] = min(sub_x_end_arr[-1], split_pos)
 
-        for i,k1 in enumerate(sub_y_start_arr):
+        for i, k1 in enumerate(sub_y_start_arr):
             sub_y_s = k1
             sub_y_e = sub_y_end_arr[i]
 
             sub_y_center = (sub_y_s+sub_y_e)/2.
 
-            for j,k2 in enumerate(sub_x_start_arr):
+            for j, k2 in enumerate(sub_x_start_arr):
                 sub_x_s = k2
                 sub_x_e = sub_x_end_arr[j]
                 # print(i,j,sub_y_s, sub_y_e,sub_x_s,sub_x_e)
                 T1 = time.time()
-                skyImg_sub = galsim.Image(skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e])
+                skyImg_sub = galsim.Image(
+                    skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e])
                 origin_sub = [sub_y_s, sub_x_s]
                 sub_x_center = (sub_x_s + sub_x_e) / 2.
 
                 sdp = SpecDisperser(orig_img=skyImg_sub, xcenter=sub_x_center, ycenter=sub_y_center, origin=origin_sub,
-                                tar_spec=spec,
-                                band_start=tbstart, band_end=tbend,
-                                conf=conf1,
-                                flat_cube=flat_cube)
+                                    tar_spec=spec,
+                                    band_start=tbstart, band_end=tbend,
+                                    conf=conf1,
+                                    flat_cube=flat_cube)
 
                 spec_orders = sdp.compute_spec_orders()
 
@@ -204,10 +206,10 @@ def calculateSkyMap_split_g(skyMap=None, blueLimit=4200, redLimit=6500, skyfn='s
                     if bounds.area() == 0:
                         continue
                     fImg[bounds] = fImg[bounds] + ssImg[bounds]
-        
+
                 T2 = time.time()
 
-                print('time: %s ms'% ((T2 - T1)*1000))
+                print('time: %s ms' % ((T2 - T1)*1000))
 
         delt_x = x_len-split_pos
         sub_x_start_arr = np.arange(split_pos, x_len, delt_x)
@@ -224,18 +226,19 @@ def calculateSkyMap_split_g(skyMap=None, blueLimit=4200, redLimit=6500, skyfn='s
                 sub_x_s = k2
                 sub_x_e = sub_x_end_arr[j]
                 # print(i,j,sub_y_s, sub_y_e,sub_x_s,sub_x_e)
-                
+
                 T1 = time.time()
 
-                skyImg_sub = galsim.Image(skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e])
+                skyImg_sub = galsim.Image(
+                    skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e])
                 origin_sub = [sub_y_s, sub_x_s]
                 sub_x_center = (sub_x_s + sub_x_e) / 2.
 
                 sdp = SpecDisperser(orig_img=skyImg_sub, xcenter=sub_x_center, ycenter=sub_y_center, origin=origin_sub,
-                                tar_spec=spec,
-                                band_start=tbstart, band_end=tbend,
-                                conf=conf2,
-                                flat_cube=flat_cube)
+                                    tar_spec=spec,
+                                    band_start=tbstart, band_end=tbend,
+                                    conf=conf2,
+                                    flat_cube=flat_cube)
 
                 spec_orders = sdp.compute_spec_orders()
 
@@ -251,17 +254,19 @@ def calculateSkyMap_split_g(skyMap=None, blueLimit=4200, redLimit=6500, skyfn='s
                     fImg[bounds] = fImg[bounds] + ssImg[bounds]
                 T2 = time.time()
 
-                print('time: %s ms'% ((T2 - T1)*1000))
+                print('time: %s ms' % ((T2 - T1)*1000))
 
     if isAlongY == 1:
-        fimg, tmx, tmy = rotate90(array_orig=fImg.array, xc=0, yc=0, isClockwise=0)
+        fimg, tmx, tmy = rotate90(
+            array_orig=fImg.array, xc=0, yc=0, isClockwise=0)
     else:
         fimg = fImg.array
 
     fimg = fimg * pixelSize * pixelSize
 
     return fimg
-    
+
+
 def calculateSkyMap(xLen=9232, yLen=9126, blueLimit=4200, redLimit=6500,
                     skyfn='sky_emiss_hubble_50_50_A.dat', conf='', pixelSize=0.074, isAlongY=0):
     skyMap = np.ones([yLen, xLen], dtype='float32')
@@ -277,14 +282,15 @@ def calculateSkyMap(xLen=9232, yLen=9126, blueLimit=4200, redLimit=6500,
     fimg = np.zeros_like(skyMap)
     fImg = galsim.Image(fimg)
     try:
-        with pkg_resources.files('ObservationSim.Straylight.data.sky').joinpath(skyfn) as data_path:
+        with pkg_resources.files('observation_sim.sky_background.data.sky').joinpath(skyfn) as data_path:
             skySpec = np.loadtxt(data_path)
     except AttributeError:
-        with pkg_resources.path('ObservationSim.Straylight.data.sky', skyfn) as data_path:
+        with pkg_resources.path('observation_sim.sky_background.data.sky', skyfn) as data_path:
             skySpec = np.loadtxt(data_path)
     # skySpec = np.loadtxt(skyfn)
-    
-    spec = Table(np.array([skySpec[:, 0], skySpec[:, 1]]).T, names=('WAVELENGTH', 'FLUX'))
+
+    spec = Table(np.array([skySpec[:, 0], skySpec[:, 1]]
+                          ).T, names=('WAVELENGTH', 'FLUX'))
 
     sdp = SpecDisperser(orig_img=skyImg, xcenter=skyImg.center.x, ycenter=skyImg.center.y, origin=[1, 1],
                         tar_spec=spec,
@@ -303,10 +309,11 @@ def calculateSkyMap(xLen=9232, yLen=9126, blueLimit=4200, redLimit=6500,
         fImg[bounds] = fImg[bounds] + ssImg[bounds]
 
     if isAlongY == 1:
-        fimg, tmx, tmy = rotate90(array_orig=fImg.array, xc=0, yc=0, isClockwise=0)
+        fimg, tmx, tmy = rotate90(
+            array_orig=fImg.array, xc=0, yc=0, isClockwise=0)
     else:
         fimg = fImg.array
-        
+
     fimg = fimg * pixelSize * pixelSize
 
     return fimg
diff --git a/ObservationSim/Straylight/Straylight.py b/observation_sim/sky_background/Straylight.py
similarity index 55%
rename from ObservationSim/Straylight/Straylight.py
rename to observation_sim/sky_background/Straylight.py
index 189fe40f79a9f4c2bf1a29386c56db9138ba9f05..d461e79424707b7fea424f0ca24627fce03f7a14 100644
--- a/ObservationSim/Straylight/Straylight.py
+++ b/observation_sim/sky_background/Straylight.py
@@ -15,270 +15,291 @@ except ImportError:
     # Try backported to PY<37 'importlib_resources'
     import importlib_resources as pkg_resources
 
-filterPivotWave = {'nuv':2875.5,'u':3629.6,'g':4808.4,'r':6178.2, 'i':7609.0, 'z':9012.9,'y':9627.9}
-filterIndex = {'nuv':0,'u':1,'g':2,'r':3, 'i':4, 'z':5,'y':6}
-filterCCD = {'nuv':'UV0','u':'UV0','g':'Astro_MB','r':'Astro_MB', 'i':'Basic_NIR', 'z':'Basic_NIR','y':'Basic_NIR'}
-bandRange = {'nuv':[2504.0,3230.0],'u':[3190.0,4039.0],'g':[3989.0,5498.0],'r':[5438.0,6956.0], 'i':[6886.0,8469.0], 'z':[8379.0,10855.0],'y':[9217.0, 10900.0], 'GU':[2550, 4000],'GV':[4000, 6200],'GI':[6200,10000]}
+filterPivotWave = {'nuv': 2875.5, 'u': 3629.6, 'g': 4808.4,
+                   'r': 6178.2, 'i': 7609.0, 'z': 9012.9, 'y': 9627.9}
+filterIndex = {'nuv': 0, 'u': 1, 'g': 2, 'r': 3, 'i': 4, 'z': 5, 'y': 6}
+filterCCD = {'nuv': 'UV0', 'u': 'UV0', 'g': 'Astro_MB',
+             'r': 'Astro_MB', 'i': 'Basic_NIR', 'z': 'Basic_NIR', 'y': 'Basic_NIR'}
+bandRange = {'nuv': [2504.0, 3230.0], 'u': [3190.0, 4039.0], 'g': [3989.0, 5498.0], 'r': [5438.0, 6956.0], 'i': [
+    6886.0, 8469.0], 'z': [8379.0, 10855.0], 'y': [9217.0, 10900.0], 'GU': [2550, 4000], 'GV': [4000, 6200], 'GI': [6200, 10000]}
 # Instrument_dir = '/Users/zhangxin/Work/SlitlessSim/CSST_SIM/CSST_C6/straylight/straylight/Instrument/'
-SpecOrder = ['-2','-1','0','1','2']
+SpecOrder = ['-2', '-1', '0', '1', '2']
+
+filterMirrorEff = {'nuv': 0.54, 'u': 0.68, 'g': 0.8,
+                   'r': 0.8, 'i': 0.8, 'z': 0.8, 'y': 0.8}
 
-filterMirrorEff = {'nuv':0.54,'u':0.68,'g':0.8,'r':0.8, 'i':0.8, 'z':0.8,'y':0.8}
 
 def transRaDec2D(ra, dec):
-    x1 = np.cos(dec / 57.2957795) * np.cos(ra / 57.2957795);
-    y1 = np.cos(dec / 57.2957795) * np.sin(ra / 57.2957795);
-    z1 = np.sin(dec / 57.2957795);
+    x1 = np.cos(dec / 57.2957795) * np.cos(ra / 57.2957795)
+    y1 = np.cos(dec / 57.2957795) * np.sin(ra / 57.2957795)
+    z1 = np.sin(dec / 57.2957795)
     return np.array([x1, y1, z1])
 
-def getAngle132(x1 = 0, y1 = 0, z1 = 0, x2 = 0, y2 = 0, z2 = 0, x3 = 0, y3 = 0, z3 = 0):
-	
-	cosValue = 0;
-	angle = 0;
-	
-	x11 = x1-x3;
-	y11 = y1-y3;
-	z11 = z1-z3;
-	
-	x22 = x2-x3;
-	y22 = y2-y3;
-	z22 = z2-z3;
-	
-	tt = np.sqrt((x11*x11 + y11*y11 + z11* z11) * (x22*x22 + y22*y22 + z22*z22));
-	if(tt==0):
-		return 0;
-
-	cosValue = (x11*x22+y11*y22+z11*z22)/tt;
-
-	if (cosValue > 1):
-		cosValue = 1;
-	if (cosValue < -1):
-		cosValue = -1;
-	angle = math.acos(cosValue);
-	return angle * 360 / (2 * math.pi);
-
-def calculateAnglePwithEarth(sat = np.array([0,0,0]), pointing = np.array([0,0,0]), sun = np.array([0,0,0])):
+
+def getAngle132(x1=0, y1=0, z1=0, x2=0, y2=0, z2=0, x3=0, y3=0, z3=0):
+
+    cosValue = 0
+    angle = 0
+
+    x11 = x1-x3
+    y11 = y1-y3
+    z11 = z1-z3
+
+    x22 = x2-x3
+    y22 = y2-y3
+    z22 = z2-z3
+
+    tt = np.sqrt((x11*x11 + y11*y11 + z11 * z11)
+                 * (x22*x22 + y22*y22 + z22*z22))
+    if (tt == 0):
+        return 0
+
+    cosValue = (x11*x22+y11*y22+z11*z22)/tt
+
+    if (cosValue > 1):
+        cosValue = 1
+    if (cosValue < -1):
+        cosValue = -1
+    angle = math.acos(cosValue)
+    return angle * 360 / (2 * math.pi)
+
+
+def calculateAnglePwithEarth(sat=np.array([0, 0, 0]), pointing=np.array([0, 0, 0]), sun=np.array([0, 0, 0])):
     modSat = np.sqrt(sat[0]*sat[0] + sat[1]*sat[1]+sat[2]*sat[2])
-    modPoint = np.sqrt(pointing[0]*pointing[0] + pointing[1]*pointing[1] + pointing[2]*pointing[2])
-    withLocalZenithAngle = (pointing[0] * sat[0] + pointing[1] * sat[1] + pointing[2] * sat[2]) / (modPoint*modSat)
+    modPoint = np.sqrt(pointing[0]*pointing[0] +
+                       pointing[1]*pointing[1] + pointing[2]*pointing[2])
+    withLocalZenithAngle = (
+        pointing[0] * sat[0] + pointing[1] * sat[1] + pointing[2] * sat[2]) / (modPoint*modSat)
 
     innerM_sat_sun = sat[0] * sun[0] + sat[1] * sun[1] + sat[2] * sun[2]
     cosAngle = innerM_sat_sun / (modSat * cons.au.value/1000)
     isInSunSide = 1
-    if (cosAngle < -0.3385737): #cos109.79
-        isInSunSide = -1;
+    if (cosAngle < -0.3385737):  # cos109.79
+        isInSunSide = -1
     elif cosAngle >= -0.3385737 and cosAngle <= 0.3385737:
-        isInSunSide = 0;
+        isInSunSide = 0
 
-    return math.acos(withLocalZenithAngle)*180/math.pi,isInSunSide
+    return math.acos(withLocalZenithAngle)*180/math.pi, isInSunSide
 
 
 # /**
 #  * *eCoor = ra, *eCoor+1 = dec
 #  */
-def Cartesian2Equatorial(carCoor = np.array([0,0,0])):
+def Cartesian2Equatorial(carCoor=np.array([0, 0, 0])):
     eCoor = np.zeros(2)
     if (carCoor[0] > 0 and carCoor[1] >= 0):
         eCoor[0] = math.atan(carCoor[1] / carCoor[0]) * 360 / (2 * math.pi)
     elif (carCoor[0] < 0):
-        eCoor[0] = (math.atan(carCoor[1] / carCoor[0]) + math.pi) * 360 / (2 * math.pi)
+        eCoor[0] = (math.atan(carCoor[1] / carCoor[0]) +
+                    math.pi) * 360 / (2 * math.pi)
     elif (carCoor[0] > 0 and carCoor[1] < 0):
-        eCoor[0] = (math.atan(carCoor[1] / carCoor[0]) + 2 * math.pi) * 360 / (2 * math.pi)
+        eCoor[0] = (math.atan(carCoor[1] / carCoor[0]) +
+                    2 * math.pi) * 360 / (2 * math.pi)
     elif (carCoor[0] == 0 and carCoor[1] < 0):
         eCoor[0] = 270
     elif (carCoor[0] == 0 and carCoor[1] > 0):
         eCoor[0] = 90
-    eCoor[1] = math.atan(carCoor[2] / np.sqrt(carCoor[0] * carCoor[0] + carCoor[1] * carCoor[1])) * 360 / (2 * math.pi)
+    eCoor[1] = math.atan(carCoor[2] / np.sqrt(carCoor[0] *
+                         carCoor[0] + carCoor[1] * carCoor[1])) * 360 / (2 * math.pi)
     return eCoor
 
-    
 
 class Straylight(object):
-    def __init__(self, jtime = 2460843., sat_pos = np.array([0,0,0]), pointing_radec = np.array([0,0]), sun_pos = np.array([0,0,0])):
+    def __init__(self, jtime=2460843., sat_pos=np.array([0, 0, 0]), pointing_radec=np.array([0, 0]), sun_pos=np.array([0, 0, 0])):
         self.jtime = jtime
         self.sat = sat_pos
         self.sun_pos = sun_pos
-        self.equator = coord.SkyCoord(pointing_radec[0]*u.degree, pointing_radec[1]*u.degree,frame='icrs')
+        self.equator = coord.SkyCoord(
+            pointing_radec[0]*u.degree, pointing_radec[1]*u.degree, frame='icrs')
         self.ecliptic = self.equator.transform_to('barycentrictrueecliptic')
         self.pointing = transRaDec2D(pointing_radec[0], pointing_radec[1])
         platForm = sys.platform
         if platForm == 'darwin':
             try:
-                with pkg_resources.files('ObservationSim.Straylight.lib').joinpath('libstraylight.dylib') as dllFn:
+                with pkg_resources.files('observation_sim.sky_background.lib').joinpath('libstraylight.dylib') as dllFn:
                     self.slcdll = ctypes.CDLL(dllFn)
             except AttributeError:
-                with pkg_resources.path('ObservationSim.Straylight.lib', 'libstraylight.dylib') as dllFn:
+                with pkg_resources.path('observation_sim.sky_background.lib', 'libstraylight.dylib') as dllFn:
                     self.slcdll = ctypes.CDLL(dllFn)
         elif platForm == 'linux':
             try:
-                with pkg_resources.files('ObservationSim.Straylight.lib').joinpath('libstraylight.so') as dllFn:
+                with pkg_resources.files('observation_sim.sky_background.lib').joinpath('libstraylight.so') as dllFn:
                     self.slcdll = ctypes.CDLL(dllFn)
             except AttributeError:
-                with pkg_resources.path('ObservationSim.Straylight.lib', 'libstraylight.so') as dllFn:
+                with pkg_resources.path('observation_sim.sky_background.lib', 'libstraylight.so') as dllFn:
                     self.slcdll = ctypes.CDLL(dllFn)
         # self.slcdll=ctypes.CDLL('./libstraylight.dylib')
         self.slcdll.Calculate.argtypes = [ctypes.c_double, ctypes.POINTER(ctypes.c_double),
-                                          ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double),
+                                          ctypes.POINTER(ctypes.c_double), ctypes.POINTER(
+                                              ctypes.c_double),
                                           ctypes.POINTER(ctypes.c_double), ctypes.c_char_p]
 
         self.slcdll.PointSource.argtypes = [ctypes.c_double, ctypes.POINTER(ctypes.c_double),
-                                            ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double),
+                                            ctypes.POINTER(ctypes.c_double), ctypes.POINTER(
+                                                ctypes.c_double),
                                             ctypes.POINTER(ctypes.c_double), ctypes.c_char_p]
 
         self.slcdll.EarthShine.argtypes = [ctypes.c_double, ctypes.POINTER(ctypes.c_double),
-                                           ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double),
+                                           ctypes.POINTER(ctypes.c_double), ctypes.POINTER(
+                                               ctypes.c_double),
                                            ctypes.POINTER(ctypes.c_double)]
 
         self.slcdll.Zodiacal.argtypes = [ctypes.c_double, ctypes.POINTER(ctypes.c_double),
                                          ctypes.POINTER(ctypes.c_double)]
         self.slcdll.ComposeY.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double),
                                          ctypes.POINTER(ctypes.c_double)]
-        self.slcdll.Init.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p]
+        self.slcdll.Init.argtypes = [
+            ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p]
         try:
-            with pkg_resources.files('ObservationSim.Straylight.lib').joinpath('DE405') as tFn:
+            with pkg_resources.files('observation_sim.sky_background.lib').joinpath('DE405') as tFn:
                 self.deFn = tFn.as_uri()[7:]
         except AttributeError:
-            with pkg_resources.path('ObservationSim.Straylight.lib', 'DE405') as tFn:
+            with pkg_resources.path('observation_sim.sky_background.lib', 'DE405') as tFn:
                 self.deFn = tFn.as_uri()[7:]
 
         try:
-            with pkg_resources.files('ObservationSim.Straylight.lib').joinpath('PST') as tFn:
+            with pkg_resources.files('observation_sim.sky_background.lib').joinpath('PST') as tFn:
                 self.PSTFn = tFn.as_uri()[7:]
         except AttributeError:
-            with pkg_resources.path('ObservationSim.Straylight.lib', 'PST') as tFn:
+            with pkg_resources.path('observation_sim.sky_background.lib', 'PST') as tFn:
                 self.PSTFn = tFn.as_uri()[7:]
 
         try:
-            with pkg_resources.files('ObservationSim.Straylight.lib').joinpath('R') as tFn:
+            with pkg_resources.files('observation_sim.sky_background.lib').joinpath('R') as tFn:
                 self.RFn = tFn.as_uri()[7:]
         except AttributeError:
-            with pkg_resources.path('ObservationSim.Straylight.lib', 'R') as tFn:
+            with pkg_resources.path('observation_sim.sky_background.lib', 'R') as tFn:
                 self.RFn = tFn.as_uri()[7:]
 
         try:
-            with pkg_resources.files('ObservationSim.Straylight.lib').joinpath('Zodiacal') as tFn:
+            with pkg_resources.files('observation_sim.sky_background.lib').joinpath('Zodiacal') as tFn:
                 self.ZolFn = tFn.as_uri()[7:]
         except AttributeError:
-            with pkg_resources.path('ObservationSim.Straylight.lib', 'Zodiacal') as tFn:
+            with pkg_resources.path('observation_sim.sky_background.lib', 'Zodiacal') as tFn:
                 self.ZolFn = tFn.as_uri()[7:]
 
         try:
-            with pkg_resources.files('ObservationSim.Straylight.lib').joinpath('BrightGaia_with_csst_mag') as tFn:
+            with pkg_resources.files('observation_sim.sky_background.lib').joinpath('BrightGaia_with_csst_mag') as tFn:
                 self.brightStarTabFn = tFn.as_uri()[7:]
         except AttributeError:
-            with pkg_resources.path('ObservationSim.Straylight.lib', 'BrightGaia_with_csst_mag') as tFn:
+            with pkg_resources.path('observation_sim.sky_background.lib', 'BrightGaia_with_csst_mag') as tFn:
                 self.brightStarTabFn = tFn.as_uri()[7:]
         print(self.deFn)
-        self.slcdll.Init(str.encode(self.deFn), str.encode(self.PSTFn), str.encode(self.RFn), str.encode(self.ZolFn))
+        self.slcdll.Init(str.encode(self.deFn), str.encode(
+            self.PSTFn), str.encode(self.RFn), str.encode(self.ZolFn))
 
-    def getFilterAndCCD_Q(self, filter = 'i'):
+    def getFilterAndCCD_Q(self, filter='i'):
         try:
-            with pkg_resources.files('ObservationSim.Instrument.data.ccd').joinpath(filterCCD[filter] + '.txt') as ccd_fn:
+            with pkg_resources.files('observation_sim.instruments.data.ccd').joinpath(filterCCD[filter] + '.txt') as ccd_fn:
                 q_ccd_f = np.loadtxt(ccd_fn)
         except AttributeError:
-            with pkg_resources.path('ObservationSim.Instrument.data.ccd', filterCCD[filter] + '.txt') as ccd_fn:
+            with pkg_resources.path('observation_sim.instruments.data.ccd', filterCCD[filter] + '.txt') as ccd_fn:
                 q_ccd_f = np.loadtxt(ccd_fn)
 
         try:
-            with pkg_resources.files('ObservationSim.Instrument.data.filters').joinpath(filter + '.txt') as filter_fn:
+            with pkg_resources.files('observation_sim.instruments.data.filters').joinpath(filter + '.txt') as filter_fn:
                 q_fil_f = np.loadtxt(filter_fn)
         except AttributeError:
-            with pkg_resources.path('ObservationSim.Instrument.data.filters', filter + '.txt') as filter_fn:
+            with pkg_resources.path('observation_sim.instruments.data.filters', filter + '.txt') as filter_fn:
                 q_fil_f = np.loadtxt(filter_fn)
 
         band_s = 2000
         band_e = 11000
 
-        q_ccd_f[:,0] = q_ccd_f[:,0]*10
-        q_ccd = np.zeros([q_ccd_f.shape[0]+2,q_ccd_f.shape[1]])
-        q_ccd[1:-1,:] = q_ccd_f
-        q_ccd[0] = [band_s,0]
-        q_ccd[-1] = [band_e,0]
-
-        q_fil = np.zeros([q_fil_f.shape[0]+2,q_fil_f.shape[1]])
-        q_fil[1:-1,:] = q_fil_f
-        q_fil[0] = [band_s,0]
-        q_fil[-1] = [band_e,0]
-
-        
-        q_fil_i = interpolate.interp1d(q_fil[:,0], q_fil[:,1])
-        q_ccd_i = interpolate.interp1d(q_ccd[:,0], q_ccd[:,1])
-        bands = np.arange(bandRange[filter][0], bandRange[filter][1],0.5)
+        q_ccd_f[:, 0] = q_ccd_f[:, 0]*10
+        q_ccd = np.zeros([q_ccd_f.shape[0]+2, q_ccd_f.shape[1]])
+        q_ccd[1:-1, :] = q_ccd_f
+        q_ccd[0] = [band_s, 0]
+        q_ccd[-1] = [band_e, 0]
+
+        q_fil = np.zeros([q_fil_f.shape[0]+2, q_fil_f.shape[1]])
+        q_fil[1:-1, :] = q_fil_f
+        q_fil[0] = [band_s, 0]
+        q_fil[-1] = [band_e, 0]
+
+        q_fil_i = interpolate.interp1d(q_fil[:, 0], q_fil[:, 1])
+        q_ccd_i = interpolate.interp1d(q_ccd[:, 0], q_ccd[:, 1])
+        bands = np.arange(bandRange[filter][0], bandRange[filter][1], 0.5)
         q_ccd_fil = q_fil_i(bands)*q_ccd_i(bands)
-        
+
         return np.trapz(q_ccd_fil, bands)/(bandRange[filter][1]-bandRange[filter][0])
-        
-    def calculateEarthShineFilter(self, filter = 'i', pixel_size_phy = 10 ):
+
+    def calculateEarthShineFilter(self, filter='i', pixel_size_phy=10):
         sat = (ctypes.c_double*3)()
         sat[:] = self.sat
         ob = (ctypes.c_double*3)()
-        ob[:]=self.pointing
-        
-        
+        ob[:] = self.pointing
+
         py1 = (ctypes.c_double*3)()
         py2 = (ctypes.c_double*3)()
-        self.slcdll.ComposeY(ob,py1,py2)
-
+        self.slcdll.ComposeY(ob, py1, py2)
 
         earth_e1 = (ctypes.c_double*7)()
-        self.slcdll.EarthShine(self.jtime,sat,ob,py1,earth_e1)
+        self.slcdll.EarthShine(self.jtime, sat, ob, py1, earth_e1)
         earth_e2 = (ctypes.c_double*7)()
-        self.slcdll.EarthShine(self.jtime,sat,ob,py2,earth_e2)
-        
+        self.slcdll.EarthShine(self.jtime, sat, ob, py2, earth_e2)
+
         band_earth_e1 = earth_e1[:][filterIndex[filter]]
         band_earth_e2 = earth_e2[:][filterIndex[filter]]
-        
-        q=self.getFilterAndCCD_Q(filter=filter)
+
+        q = self.getFilterAndCCD_Q(filter=filter)
         p_lambda = filterPivotWave[filter]
         c = cons.c.value
         h = cons.h.value
-        pix_earth_e1 = band_earth_e1/(h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q
-        pix_earth_e2 = band_earth_e2/(h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q
+        pix_earth_e1 = band_earth_e1 / \
+            (h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q
+        pix_earth_e2 = band_earth_e2 / \
+            (h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q
 
-        if pix_earth_e1< pix_earth_e2:
+        if pix_earth_e1 < pix_earth_e2:
             return pix_earth_e1, py1[:]
         else:
             return pix_earth_e2, py2[:]
-    
+
     """
     calculate zodiacal  call c++ program, seems to have some problem
     """
-    def calculateZodiacalFilter1(self, filter = 'i', pixel_size_phy = 10 ):
+
+    def calculateZodiacalFilter1(self, filter='i', pixel_size_phy=10):
         sat = (ctypes.c_double*3)()
         sat[:] = self.sat
         ob = (ctypes.c_double*3)()
-        ob[:]=self.pointing
-    
+        ob[:] = self.pointing
+
         zodical_e = (ctypes.c_double*7)()
-        self.slcdll.Zodiacal(self.jtime,ob,zodical_e)
+        self.slcdll.Zodiacal(self.jtime, ob, zodical_e)
 
         ob1 = (ctypes.c_double*2)()
         ob1[:] = np.array([self.ecliptic.lon.value, self.ecliptic.lat.value])
         zodical_e1 = (ctypes.c_double*7)()
-        self.slcdll.Zodiacal1(ob1,zodical_e1)
-        
+        self.slcdll.Zodiacal1(ob1, zodical_e1)
+
         band_zodical_e = zodical_e[:][filterIndex[filter]]
-        
-        q=self.getFilterAndCCD_Q(filter=filter)
+
+        q = self.getFilterAndCCD_Q(filter=filter)
         p_lambda = filterPivotWave[filter]
         c = cons.c.value
         h = cons.h.value
-        pix_zodical_e = band_zodical_e/(h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q
-        
+        pix_zodical_e = band_zodical_e / \
+            (h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q
+
         return pix_zodical_e, band_zodical_e
-    
+
     """
     calculate zodiacal  use python
     """
-    def calculateZodiacalFilter2(self,filter = 'i', aper = 2, pixelsize = 0.074, sun_pos = np.array([0,0,0])):
-       
-        spec, v_mag = self.calculateZodicalSpec(longitude = self.ecliptic.lon.value, latitude = self.ecliptic.lat.value, sun_pos = sun_pos)
+
+    def calculateZodiacalFilter2(self, filter='i', aper=2, pixelsize=0.074, sun_pos=np.array([0, 0, 0])):
+
+        spec, v_mag = self.calculateZodicalSpec(
+            longitude=self.ecliptic.lon.value, latitude=self.ecliptic.lat.value, sun_pos=sun_pos)
         # spec = self.calculateZodicalSpec(longitude = lon, latitude = lat)
 
         try:
-            with pkg_resources.files('ObservationSim.Instrument.data.throughputs').joinpath(filter + '_throughput.txt') as throughputFn:
+            with pkg_resources.files('observation_sim.instruments.data.throughputs').joinpath(filter + '_throughput.txt') as throughputFn:
                 throughput = np.loadtxt(throughputFn)
         except AttributeError:
-            with pkg_resources.path('ObservationSim.Instrument.data.throughputs', filter + '_throughput.txt') as throughputFn:
+            with pkg_resources.path('observation_sim.instruments.data.throughputs', filter + '_throughput.txt') as throughputFn:
                 throughput = np.loadtxt(throughputFn)
 
         deltL = 0.5
@@ -294,61 +315,60 @@ class Straylight(object):
 
         throughput_ = throughput_i(lamb)
 
-        sky_pix = np.trapz(flux*throughput_, lamb) * math.pi * aper*aper/4 * pixelsize * pixelsize
+        sky_pix = np.trapz(flux*throughput_, lamb) * \
+            math.pi * aper*aper/4 * pixelsize * pixelsize
 
         # sky_pix_e = np.trapz(y, lamb) * math.pi * aper*aper/4 * pixelsize * pixelsize/(10*10*1e-6*1e-6)*1e-7*1e4
 
-        return sky_pix, v_mag#,  sky_pix_e
-    
-    def calculateStarLightFilter(self, filter = 'i', pointYaxis = np.array([1,1,1]), pixel_size_phy = 10 ):
+        return sky_pix, v_mag  # ,  sky_pix_e
+
+    def calculateStarLightFilter(self, filter='i', pointYaxis=np.array([1, 1, 1]), pixel_size_phy=10):
         sat = (ctypes.c_double*3)()
         sat[:] = self.sat
         ob = (ctypes.c_double*3)()
-        ob[:]=self.pointing
-        
-        
+        ob[:] = self.pointing
+
         py = (ctypes.c_double*3)()
         py[:] = pointYaxis
 
-        q=self.getFilterAndCCD_Q(filter=filter)
+        q = self.getFilterAndCCD_Q(filter=filter)
         p_lambda = filterPivotWave[filter]
         c = cons.c.value
         h = cons.h.value
 
-
         star_e1 = (ctypes.c_double*7)()
-        self.slcdll.PointSource(self.jtime,sat,ob,py,star_e1, str.encode(self.brightStarTabFn))
+        self.slcdll.PointSource(self.jtime, sat, ob, py,
+                                star_e1, str.encode(self.brightStarTabFn))
 
         band_star_e1 = star_e1[:][filterIndex[filter]]
 
-        pix_star_e1 = band_star_e1/(h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q
-        
+        pix_star_e1 = band_star_e1 / \
+            (h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q
+
         return pix_star_e1
 
-    def calculateEarthshineGrating(self, grating = 'GU', pixel_size_phy = 10, normFilter = 'g',  aper = 2, pixelsize = 0.074):
+    def calculateEarthshineGrating(self, grating='GU', pixel_size_phy=10, normFilter='g',  aper=2, pixelsize=0.074):
         sat = (ctypes.c_double*3)()
         sat[:] = self.sat
         ob = (ctypes.c_double*3)()
-        ob[:]=self.pointing
-        
-        
+        ob[:] = self.pointing
+
         py1 = (ctypes.c_double*3)()
         py2 = (ctypes.c_double*3)()
-        self.slcdll.ComposeY(ob,py1,py2)
-
+        self.slcdll.ComposeY(ob, py1, py2)
 
         earth_e1 = (ctypes.c_double*7)()
-        self.slcdll.EarthShine(self.jtime,sat,ob,py1,earth_e1)
+        self.slcdll.EarthShine(self.jtime, sat, ob, py1, earth_e1)
         earth_e2 = (ctypes.c_double*7)()
-        self.slcdll.EarthShine(self.jtime,sat,ob,py2,earth_e2)
+        self.slcdll.EarthShine(self.jtime, sat, ob, py2, earth_e2)
         # zodical_e = (ctypes.c_double*7)()
         # self.slcdll.Zodiacal(self.jtime,ob,zodical_e)
-        
+
         band_earth_e1 = earth_e1[:][filterIndex[normFilter]]
         band_earth_e2 = earth_e2[:][filterIndex[normFilter]]
         band_earth_e = band_earth_e2
         py = py2[:]
-        if band_earth_e1<band_earth_e2:
+        if band_earth_e1 < band_earth_e2:
             band_earth_e = band_earth_e1
             py = py1[:]
         # band_earth_e = np.min([band_earth_e1, band_earth_e2])
@@ -356,18 +376,20 @@ class Straylight(object):
         # band_earth_e1 = 0
         # band_earth_e2 = 0
         # band_zodical_e = zodical_e[:][filterIndex[normFilter]]
-        
-        q=self.getFilterAndCCD_Q(filter=normFilter)
+
+        q = self.getFilterAndCCD_Q(filter=normFilter)
         p_lambda = filterPivotWave[normFilter]
         c = cons.c.value
         h = cons.h.value
-        pix_earth_e = band_earth_e/(h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q
-        
+        pix_earth_e = band_earth_e / \
+            (h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q
+
         # pix_earth_e2 = band_earth_e2/(h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q
         # pix_zodical_e = band_zodical_e/(h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q
         # pix_earth_e = np.min([pix_earth_e1, pix_earth_e2])
 
-        earthshine_v, earthshine_spec = self.calculatEarthshineByHSTSpec(filter = normFilter, aper = aper, pixelsize = pixelsize)
+        earthshine_v, earthshine_spec = self.calculatEarthshineByHSTSpec(
+            filter=normFilter, aper=aper, pixelsize=pixelsize)
 
         lamb_earth = earthshine_spec['WAVELENGTH']
         flux_earth = earthshine_spec['FLUX']*pix_earth_e/earthshine_v
@@ -375,30 +397,31 @@ class Straylight(object):
         earth_v_grating = 0
         for s_order in SpecOrder:
             try:
-                with pkg_resources.files('ObservationSim.Instrument.data.sls_conf').joinpath(
+                with pkg_resources.files('observation_sim.instruments.data.sls_conf').joinpath(
                         grating + '.Throughput.' + s_order + 'st.fits') as thpFn:
                     thp_ = Table.read(thpFn)
             except AttributeError:
-                with pkg_resources.path('ObservationSim.Instrument.data.sls_conf',
+                with pkg_resources.path('observation_sim.instruments.data.sls_conf',
                                         grating + '.Throughput.' + s_order + 'st.fits') as thpFn:
                     thp_ = Table.read(thpFn)
 
-            thpFn_i = interpolate.interp1d(thp_['WAVELENGTH'], thp_['SENSITIVITY'])
+            thpFn_i = interpolate.interp1d(
+                thp_['WAVELENGTH'], thp_['SENSITIVITY'])
             thp = thpFn_i(lamb_earth)
-            beamsEarth = np.trapz(flux_earth*thp,lamb_earth)* math.pi*aper*aper/4 * pixelsize * pixelsize
+            beamsEarth = np.trapz(flux_earth*thp, lamb_earth) * \
+                math.pi*aper*aper/4 * pixelsize * pixelsize
             earth_v_grating = earth_v_grating + beamsEarth
             # print(beamsEarth)
 
         # print(earthshine_v, pix_earth_e, earth_v_grating)
         return earth_v_grating, py
 
-    def calculateStarLightGrating(self, grating = 'GU', pointYaxis = np.array([1,1,1]), pixel_size_phy = 10 ):
+    def calculateStarLightGrating(self, grating='GU', pointYaxis=np.array([1, 1, 1]), pixel_size_phy=10):
         sat = (ctypes.c_double*3)()
         sat[:] = self.sat
         ob = (ctypes.c_double*3)()
-        ob[:]=self.pointing
-        
-        
+        ob[:] = self.pointing
+
         py = (ctypes.c_double*3)()
         py[:] = pointYaxis
 
@@ -407,9 +430,9 @@ class Straylight(object):
         c = cons.c.value
         h = cons.h.value
 
-
         star_e1 = (ctypes.c_double*7)()
-        self.slcdll.PointSource(self.jtime,sat,ob,py,star_e1, str.encode(self.brightStarTabFn))
+        self.slcdll.PointSource(self.jtime, sat, ob, py,
+                                star_e1, str.encode(self.brightStarTabFn))
 
         filterPivotWaveList = np.zeros(7)
         bandRangeList = np.zeros(7)
@@ -420,54 +443,54 @@ class Straylight(object):
             filterMirrorEffList[i] = filterMirrorEff[filterNameList[i]]
             brange = bandRange[filterNameList[i]]
             bandRangeList[i] = brange[1] - brange[0]
-        filterFlux_lamb = star_e1[:]/bandRangeList/filterMirrorEffList/(h*c/(filterPivotWaveList*1e-10))
-        filterFlux_lambi = interpolate.interp1d(filterPivotWaveList,filterFlux_lamb,fill_value="extrapolate")
+        filterFlux_lamb = star_e1[:]/bandRangeList / \
+            filterMirrorEffList/(h*c/(filterPivotWaveList*1e-10))
+        filterFlux_lambi = interpolate.interp1d(
+            filterPivotWaveList, filterFlux_lamb, fill_value="extrapolate")
 
-        lamb_g = np.arange(bandRange[grating][0], bandRange[grating][1],1)
+        lamb_g = np.arange(bandRange[grating][0], bandRange[grating][1], 1)
         flux_g = filterFlux_lambi(lamb_g)
         # flux_total_g = np.trapz(flux_g,lamb_g)
         starLight_grating = 0
         for s_order in SpecOrder:
             try:
-                with pkg_resources.files('ObservationSim.Instrument.data.sls_conf').joinpath(
+                with pkg_resources.files('observation_sim.instruments.data.sls_conf').joinpath(
                         grating + '.Throughput.' + s_order + 'st.fits') as thpFn:
                     thp_ = Table.read(thpFn)
             except AttributeError:
-                with pkg_resources.path('ObservationSim.Instrument.data.sls_conf',
+                with pkg_resources.path('observation_sim.instruments.data.sls_conf',
                                         grating + '.Throughput.' + s_order + 'st.fits') as thpFn:
                     thp_ = Table.read(thpFn)
 
-            thpFn_i = interpolate.interp1d(thp_['WAVELENGTH'], thp_['SENSITIVITY'])
+            thpFn_i = interpolate.interp1d(
+                thp_['WAVELENGTH'], thp_['SENSITIVITY'])
             thp = thpFn_i(lamb_g)
-            beamsZol = np.trapz(flux_g*thp,lamb_g)*pixel_size_phy*1e-6*pixel_size_phy*1e-6
+            beamsZol = np.trapz(flux_g*thp, lamb_g) * \
+                pixel_size_phy*1e-6*pixel_size_phy*1e-6
             starLight_grating = starLight_grating + beamsZol
             # print(beamsZol)
 
-
-
         # band_star_e1 = star_e1[:][filterIndex[filter]]
 
         # pix_star_e1 = band_star_e1/(h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q
-        
-        return starLight_grating
 
+        return starLight_grating
 
-    
-    def calculatEarthshineByHSTSpec(self, filter = 'g', aper = 2, pixelsize = 0.074, s = 2000, e = 11000):
+    def calculatEarthshineByHSTSpec(self, filter='g', aper=2, pixelsize=0.074, s=2000, e=11000):
 
         try:
-            with pkg_resources.files('ObservationSim.Straylight.data.sky').joinpath('earthShine.dat') as specFn:
+            with pkg_resources.files('observation_sim.sky_background.data.sky').joinpath('earthShine.dat') as specFn:
                 spec = np.loadtxt(specFn)
         except AttributeError:
-            with pkg_resources.path('ObservationSim.Straylight.data.sky',
+            with pkg_resources.path('observation_sim.sky_background.data.sky',
                                     'earthShine.dat') as specFn:
                 spec = np.loadtxt(specFn)
 
         try:
-            with pkg_resources.files('ObservationSim.Instrument.data.throughputs').joinpath(filter + '_throughput.txt') as throughputFn:
+            with pkg_resources.files('observation_sim.instruments.data.throughputs').joinpath(filter + '_throughput.txt') as throughputFn:
                 throughput = np.loadtxt(throughputFn)
         except AttributeError:
-            with pkg_resources.path('ObservationSim.Instrument.data.throughputs', filter + '_throughput.txt') as throughputFn:
+            with pkg_resources.path('observation_sim.instruments.data.throughputs', filter + '_throughput.txt') as throughputFn:
                 throughput = np.loadtxt(throughputFn)
 
         deltL = 0.5
@@ -482,7 +505,8 @@ class Straylight(object):
 
         throughput_ = throughput_i(lamb)
 
-        sky_pix = np.trapz(flux*throughput_, lamb) * math.pi * aper*aper/4 * pixelsize * pixelsize
+        sky_pix = np.trapz(flux*throughput_, lamb) * \
+            math.pi * aper*aper/4 * pixelsize * pixelsize
 
         lamb = np.arange(s, e, deltL)
         speci = interpolate.interp1d(spec[:, 0], spec[:, 1])
@@ -490,30 +514,31 @@ class Straylight(object):
         # erg/s/cm2/A --> photo/s/m2/A
         flux = y * lamb / (cons.h.value * cons.c.value) * 1e-13
 
-        return sky_pix, Table(np.array([lamb, flux]).T,names=('WAVELENGTH', 'FLUX'))
+        return sky_pix, Table(np.array([lamb, flux]).T, names=('WAVELENGTH', 'FLUX'))
 
-    def calculateZodicalSpec(self,longitude = 50, latitude = 60, sun_pos = np.array([0,0,0])):
+    def calculateZodicalSpec(self, longitude=50, latitude=60, sun_pos=np.array([0, 0, 0])):
         from scipy.interpolate import interp2d
         from scipy.interpolate import griddata
 
         try:
-            with pkg_resources.files('ObservationSim.Straylight.data').joinpath('Zodiacal_map1.dat') as z_map_fn:
-                 ZL = np.loadtxt(z_map_fn)
+            with pkg_resources.files('observation_sim.sky_background.data').joinpath('Zodiacal_map1.dat') as z_map_fn:
+                ZL = np.loadtxt(z_map_fn)
         except AttributeError:
-            with pkg_resources.path('ObservationSim.Straylight.data',
+            with pkg_resources.path('observation_sim.sky_background.data',
                                     'Zodiacal_map1.dat') as z_map_fn:
                 ZL = np.loadtxt(z_map_fn)
 
         # zl_sh = ZL.shape
         # x = np.arange(0,zl_sh[1],1)
         # y = np.arange(0,zl_sh[0],1)
-        x = ZL[0,1:]
-        y = ZL[1:,0]
-        X,Y = np.meshgrid(x,y)
+        x = ZL[0, 1:]
+        y = ZL[1:, 0]
+        X, Y = np.meshgrid(x, y)
         # f_sur = interp2d(X,Y,ZL,kind='linear')
         sun_radec = Cartesian2Equatorial(sun_pos)
 
-        sun_eclip = coord.SkyCoord(sun_radec[0]*u.degree, sun_radec[1]*u.degree,frame='icrs')
+        sun_eclip = coord.SkyCoord(
+            sun_radec[0]*u.degree, sun_radec[1]*u.degree, frame='icrs')
         sun_equtor = sun_eclip.transform_to('barycentrictrueecliptic')
 
         longitude = longitude - (sun_equtor.lon*u.degree).value
@@ -526,15 +551,16 @@ class Straylight(object):
         latitude = np.abs(latitude)
         lo = longitude
         la = latitude
-        zl = griddata((X.flatten(),Y.flatten()),ZL[1:,1:].flatten(),(la,lo), method='cubic').min()
+        zl = griddata((X.flatten(), Y.flatten()),
+                      ZL[1:, 1:].flatten(), (la, lo), method='cubic').min()
         zl = zl*(math.pi*math.pi)/(180*180)/(3600*3600)*1e-4*1e7*1e-8*1e-4
         # print(zl , '\n')
 
         try:
-            with pkg_resources.files('ObservationSim.Straylight.data.sky').joinpath('zodiacal.dat') as zodical_fn:
+            with pkg_resources.files('observation_sim.sky_background.data.sky').joinpath('zodiacal.dat') as zodical_fn:
                 spec = np.loadtxt(zodical_fn)
         except AttributeError:
-            with pkg_resources.path('ObservationSim.Straylight.data.sky',
+            with pkg_resources.path('observation_sim.sky_background.data.sky',
                                     'zodiacal.dat') as zodical_fn:
                 spec = np.loadtxt(zodical_fn)
 
@@ -545,29 +571,37 @@ class Straylight(object):
         v_mag = np.log10(f_ration)*(-2.5)+22.1
         # print("factor:", v_mag, lo, la)
 
-        return Table(np.array([spec[:,0], spec[:,1]*f_ration]).T,names=('WAVELENGTH', 'FLUX')), v_mag
-    
-    def calculateStrayLightFilter(self, filter = 'i', pixel_size_phy = 10, pixel_scale = 0.074):
-        e1,py = self.calculateEarthShineFilter(filter = filter, pixel_size_phy = pixel_size_phy)
-        e2, _ = self.calculateZodiacalFilter2(filter = filter, sun_pos=self.sun_pos, pixelsize = pixel_scale)
-        e3 = self.calculateStarLightFilter(filter = filter,pointYaxis = py, pixel_size_phy = pixel_size_phy)
-        
+        return Table(np.array([spec[:, 0], spec[:, 1]*f_ration]).T, names=('WAVELENGTH', 'FLUX')), v_mag
+
+    def calculateStrayLightFilter(self, filter='i', pixel_size_phy=10, pixel_scale=0.074):
+        e1, py = self.calculateEarthShineFilter(
+            filter=filter, pixel_size_phy=pixel_size_phy)
+        e2, _ = self.calculateZodiacalFilter2(
+            filter=filter, sun_pos=self.sun_pos, pixelsize=pixel_scale)
+        e3 = self.calculateStarLightFilter(
+            filter=filter, pointYaxis=py, pixel_size_phy=pixel_size_phy)
+
         return e1+e2+e3
-    
-    def calculateStrayLightGrating(self, grating = 'GI', pixel_size_phy = 10, normFilter_es = 'g'):
-        e1,py = self.calculateEarthshineGrating(grating = grating, pixel_size_phy = pixel_size_phy, normFilter = normFilter_es)
-        e2 = self.calculateStarLightGrating(grating = grating, pointYaxis = py)
-        spec, _ = self.calculateZodicalSpec(longitude = self.ecliptic.lon.value, latitude = self.ecliptic.lat.value, sun_pos = self.sun_pos)
-        
+
+    def calculateStrayLightGrating(self, grating='GI', pixel_size_phy=10, normFilter_es='g'):
+        e1, py = self.calculateEarthshineGrating(
+            grating=grating, pixel_size_phy=pixel_size_phy, normFilter=normFilter_es)
+        e2 = self.calculateStarLightGrating(grating=grating, pointYaxis=py)
+        spec, _ = self.calculateZodicalSpec(
+            longitude=self.ecliptic.lon.value, latitude=self.ecliptic.lat.value, sun_pos=self.sun_pos)
+
         return e1+e2, spec
- 
 
-def testZodiacal(lon = 285.04312526255366, lat = 30.):
-    c_eclip = coord.SkyCoord(lon*u.degree, lat*u.degree,frame='barycentrictrueecliptic')
+
+def testZodiacal(lon=285.04312526255366, lat=30.):
+    c_eclip = coord.SkyCoord(lon*u.degree, lat*u.degree,
+                             frame='barycentrictrueecliptic')
     c_equtor = c_eclip.transform_to('icrs')
 
-    sl = Straylight(jtime = 2459767.00354975, sat = np.array([]), radec = np.array([(c_equtor.ra*u.degree).value, (c_equtor.dec*u.degree).value]))
-    e_zol, v_mag = sl.calculateZodiacalFilter2(filter = 'i', sun_pos=np.array([-3.70939436e+07,  1.35334903e+08,  5.86673104e+07]))
+    sl = Straylight(jtime=2459767.00354975, sat=np.array([]), radec=np.array(
+        [(c_equtor.ra*u.degree).value, (c_equtor.dec*u.degree).value]))
+    e_zol, v_mag = sl.calculateZodiacalFilter2(filter='i', sun_pos=np.array(
+        [-3.70939436e+07,  1.35334903e+08,  5.86673104e+07]))
     print(e_zol)
 
 # ju=2.4608437604166665e+06
@@ -639,4 +673,3 @@ def testZodiacal(lon = 285.04312526255366, lat = 30.):
 #     print(e1+e2,e1_+e3+e4,e5,e6)
 #
 #     # print(e1,e2,e3,e4)
-
diff --git a/ObservationSim/Straylight/__init__.py b/observation_sim/sky_background/__init__.py
similarity index 100%
rename from ObservationSim/Straylight/__init__.py
rename to observation_sim/sky_background/__init__.py
diff --git a/ObservationSim/Straylight/data/Zodiacal_map1.dat b/observation_sim/sky_background/data/Zodiacal_map1.dat
similarity index 100%
rename from ObservationSim/Straylight/data/Zodiacal_map1.dat
rename to observation_sim/sky_background/data/Zodiacal_map1.dat
diff --git a/ObservationSim/Straylight/data/sky/__init__.py b/observation_sim/sky_background/data/__init__.py
similarity index 100%
rename from ObservationSim/Straylight/data/sky/__init__.py
rename to observation_sim/sky_background/data/__init__.py
diff --git a/ObservationSim/Straylight/lib/__init__.py b/observation_sim/sky_background/data/sky/__init__.py
similarity index 100%
rename from ObservationSim/Straylight/lib/__init__.py
rename to observation_sim/sky_background/data/sky/__init__.py
diff --git a/ObservationSim/Straylight/data/sky/earthShine.dat b/observation_sim/sky_background/data/sky/earthShine.dat
similarity index 100%
rename from ObservationSim/Straylight/data/sky/earthShine.dat
rename to observation_sim/sky_background/data/sky/earthShine.dat
diff --git a/ObservationSim/Straylight/data/sky/earthshine1.dat b/observation_sim/sky_background/data/sky/earthshine1.dat
similarity index 100%
rename from ObservationSim/Straylight/data/sky/earthshine1.dat
rename to observation_sim/sky_background/data/sky/earthshine1.dat
diff --git a/ObservationSim/Straylight/data/sky/sky.dat b/observation_sim/sky_background/data/sky/sky.dat
similarity index 100%
rename from ObservationSim/Straylight/data/sky/sky.dat
rename to observation_sim/sky_background/data/sky/sky.dat
diff --git a/ObservationSim/Straylight/data/sky/sky_emiss_hubble_50_50_A.dat b/observation_sim/sky_background/data/sky/sky_emiss_hubble_50_50_A.dat
similarity index 100%
rename from ObservationSim/Straylight/data/sky/sky_emiss_hubble_50_50_A.dat
rename to observation_sim/sky_background/data/sky/sky_emiss_hubble_50_50_A.dat
diff --git a/ObservationSim/Straylight/data/sky/zodiacal.dat b/observation_sim/sky_background/data/sky/zodiacal.dat
similarity index 100%
rename from ObservationSim/Straylight/data/sky/zodiacal.dat
rename to observation_sim/sky_background/data/sky/zodiacal.dat
diff --git a/ObservationSim/Straylight/data/sky/zodiacal_.dat b/observation_sim/sky_background/data/sky/zodiacal_.dat
similarity index 100%
rename from ObservationSim/Straylight/data/sky/zodiacal_.dat
rename to observation_sim/sky_background/data/sky/zodiacal_.dat
diff --git a/ObservationSim/Straylight/lib/BrightGaia_with_csst_mag b/observation_sim/sky_background/lib/BrightGaia_with_csst_mag
similarity index 100%
rename from ObservationSim/Straylight/lib/BrightGaia_with_csst_mag
rename to observation_sim/sky_background/lib/BrightGaia_with_csst_mag
diff --git a/ObservationSim/Straylight/lib/DE405 b/observation_sim/sky_background/lib/DE405
similarity index 100%
rename from ObservationSim/Straylight/lib/DE405
rename to observation_sim/sky_background/lib/DE405
diff --git a/ObservationSim/Straylight/lib/PST b/observation_sim/sky_background/lib/PST
similarity index 100%
rename from ObservationSim/Straylight/lib/PST
rename to observation_sim/sky_background/lib/PST
diff --git a/ObservationSim/Straylight/lib/R b/observation_sim/sky_background/lib/R
similarity index 100%
rename from ObservationSim/Straylight/lib/R
rename to observation_sim/sky_background/lib/R
diff --git a/ObservationSim/Straylight/lib/Zodiacal b/observation_sim/sky_background/lib/Zodiacal
similarity index 100%
rename from ObservationSim/Straylight/lib/Zodiacal
rename to observation_sim/sky_background/lib/Zodiacal
diff --git a/ObservationSim/__init__.py b/observation_sim/sky_background/lib/__init__.py
similarity index 100%
rename from ObservationSim/__init__.py
rename to observation_sim/sky_background/lib/__init__.py
diff --git a/ObservationSim/Straylight/lib/libstraylight.dylib b/observation_sim/sky_background/lib/libstraylight.dylib
similarity index 100%
rename from ObservationSim/Straylight/lib/libstraylight.dylib
rename to observation_sim/sky_background/lib/libstraylight.dylib
diff --git a/ObservationSim/Straylight/lib/libstraylight.so b/observation_sim/sky_background/lib/libstraylight.so
similarity index 100%
rename from ObservationSim/Straylight/lib/libstraylight.so
rename to observation_sim/sky_background/lib/libstraylight.so
diff --git a/run_sim.py b/run_sim.py
index 0cc1368633c80a2c84f7a39d4171eb11b6cc5783..f1179851f87e066259bbc9cbd1e63939da78e3fc 100755
--- a/run_sim.py
+++ b/run_sim.py
@@ -1,5 +1,5 @@
-from ObservationSim.ObservationSim import Observation
-from ObservationSim._util import parse_args, make_run_dirs, generate_pointing_list
+from observation_sim.ObservationSim import Observation
+from observation_sim._util import parse_args, make_run_dirs, generate_pointing_list
 from importlib.metadata import version
 import os
 import yaml
@@ -18,7 +18,7 @@ def run_sim():
     Parameters
     ----------
     Catalog : Class
-        a catalog class which is inherited from ObservationSim.MockObject.CatalogBase 
+        a catalog class which is inherited from observation_sim.mock_objects.CatalogBase 
 
     Returns
     ----------
@@ -94,7 +94,7 @@ def run_sim():
 
     # Initialize the simulation
     if args.catalog is not None:
-        catalog_module = importlib.import_module('Catalog.'+args.catalog)
+        catalog_module = importlib.import_module('catalog.'+args.catalog)
         obs = Observation(config=config, Catalog=catalog_module.Catalog,
                           work_dir=config['work_dir'], data_dir=config['data_dir'])
     else:
diff --git a/setup.py b/setup.py
index 921688eb4a29fd6ae500407c0fb34ce45e692c10..9257f72484e4a0f38d72c311e09d61753659d9e4 100644
--- a/setup.py
+++ b/setup.py
@@ -39,26 +39,26 @@ class build_ext(build_ext):
 
 
 extensions = [
-    Extension("ObservationSim.MockObject.SpecDisperser.disperse_c.interp", ["ObservationSim/MockObject/SpecDisperser/disperse_c/interp.pyx"],
+    Extension("observation_sim.mock_objects.SpecDisperser.disperse_c.interp", ["observation_sim/mock_objects/SpecDisperser/disperse_c/interp.pyx"],
               include_dirs=[numpy.get_include()],
               libraries=["m"]),
 
-    Extension("ObservationSim.MockObject.SpecDisperser.disperse_c.disperse", ["ObservationSim/MockObject/SpecDisperser/disperse_c/disperse.pyx"],
+    Extension("observation_sim.mock_objects.SpecDisperser.disperse_c.disperse", ["observation_sim/mock_objects/SpecDisperser/disperse_c/disperse.pyx"],
               include_dirs=[numpy.get_include()],
               libraries=["m"]),
 ]
 
-df_module = [CTypes('ObservationSim.Instrument.Chip.libBF.libmoduleBF',
-                    ['ObservationSim/Instrument/Chip/libBF/diffusion_X1.c',
-                        'ObservationSim/Instrument/Chip/libBF/nrutil.c'],
+df_module = [CTypes('observation_sim.instruments.chip.libBF.libmoduleBF',
+                    ['observation_sim/instruments/chip/libBF/diffusion_X1.c',
+                        'observation_sim/instruments/chip/libBF/nrutil.c'],
                     include_dirs=[
-                        'ObservationSim/Instrument/Chip/libBF/', '/usr/include']
+                        'observation_sim/instruments/chip/libBF/', '/usr/include']
                     )]
-cti_module = [CTypes('ObservationSim.Instrument.Chip.libCTI.libmoduleCTI',
-                     ['ObservationSim/Instrument/Chip/libCTI/src/add_CTI.c', 'ObservationSim/Instrument/Chip/libCTI/src/nrutil.c', 'ObservationSim/Instrument/Chip/libCTI/src/ran1.c', 'ObservationSim/Instrument/Chip/libCTI/src/ran2.c', 'ObservationSim/Instrument/Chip/libCTI/src/poidev.c',
-                         'ObservationSim/Instrument/Chip/libCTI/src/gammln.c', 'ObservationSim/Instrument/Chip/libCTI/src/gasdev.c', 'ObservationSim/Instrument/Chip/libCTI/src/sort.c', 'ObservationSim/Instrument/Chip/libCTI/src/creattraps.c'],
+cti_module = [CTypes('observation_sim.instruments.chip.libCTI.libmoduleCTI',
+                     ['observation_sim/instruments/chip/libCTI/src/add_CTI.c', 'observation_sim/instruments/chip/libCTI/src/nrutil.c', 'observation_sim/instruments/chip/libCTI/src/ran1.c', 'observation_sim/instruments/chip/libCTI/src/ran2.c', 'observation_sim/instruments/chip/libCTI/src/poidev.c',
+                         'observation_sim/instruments/chip/libCTI/src/gammln.c', 'observation_sim/instruments/chip/libCTI/src/gasdev.c', 'observation_sim/instruments/chip/libCTI/src/sort.c', 'observation_sim/instruments/chip/libCTI/src/creattraps.c'],
                      include_dirs=[
-                         'ObservationSim/Instrument/Chip/libCTI/src/', '/usr/include']
+                         'observation_sim/instruments/chip/libCTI/src/', '/usr/include']
                      )]
 
 
@@ -93,23 +93,23 @@ setup(name='csst_msc_sim',
       # ],
 
       package_data={
-          'ObservationSim.Astrometry.lib': ['libshao.so'],
-          'ObservationSim.Instrument.Chip.libBF': ['libmoduleBF.so'],
-          'ObservationSim.Instrument.Chip.libCTI': ['libmoduleCTI.so'],
-          'ObservationSim.MockObject.data': ['*.dat'],
-          'ObservationSim.MockObject.data.led': ['*.fits'],
-          'ObservationSim.Instrument.data': ['*.txt', '*.dat', '*.json'],
-          'ObservationSim.Instrument.data.field_distortion': ['*.pickle'],
-          'ObservationSim.Instrument.data.ccd': ['*.txt', '*.json'],
-          'ObservationSim.Instrument.data.filters': ['*.txt', '*.list', '*.dat'],
-          'ObservationSim.Instrument.data.throughputs': ['*.txt', '*.dat'],
-          'ObservationSim.Instrument.data.sls_conf': ['*.conf', '*.fits'],
-          #   'ObservationSim.Instrument.data.flatCube': ['*.fits'],
-          'Catalog.data': ['*.fits', '*.so'],
-          'ObservationSim.Config.Header': ['*.fits', '*.lst'],
-          'ObservationSim.Straylight.data': ['*.dat'],
-          'ObservationSim.Straylight.data.sky': ['*.dat'],
-          'ObservationSim.Straylight.lib': ['*'],
+          'observation_sim.astrometry.lib': ['libshao.so'],
+          'observation_sim.instruments.chip.libBF': ['libmoduleBF.so'],
+          'observation_sim.instruments.chip.libCTI': ['libmoduleCTI.so'],
+          'observation_sim.mock_objects.data': ['*.dat'],
+          'observation_sim.mock_objects.data.led': ['*.fits'],
+          'observation_sim.instruments.data': ['*.txt', '*.dat', '*.json'],
+          'observation_sim.instruments.data.field_distortion': ['*.pickle'],
+          'observation_sim.instruments.data.ccd': ['*.txt', '*.json'],
+          'observation_sim.instruments.data.filters': ['*.txt', '*.list', '*.dat'],
+          'observation_sim.instruments.data.throughputs': ['*.txt', '*.dat'],
+          'observation_sim.instruments.data.sls_conf': ['*.conf', '*.fits'],
+          #   'observation_sim.Instrument.data.flatCube': ['*.fits'],
+          'catalog.data': ['*.fits', '*.so'],
+          'observation_sim.config.header': ['*.fits', '*.lst'],
+          'observation_sim.sky_background.data': ['*.dat'],
+          'observation_sim.sky_background.data.sky': ['*.dat'],
+          'observation_sim.sky_background.lib': ['*'],
       },
       python_requires=">=3.11",  # Python版本要求
       install_requires=requirements,
diff --git a/tests/test_BF_CTE.py b/tests/test_BF_CTE.py
index 4b3ef74015b99d9fe4d51a51fa8acc26ca248a92..26b9dad3912ec479b1bba258e4b9433bffa99b4c 100644
--- a/tests/test_BF_CTE.py
+++ b/tests/test_BF_CTE.py
@@ -1,6 +1,8 @@
 import unittest
 
-import sys,os,math
+import sys
+import os
+import math
 from itertools import islice
 import numpy as np
 import copy
@@ -9,10 +11,9 @@ import galsim
 import yaml
 from astropy.io import fits
 
-from ObservationSim.Instrument import Chip, Filter, FilterParam, FocalPlane
-from ObservationSim.Instrument.Chip import ChipUtils as chip_utils
-#from ObservationSim.sim_steps import add_brighter_fatter_CTE
-from ObservationSim.Instrument.Chip.libCTI.CTI_modeling import CTI_sim
+from observation_sim.instruments import Chip, Filter, FilterParam, FocalPlane
+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
@@ -23,14 +24,15 @@ except ImportError:
 
 ### test FUNCTION --- START ###
 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
@@ -38,11 +40,11 @@ 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])
@@ -50,20 +52,24 @@ def add_brighter_fatter(img):
     return img
 ### test FUNCTION --- END ###
 
+
 def defineCCD(iccd, config_file):
     with open(config_file, "r") as stream:
         try:
             config = yaml.safe_load(stream)
-            #for key, value in config.items():
+            # for key, value in config.items():
             #    print (key + " : " + str(value))
         except yaml.YAMLError as exc:
             print(exc)
     chip = Chip(chipID=iccd, config=config)
-    chip.img = galsim.ImageF(400, 200) #galsim.ImageF(chip.npix_x, chip.npix_y)
+    # galsim.ImageF(chip.npix_x, chip.npix_y)
+    chip.img = galsim.ImageF(400, 200)
     focal_plane = FocalPlane(chip_list=[iccd])
-    chip.img.wcs= focal_plane.getTanWCS(192.8595, 27.1283, -113.4333*galsim.degrees, chip.pix_scale)
+    chip.img.wcs = focal_plane.getTanWCS(
+        192.8595, 27.1283, -113.4333*galsim.degrees, chip.pix_scale)
     return chip
 
+
 def defineFilt(chip):
     filter_param = FilterParam()
     filter_id, filter_type = chip.getChipFilter()
@@ -79,11 +85,11 @@ def defineFilt(chip):
 class detModule_coverage(unittest.TestCase):
     def __init__(self, methodName='runTest'):
         super(detModule_coverage, self).__init__(methodName)
-        ##self.dataPath = "/public/home/chengliang/CSSOSDataProductsSims/csst-simulation/tests/UNIT_TEST_DATA" ##os.path.join(os.getenv('UNIT_TEST_DATA_ROOT'), 'csst_fz_gc1')
-        self.dataPath = os.path.join(os.getenv('UNIT_TEST_DATA_ROOT'), 'csst_msc_sim/csst_fz_msc')
+        # self.dataPath = "/public/home/chengliang/CSSOSDataProductsSims/csst-simulation/tests/UNIT_TEST_DATA" ##os.path.join(os.getenv('UNIT_TEST_DATA_ROOT'), 'csst_fz_gc1')
+        self.dataPath = os.path.join(
+            os.getenv('UNIT_TEST_DATA_ROOT'), 'csst_msc_sim/csst_fz_msc')
         self.iccd = 1
 
-
     def test_add_brighter_fatter(self):
         config_file = os.path.join(self.dataPath, 'config_test.yaml')
         chip = defineCCD(self.iccd, config_file)
@@ -91,32 +97,31 @@ class detModule_coverage(unittest.TestCase):
         print(chip.chipID)
         print(chip.cen_pix_x, chip.cen_pix_y)
 
-        #objA-lowSFB
+        # objA-lowSFB
         obj = galsim.Gaussian(sigma=0.2, flux=1000)
         arr = obj.drawImage(nx=64, ny=64, scale=0.074).array
-        chip.img.array[(100-32):(100+32),(200-32):(200+32)] = arr[:,:] 
+        chip.img.array[(100-32):(100+32), (200-32):(200+32)] = arr[:, :]
         img_old = copy.deepcopy(chip.img)
         img_new = add_brighter_fatter(img=chip.img)
-        arr1= img_old.array
-        arr2= img_new.array
+        arr1 = img_old.array
+        arr2 = img_new.array
         deltaA_max = np.max(np.abs(arr2-arr1))
-        print('deltaA-max:', np.max(np.abs(arr2-arr1))) 
-        print('deltaA-min:', np.min(np.abs(arr2-arr1))) 
+        print('deltaA-max:', np.max(np.abs(arr2-arr1)))
+        print('deltaA-min:', np.min(np.abs(arr2-arr1)))
 
-        #objB-highSFB
+        # objB-highSFB
         obj = galsim.Gaussian(sigma=0.2, flux=10000)
         arr = obj.drawImage(nx=64, ny=64, scale=0.074).array
-        chip.img.array[(100-32):(100+32),(200-32):(200+32)] = arr[:,:] 
+        chip.img.array[(100-32):(100+32), (200-32):(200+32)] = arr[:, :]
         img_old = copy.deepcopy(chip.img)
         img_new = add_brighter_fatter(img=chip.img)
-        arr3= img_old.array
-        arr4= img_new.array
+        arr3 = img_old.array
+        arr4 = img_new.array
         deltaB_max = np.max(np.abs(arr4-arr3))
-        print('deltaB-max:', np.max(np.abs(arr4-arr3))) 
-        print('deltaB-min:', np.min(np.abs(arr4-arr3))) 
-        
-        self.assertTrue( deltaB_max > deltaA_max )
+        print('deltaB-max:', np.max(np.abs(arr4-arr3)))
+        print('deltaB-min:', np.min(np.abs(arr4-arr3)))
 
+        self.assertTrue(deltaB_max > deltaA_max)
 
     def test_apply_CTE(self):
         config_file = os.path.join(self.dataPath, 'config_test.yaml')
@@ -126,18 +131,21 @@ class detModule_coverage(unittest.TestCase):
         print(chip.cen_pix_x, chip.cen_pix_y)
 
         print("  Apply CTE Effect")
-        nx,ny,noverscan,nsp,nmax = 4608,4616,84,3,10
+        nx, ny, noverscan, nsp, nmax = 4608, 4616, 84, 3, 10
         ntotal = 4700
-        beta,w,c = 0.478,84700,0
-        t = np.array([0.74,7.7,37],dtype=np.float32)
-        rho_trap = np.array([0.6,1.6,1.4],dtype=np.float32)
-        trap_seeds = np.array([0,100,1000],dtype=np.int32)
+        beta, w, c = 0.478, 84700, 0
+        t = np.array([0.74, 7.7, 37], dtype=np.float32)
+        rho_trap = np.array([0.6, 1.6, 1.4], dtype=np.float32)
+        trap_seeds = np.array([0, 100, 1000], dtype=np.int32)
         release_seed = 500
-        image = fits.getdata(os.path.join(self.dataPath, "testCTE_image_before.fits")).astype(np.int32) 
-        #get_trap_map(trap_seeds,nx,ny,nmax,rho_trap,beta,c,".")
-        #bin2fits("trap.bin",".",nsp,nx,ny,nmax)
-        image_cti = CTI_sim(image,nx,ny,noverscan,nsp,nmax,beta,w,c,t,rho_trap,trap_seeds,release_seed)
-        fits.writeto(os.path.join(self.dataPath, "testCTE_image_after.fits"),data=image_cti,overwrite=True)
+        image = fits.getdata(os.path.join(
+            self.dataPath, "testCTE_image_before.fits")).astype(np.int32)
+        # get_trap_map(trap_seeds,nx,ny,nmax,rho_trap,beta,c,".")
+        # bin2fits("trap.bin",".",nsp,nx,ny,nmax)
+        image_cti = CTI_sim(image, nx, ny, noverscan, nsp, nmax,
+                            beta, w, c, t, rho_trap, trap_seeds, release_seed)
+        fits.writeto(os.path.join(
+            self.dataPath, "testCTE_image_after.fits"), data=image_cti, overwrite=True)
 
 
 if __name__ == '__main__':
diff --git a/tests/test_PSFmodule.py b/tests/test_PSFmodule.py
index c0399aaf0ea9c1e26483ef442a9c41a218115564..0e575f14312b1fcca365672cac85f6e76a604b82 100644
--- a/tests/test_PSFmodule.py
+++ b/tests/test_PSFmodule.py
@@ -1,29 +1,33 @@
 import unittest
 
-import sys,os,math
+import sys
+import os
+import math
 from itertools import islice
 import numpy as np
 import galsim
 import yaml
 
-from ObservationSim.Instrument import Chip, Filter, FilterParam, FocalPlane
-from ObservationSim.PSF.PSFInterp import PSFInterp
+from observation_sim.instruments import Chip, Filter, FilterParam, FocalPlane
+from observation_sim.PSF.PSFInterp import PSFInterp
 
 
 def defineCCD(iccd, config_file):
     with open(config_file, "r") as stream:
         try:
             config = yaml.safe_load(stream)
-            #for key, value in config.items():
+            # for key, value in config.items():
             #    print (key + " : " + str(value))
         except yaml.YAMLError as exc:
             print(exc)
     chip = Chip(chipID=iccd, config=config)
     chip.img = galsim.ImageF(chip.npix_x, chip.npix_y)
     focal_plane = FocalPlane(chip_list=[iccd])
-    chip.img.wcs= focal_plane.getTanWCS(192.8595, 27.1283, -113.4333*galsim.degrees, chip.pix_scale)
+    chip.img.wcs = focal_plane.getTanWCS(
+        192.8595, 27.1283, -113.4333*galsim.degrees, chip.pix_scale)
     return chip
 
+
 def defineFilt(chip):
     filter_param = FilterParam()
     filter_id, filter_type = chip.getChipFilter()
@@ -39,7 +43,8 @@ def defineFilt(chip):
 class PSFInterpModule_coverage(unittest.TestCase):
     def __init__(self, methodName='runTest'):
         super(PSFInterpModule_coverage, self).__init__(methodName)
-        self.dataPath = os.path.join(os.getenv('UNIT_TEST_DATA_ROOT'), 'csst_msc_sim/csst_fz_msc')
+        self.dataPath = os.path.join(
+            os.getenv('UNIT_TEST_DATA_ROOT'), 'csst_msc_sim/csst_fz_msc')
         self.iccd = 8
 
     def test_loadPSFSet(self):
@@ -48,23 +53,28 @@ class PSFInterpModule_coverage(unittest.TestCase):
         bandpass = defineFilt(chip)
         print(chip.chipID)
         print(chip.cen_pix_x, chip.cen_pix_y)
-        
-        pathTemp = self.dataPath #"/public/share/yangxuliu/CSSOSDataProductsSims/psfCube/set1_dynamic/"
-        psfModel= PSFInterp(chip, npsf=900, PSF_data_file=pathTemp, PSF_data_prefix="", HocBuild=True, LOG_DEBUG=True)
-        
-        x, y = 4096, 4096 #imgPos[iobj, :] # try get the PSF at some location (1234, 1234) on the chip
+
+        # "/public/share/yangxuliu/CSSOSDataProductsSims/psfCube/set1_dynamic/"
+        pathTemp = self.dataPath
+        psfModel = PSFInterp(chip, npsf=900, PSF_data_file=pathTemp,
+                             PSF_data_prefix="", HocBuild=True, LOG_DEBUG=True)
+
+        # imgPos[iobj, :] # try get the PSF at some location (1234, 1234) on the chip
+        x, y = 4096, 4096
         x = x+chip.bound.xmin
         y = y+chip.bound.ymin
         pos_img = galsim.PositionD(x, y)
 
-        psf,_ = psfModel.get_PSF(chip=chip, pos_img=pos_img, bandpass=0, galsimGSObject=True)
-        psfA  = psfModel.get_PSF(chip=chip, pos_img=pos_img, bandpass=bandpass[0], galsimGSObject=False)
-        psfB  = psfModel.get_PSF(chip=chip, pos_img=pos_img, findNeighMode='hoclistFind', bandpass=bandpass[0], galsimGSObject=False)
-        
-        self.assertTrue( psf != None )
-        self.assertTrue( np.max(np.abs(psfA-psfB))<1e-6 )
+        psf, _ = psfModel.get_PSF(
+            chip=chip, pos_img=pos_img, bandpass=0, galsimGSObject=True)
+        psfA = psfModel.get_PSF(
+            chip=chip, pos_img=pos_img, bandpass=bandpass[0], galsimGSObject=False)
+        psfB = psfModel.get_PSF(
+            chip=chip, pos_img=pos_img, findNeighMode='hoclistFind', bandpass=bandpass[0], galsimGSObject=False)
+
+        self.assertTrue(psf != None)
+        self.assertTrue(np.max(np.abs(psfA-psfB)) < 1e-6)
 
 
 if __name__ == '__main__':
     unittest.main()
-
diff --git a/tests/test_SpecDisperse.py b/tests/test_SpecDisperse.py
index 2b9529d86724db8b4d35b5b72845dee52bd98a84..ead08a2635c04dd55928190024791d84f58f5595 100644
--- a/tests/test_SpecDisperse.py
+++ b/tests/test_SpecDisperse.py
@@ -1,15 +1,15 @@
 #
-#need add environment parameter  UNIT_TEST_DATA_ROOT, link to "testData/"
-#linx and mac can run as follow, need modify the name of file directory
-#export UNIT_TEST_DATA_ROOT=/Users/zhangxin/Work/SlitlessSim/CSST_SIM/CSST_develop/csst-simulation/tests/testData
+# need add environment parameter  UNIT_TEST_DATA_ROOT, link to "testData/"
+# linx and mac can run as follow, need modify the name of file directory
+# export UNIT_TEST_DATA_ROOT=/Users/zhangxin/Work/SlitlessSim/CSST_SIM/CSST_develop/csst-simulation/tests/testData
 #
 import unittest
-from ObservationSim.MockObject.SpecDisperser import rotate90, SpecDisperser
+from observation_sim.mock_objects.SpecDisperser import rotate90, SpecDisperser
 
-from ObservationSim.Config import ChipOutput
-from ObservationSim.Instrument import Telescope, Chip, FilterParam, Filter, FocalPlane
-from ObservationSim.MockObject import MockObject, Star
-from ObservationSim.PSF import PSFGauss
+from observation_sim.config import ChipOutput
+from observation_sim.instruments import Telescope, Chip, FilterParam, Filter, FocalPlane
+from observation_sim.mock_objects import MockObject, Star
+from observation_sim.PSF import PSFGauss
 
 import numpy as np
 import galsim
@@ -20,36 +20,37 @@ import matplotlib.pyplot as plt
 
 from lmfit.models import LinearModel, GaussianModel
 
-from ObservationSim.Config.Header import generateExtensionHeader
+from observation_sim.config.header import generateExtensionHeader
 import math
 import yaml
 import os
 
 
 def getAngle132(x1=0, y1=0, z1=0, x2=0, y2=0, z2=0, x3=0, y3=0, z3=0):
-    cosValue = 0;
-    angle = 0;
+    cosValue = 0
+    angle = 0
 
-    x11 = x1 - x3;
-    y11 = y1 - y3;
-    z11 = z1 - z3;
+    x11 = x1 - x3
+    y11 = y1 - y3
+    z11 = z1 - z3
 
-    x22 = x2 - x3;
-    y22 = y2 - y3;
-    z22 = z2 - z3;
+    x22 = x2 - x3
+    y22 = y2 - y3
+    z22 = z2 - z3
 
-    tt = np.sqrt((x11 * x11 + y11 * y11 + z11 * z11) * (x22 * x22 + y22 * y22 + z22 * z22));
+    tt = np.sqrt((x11 * x11 + y11 * y11 + z11 * z11)
+                 * (x22 * x22 + y22 * y22 + z22 * z22))
     if (tt == 0):
-        return 0;
+        return 0
 
-    cosValue = (x11 * x22 + y11 * y22 + z11 * z22) / tt;
+    cosValue = (x11 * x22 + y11 * y22 + z11 * z22) / tt
 
     if (cosValue > 1):
-        cosValue = 1;
+        cosValue = 1
     if (cosValue < -1):
-        cosValue = -1;
-    angle = math.acos(cosValue);
-    return angle * 360 / (2 * math.pi);
+        cosValue = -1
+    angle = math.acos(cosValue)
+    return angle * 360 / (2 * math.pi)
 
 
 def fit_SingleGauss(xX, yX, contmX, iHa0):
@@ -71,26 +72,35 @@ def fit_SingleGauss(xX, yX, contmX, iHa0):
     # print outX.params['g_center']
     outX.fit_report(min_correl=0.25)
     # print(outX.fit_report(min_correl=0.25))
-    line_slopeX = float(outX.fit_report(min_correl=0.25).split('line_slope:')[1].split('+/-')[0]) * contmX
+    line_slopeX = float(outX.fit_report(min_correl=0.25).split(
+        'line_slope:')[1].split('+/-')[0]) * contmX
     err_line_slopeX = float(
         outX.fit_report(min_correl=0.25).split('line_slope:')[1].split('+/-')[1].split('(')[0]) * contmX
 
-    line_interceptX = float(outX.fit_report(min_correl=0.25).split('line_intercept:')[1].split('+/-')[0]) * contmX
+    line_interceptX = float(outX.fit_report(min_correl=0.25).split(
+        'line_intercept:')[1].split('+/-')[0]) * contmX
     err_line_interceptX = float(
         outX.fit_report(min_correl=0.25).split('line_intercept:')[1].split('+/-')[1].split('(')[0]) * contmX
 
-    sigmaX = float(outX.fit_report(min_correl=0.25).split('g_sigma:')[1].split('+/-')[0])
-    err_sigmaX = float(outX.fit_report(min_correl=0.25).split('g_sigma:')[1].split('+/-')[1].split('(')[0])
+    sigmaX = float(outX.fit_report(min_correl=0.25).split(
+        'g_sigma:')[1].split('+/-')[0])
+    err_sigmaX = float(outX.fit_report(min_correl=0.25).split(
+        'g_sigma:')[1].split('+/-')[1].split('(')[0])
 
-    fwhmX = float(outX.fit_report(min_correl=0.25).split('g_fwhm:')[1].split('+/-')[0])
-    err_fwhmX = float(outX.fit_report(min_correl=0.25).split('g_fwhm:')[1].split('+/-')[1].split('(')[0])
+    fwhmX = float(outX.fit_report(min_correl=0.25).split(
+        'g_fwhm:')[1].split('+/-')[0])
+    err_fwhmX = float(outX.fit_report(min_correl=0.25).split(
+        'g_fwhm:')[1].split('+/-')[1].split('(')[0])
 
-    centerX = float(outX.fit_report(min_correl=0.25).split('g_center:')[1].split('+/-')[0])
-    err_centerX = float(outX.fit_report(min_correl=0.25).split('g_center:')[1].split('+/-')[1].split('(')[0])
+    centerX = float(outX.fit_report(min_correl=0.25).split(
+        'g_center:')[1].split('+/-')[0])
+    err_centerX = float(outX.fit_report(min_correl=0.25).split(
+        'g_center:')[1].split('+/-')[1].split('(')[0])
 
     return sigmaX, err_sigmaX, fwhmX, err_fwhmX, centerX, err_centerX
 
-def produceObj(x,y,chip, ra, dec, pa):
+
+def produceObj(x, y, chip, ra, dec, pa):
     pos_img = galsim.PositionD(x, y)
 
     param = {}
@@ -104,22 +114,22 @@ def produceObj(x,y,chip, ra, dec, pa):
     obj = Star(param)
 
     header_wcs = generateExtensionHeader(chip,
-        xlen=chip.npix_x,
-        ylen=chip.npix_y,
-        ra=ra,
-        dec=dec,
-        pa=pa,
-        gain=chip.gain,
-        readout=chip.read_noise,
-        dark=chip.dark_noise,
-        saturation=90000,
-        row_num=chip.rowID,
-        col_num=chip.colID,
-        pixel_scale=chip.pix_scale,
-        pixel_size=chip.pix_size,
-        xcen=chip.x_cen,
-        ycen=chip.y_cen,
-        extName='SCI')
+                                         xlen=chip.npix_x,
+                                         ylen=chip.npix_y,
+                                         ra=ra,
+                                         dec=dec,
+                                         pa=pa,
+                                         gain=chip.gain,
+                                         readout=chip.read_noise,
+                                         dark=chip.dark_noise,
+                                         saturation=90000,
+                                         row_num=chip.rowID,
+                                         col_num=chip.colID,
+                                         pixel_scale=chip.pix_scale,
+                                         pixel_size=chip.pix_size,
+                                         xcen=chip.x_cen,
+                                         ycen=chip.y_cen,
+                                         extName='SCI')
 
     chip_wcs = galsim.FitsWCS(header=header_wcs)
     param["ra"] = chip_wcs.posToWorld(pos_img).ra.deg
@@ -143,50 +153,56 @@ def produceObj(x,y,chip, ra, dec, pa):
 class TestSpecDisperse(unittest.TestCase):
 
     def __init__(self, methodName='runTest'):
-        super(TestSpecDisperse,self).__init__(methodName)
+        super(TestSpecDisperse, self).__init__(methodName)
 
         self.filePath('csst_msc_sim/test_sls_and_straylight')
-        
+
         # self.conff = conff
         # self.throughputf = throughputf
 
-
     def filePath(self, file_name):
         fn = os.path.join(os.getenv('UNIT_TEST_DATA_ROOT'), file_name)
-        self.conff= os.path.join(fn, 'CSST_GI2.conf')
-        self.throughputf= os.path.join(fn, 'GI.Throughput.1st.fits')
+        self.conff = os.path.join(fn, 'CSST_GI2.conf')
+        self.throughputf = os.path.join(fn, 'GI.Throughput.1st.fits')
         self.testDir = fn
-        self.outDataFn = os.path.join(fn,'output')
+        self.outDataFn = os.path.join(fn, 'output')
         if os.path.isdir(self.outDataFn):
             pass
         else:
             os.mkdir(self.outDataFn)
 
     def test_rotate901(self):
-        m = np.array([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20],[21,22,23,24,25]])
-        m1 = np.array([[21,16,11,6,1],[22,17,12,7,2],[23,18,13,8,3],[24,19,14,9,4],[25,20,15,10,5]])
-        m2 = np.array([[5,10,15,20,25],[4,9,14,19,24],[3,8,13,18,23],[2,7,12,17,22],[1,6,11,16,21]])
+        m = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [
+                     16, 17, 18, 19, 20], [21, 22, 23, 24, 25]])
+        m1 = np.array([[21, 16, 11, 6, 1], [22, 17, 12, 7, 2], [
+                      23, 18, 13, 8, 3], [24, 19, 14, 9, 4], [25, 20, 15, 10, 5]])
+        m2 = np.array([[5, 10, 15, 20, 25], [4, 9, 14, 19, 24], [
+                      3, 8, 13, 18, 23], [2, 7, 12, 17, 22], [1, 6, 11, 16, 21]])
         xc = 2
         yc = 2
         isClockwise = 0
-        m1, xc1, yc1 = rotate90(array_orig=m, xc=xc, yc=yc, isClockwise=isClockwise)
+        m1, xc1, yc1 = rotate90(array_orig=m, xc=xc,
+                                yc=yc, isClockwise=isClockwise)
         self.assertTrue(xc1-xc == 0)
         self.assertTrue(yc1-yc == 0)
         self.assertTrue(np.sum(m-m1) == 0)
 
     def test_rotate902(self):
-        m = np.array([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20],[21,22,23,24,25]])
-        m1 = np.array([[21,16,11,6,1],[22,17,12,7,2],[23,18,13,8,3],[24,19,14,9,4],[25,20,15,10,5]])
-        m2 = np.array([[5,10,15,20,25],[4,9,14,19,24],[3,8,13,18,23],[2,7,12,17,22],[1,6,11,16,21]])
+        m = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [
+                     16, 17, 18, 19, 20], [21, 22, 23, 24, 25]])
+        m1 = np.array([[21, 16, 11, 6, 1], [22, 17, 12, 7, 2], [
+                      23, 18, 13, 8, 3], [24, 19, 14, 9, 4], [25, 20, 15, 10, 5]])
+        m2 = np.array([[5, 10, 15, 20, 25], [4, 9, 14, 19, 24], [
+                      3, 8, 13, 18, 23], [2, 7, 12, 17, 22], [1, 6, 11, 16, 21]])
         xc = 2
         yc = 2
-        isClockwise =1
-        m1, xc1, yc1 = rotate90(array_orig=m, xc=xc, yc=yc, isClockwise=isClockwise)
+        isClockwise = 1
+        m1, xc1, yc1 = rotate90(array_orig=m, xc=xc,
+                                yc=yc, isClockwise=isClockwise)
         self.assertTrue(xc1-xc == 0)
         self.assertTrue(yc1-yc == 0)
         self.assertTrue(np.sum(m-m2) == 0)
 
-
     def test_Specdistperse1(self):
 
         star = galsim.Gaussian(fwhm=0.39)
@@ -236,7 +252,8 @@ class TestSpecDisperse(unittest.TestCase):
         ids = wave_pix < 9700
         ids1 = wave_pix[ids] > 6500
         print('Spec disperse flux test')
-        self.assertTrue(np.mean((wave_flux[ids][ids1] - sed_i(wave_pix[ids][ids1]))/sed_i(wave_pix[ids][ids1]))<0.004)
+        self.assertTrue(np.mean(
+            (wave_flux[ids][ids1] - sed_i(wave_pix[ids][ids1]))/sed_i(wave_pix[ids][ids1])) < 0.004)
         # plt.figure()
         # plt.plot(wave_pix, wave_flux)
         # plt.plot(sed['WAVELENGTH'], sed['FLUX'])
@@ -299,14 +316,17 @@ class TestSpecDisperse(unittest.TestCase):
         input_em_lam = 6600
         ids = wave_pix < input_em_lam+200
         ids1 = wave_pix[ids] > input_em_lam-200
-        deltLamda_pix = (max(wave_pix[ids][ids1]) - min(wave_pix[ids][ids1])) / (wave_pix[ids][ids1].shape[0] - 1)
-        _, _, fwhmx, fwhmx_err, center, center_err = fit_SingleGauss(wave_pix[ids][ids1], wave_flux[ids][ids1], 1.0, 6600)
+        deltLamda_pix = (max(
+            wave_pix[ids][ids1]) - min(wave_pix[ids][ids1])) / (wave_pix[ids][ids1].shape[0] - 1)
+        _, _, fwhmx, fwhmx_err, center, center_err = fit_SingleGauss(
+            wave_pix[ids][ids1], wave_flux[ids][ids1], 1.0, 6600)
 
         print('Emission line position and shape test')
 
         self.assertTrue(input_em_lam-center < deltLamda_pix)
         # print(fwhmx/deltLamda_pix*pix_scale - psf_fwhm)
-        self.assertTrue(fwhmx/deltLamda_pix*pix_scale - psf_fwhm  < np.abs(0.02))
+        self.assertTrue(fwhmx/deltLamda_pix*pix_scale -
+                        psf_fwhm < np.abs(0.02))
         # print('error is ',np.mean((wave_flux[ids][ids1] - sed_i(wave_pix[ids][ids1]))/sed_i(wave_pix[ids][ids1])))
         # self.assertTrue(np.mean((wave_flux[ids][ids1] - sed_i(wave_pix[ids][ids1]))/sed_i(wave_pix[ids][ids1]))<0.004)
         # plt.figure()
@@ -356,7 +376,6 @@ class TestSpecDisperse(unittest.TestCase):
         for i in range(sh[1]):
             spec_pix[i] = sum(Aimg[:, i])
 
-
         wave_flux = np.zeros(wave_pix.shape[0])
         for i in np.arange(1, wave_pix.shape[0] - 1):
             w = wave_pix[i]
@@ -414,14 +433,12 @@ class TestSpecDisperse(unittest.TestCase):
         plt.legend(['one spec', 'split in 8000 A'])
         plt.show()
 
-
-
     def test_double_disperse(self):
         # work_dir = "/public/home/fangyuedong/CSST_unittest/CSST/test/"
         # data_dir = "/Volumes/Extreme SSD/SimData/"
         # data_dir = "/data/simudata/CSSOSDataProductsSims/data/"
         configFn = os.path.join(self.testDir, 'config_C6.yaml')
-        normFilterFn =  os.path.join(self.testDir, 'SLOAN_SDSS.g.fits')
+        normFilterFn = os.path.join(self.testDir, 'SLOAN_SDSS.g.fits')
         norm_star = Table.read(normFilterFn)
         with open(configFn, "r") as stream:
             try:
@@ -431,9 +448,9 @@ class TestSpecDisperse(unittest.TestCase):
             except yaml.YAMLError as exc:
                 print(exc)
 
-
         filter_param = FilterParam()
-        focal_plane = FocalPlane(survey_type=config["obs_setting"]["survey_type"])
+        focal_plane = FocalPlane(
+            survey_type=config["obs_setting"]["survey_type"])
         chip = Chip(1, config=config)
         filter_id, filter_type = chip.getChipFilter()
         filt = Filter(filter_id=filter_id, filter_type=filter_type, filter_param=filter_param,
@@ -442,13 +459,14 @@ class TestSpecDisperse(unittest.TestCase):
 
         psf_model = PSFGauss(chip=chip)
 
-
-        wcs_fp = focal_plane.getTanWCS(float(config["obs_setting"]["ra_center"]), float(config["obs_setting"]["dec_center"]), float(config["obs_setting"]["image_rot"]) * galsim.degrees, chip.pix_scale)
+        wcs_fp = focal_plane.getTanWCS(float(config["obs_setting"]["ra_center"]), float(
+            config["obs_setting"]["dec_center"]), float(config["obs_setting"]["image_rot"]) * galsim.degrees, chip.pix_scale)
         chip.img = galsim.ImageF(chip.npix_x, chip.npix_y)
         chip.img.setOrigin(chip.bound.xmin, chip.bound.ymin)
         chip.img.wcs = wcs_fp
 
-        obj, pos_img = produceObj(2000,4500, chip,float(config["obs_setting"]["ra_center"]), float(config["obs_setting"]["dec_center"]), float(config["obs_setting"]["image_rot"]))
+        obj, pos_img = produceObj(2000, 4500, chip, float(config["obs_setting"]["ra_center"]), float(
+            config["obs_setting"]["dec_center"]), float(config["obs_setting"]["image_rot"]))
         # print(pos_img,chip.pix_scale)
         obj.drawObj_slitless(
             tel=tel,
@@ -462,7 +480,8 @@ class TestSpecDisperse(unittest.TestCase):
             exptime=150,
             normFilter=norm_star)
 
-        obj, pos_img = produceObj(3685, 6500, chip,float(config["obs_setting"]["ra_center"]), float(config["obs_setting"]["dec_center"]), float(config["obs_setting"]["image_rot"]))
+        obj, pos_img = produceObj(3685, 6500, chip, float(config["obs_setting"]["ra_center"]), float(
+            config["obs_setting"]["dec_center"]), float(config["obs_setting"]["image_rot"]))
         obj.drawObj_slitless(
             tel=tel,
             pos_img=pos_img,
@@ -475,7 +494,8 @@ class TestSpecDisperse(unittest.TestCase):
             exptime=150,
             normFilter=norm_star)
 
-        obj, pos_img = produceObj(5000, 2500, chip, float(config["obs_setting"]["ra_center"]), float(config["obs_setting"]["dec_center"]), float(config["obs_setting"]["image_rot"]))
+        obj, pos_img = produceObj(5000, 2500, chip, float(config["obs_setting"]["ra_center"]), float(
+            config["obs_setting"]["dec_center"]), float(config["obs_setting"]["image_rot"]))
         obj.drawObj_slitless(
             tel=tel,
             pos_img=pos_img,
@@ -490,7 +510,8 @@ class TestSpecDisperse(unittest.TestCase):
 
         print('Spec double disperse test')
         from astropy.io import fits
-        fits.writeto(os.path.join(self.outDataFn,'test_sls_doubleDisp.fits'),chip.img.array, overwrite = True)
+        fits.writeto(os.path.join(
+            self.outDataFn, 'test_sls_doubleDisp.fits'), chip.img.array, overwrite=True)
 
         # plt.figure()
         # plt.imshow(chip.img.array)
@@ -498,7 +519,7 @@ class TestSpecDisperse(unittest.TestCase):
 
     def test_SLSImage_rotation(self):
         from astropy.wcs import WCS
-        configFn = os.path.join(self.testDir,'config_C6.yaml')
+        configFn = os.path.join(self.testDir, 'config_C6.yaml')
 
         with open(configFn, "r") as stream:
             try:
@@ -509,71 +530,71 @@ class TestSpecDisperse(unittest.TestCase):
                 print(exc)
         chip = Chip(1, config=config)
 
-        ra=float(config["obs_setting"]["ra_center"])
-        dec=float(config["obs_setting"]["dec_center"])
-        pa=float(config["obs_setting"]["image_rot"])
+        ra = float(config["obs_setting"]["ra_center"])
+        dec = float(config["obs_setting"]["dec_center"])
+        pa = float(config["obs_setting"]["image_rot"])
 
         chip.rotate_angle = 0
         header_wcs1 = generateExtensionHeader(chip,
-            xlen=chip.npix_x,
-            ylen=chip.npix_y,
-            ra=ra,
-            dec=dec,
-            pa=pa,
-            gain=chip.gain,
-            readout=chip.read_noise,
-            dark=chip.dark_noise,
-            saturation=90000,
-            pixel_scale=chip.pix_scale,
-            row_num=chip.rowID,
-            col_num=chip.colID,
-            extName='raw')
+                                              xlen=chip.npix_x,
+                                              ylen=chip.npix_y,
+                                              ra=ra,
+                                              dec=dec,
+                                              pa=pa,
+                                              gain=chip.gain,
+                                              readout=chip.read_noise,
+                                              dark=chip.dark_noise,
+                                              saturation=90000,
+                                              pixel_scale=chip.pix_scale,
+                                              row_num=chip.rowID,
+                                              col_num=chip.colID,
+                                              extName='raw')
 
         center = np.array([chip.npix_x / 2, chip.npix_y / 2])
         h_wcs1 = WCS(header_wcs1)
-        x1, y1 = center + [100,0]
-        sky_1 = h_wcs1.pixel_to_world(x1,y1)
+        x1, y1 = center + [100, 0]
+        sky_1 = h_wcs1.pixel_to_world(x1, y1)
         chip = Chip(1, config=config)
         rot_angle = 1
         chip.rotate_angle = rot_angle
         header_wcs2 = generateExtensionHeader(chip,
-            xlen=chip.npix_x,
-            ylen=chip.npix_y,
-            ra=ra,
-            dec=dec,
-            pa=pa,
-            gain=chip.gain,
-            readout=chip.read_noise,
-            dark=chip.dark_noise,
-            saturation=90000,
-            pixel_scale=chip.pix_scale,
-            row_num=chip.rowID,
-            col_num=chip.colID,
-            extName='raw')
+                                              xlen=chip.npix_x,
+                                              ylen=chip.npix_y,
+                                              ra=ra,
+                                              dec=dec,
+                                              pa=pa,
+                                              gain=chip.gain,
+                                              readout=chip.read_noise,
+                                              dark=chip.dark_noise,
+                                              saturation=90000,
+                                              pixel_scale=chip.pix_scale,
+                                              row_num=chip.rowID,
+                                              col_num=chip.colID,
+                                              extName='raw')
 
         h_wcs2 = WCS(header_wcs2)
         x2, y2 = h_wcs2.world_to_pixel(sky_1)
-        angle = getAngle132(x1,y1,0,x2,y2,0,center[0],center[1],0)
+        angle = getAngle132(x1, y1, 0, x2, y2, 0, center[0], center[1], 0)
 
         # print("rotation angle:" ,rot_angle ,chip.rotate_angle, angle)
         # self.assertTrue(rot_angle - angle < np.abs(0.001))
 
         rot_angle = 10
-        chip.rotate_angle =  rot_angle
+        chip.rotate_angle = rot_angle
         header_wcs2 = generateExtensionHeader(chip,
-            xlen=chip.npix_x,
-            ylen=chip.npix_y,
-            ra=ra,
-            dec=dec,
-            pa=pa,
-            gain=chip.gain,
-            readout=chip.read_noise,
-            dark=chip.dark_noise,
-            saturation=90000,
-            pixel_scale=chip.pix_scale,
-            row_num=chip.rowID,
-            col_num=chip.colID,
-            extName='raw')
+                                              xlen=chip.npix_x,
+                                              ylen=chip.npix_y,
+                                              ra=ra,
+                                              dec=dec,
+                                              pa=pa,
+                                              gain=chip.gain,
+                                              readout=chip.read_noise,
+                                              dark=chip.dark_noise,
+                                              saturation=90000,
+                                              pixel_scale=chip.pix_scale,
+                                              row_num=chip.rowID,
+                                              col_num=chip.colID,
+                                              extName='raw')
 
         h_wcs2 = WCS(header_wcs2)
         x2, y2 = h_wcs2.world_to_pixel(sky_1)
@@ -584,19 +605,19 @@ class TestSpecDisperse(unittest.TestCase):
         rot_angle = 50
         chip.rotate_angle = rot_angle
         header_wcs2 = generateExtensionHeader(chip,
-            xlen=chip.npix_x,
-            ylen=chip.npix_y,
-            ra=ra,
-            dec=dec,
-            pa=pa,
-            gain=chip.gain,
-            readout=chip.read_noise,
-            dark=chip.dark_noise,
-            saturation=90000,
-            pixel_scale=chip.pix_scale,
-            row_num=chip.rowID,
-            col_num=chip.colID,
-            extName='raw')
+                                              xlen=chip.npix_x,
+                                              ylen=chip.npix_y,
+                                              ra=ra,
+                                              dec=dec,
+                                              pa=pa,
+                                              gain=chip.gain,
+                                              readout=chip.read_noise,
+                                              dark=chip.dark_noise,
+                                              saturation=90000,
+                                              pixel_scale=chip.pix_scale,
+                                              row_num=chip.rowID,
+                                              col_num=chip.colID,
+                                              extName='raw')
 
         h_wcs2 = WCS(header_wcs2)
         x2, y2 = h_wcs2.world_to_pixel(sky_1)
@@ -604,7 +625,6 @@ class TestSpecDisperse(unittest.TestCase):
         # print(rot_angle - angle)
         self.assertTrue(rot_angle - angle < np.abs(0.001))
 
-
         chip = Chip(27, config=config)
 
         ra = float(config["obs_setting"]["ra_center"])
@@ -612,19 +632,19 @@ class TestSpecDisperse(unittest.TestCase):
         pa = float(config["obs_setting"]["image_rot"])
         chip.rotate_angle = 0
         header_wcs1 = generateExtensionHeader(chip,
-            xlen=chip.npix_x,
-            ylen=chip.npix_y,
-            ra=ra,
-            dec=dec,
-            pa=pa,
-            gain=chip.gain,
-            readout=chip.read_noise,
-            dark=chip.dark_noise,
-            saturation=90000,
-            pixel_scale=chip.pix_scale,
-            row_num=chip.rowID,
-            col_num=chip.colID,
-            extName='raw')
+                                              xlen=chip.npix_x,
+                                              ylen=chip.npix_y,
+                                              ra=ra,
+                                              dec=dec,
+                                              pa=pa,
+                                              gain=chip.gain,
+                                              readout=chip.read_noise,
+                                              dark=chip.dark_noise,
+                                              saturation=90000,
+                                              pixel_scale=chip.pix_scale,
+                                              row_num=chip.rowID,
+                                              col_num=chip.colID,
+                                              extName='raw')
 
         center = np.array([chip.npix_x / 2, chip.npix_y / 2])
         h_wcs1 = WCS(header_wcs1)
@@ -634,19 +654,19 @@ class TestSpecDisperse(unittest.TestCase):
         rot_angle = 1
         chip.rotate_angle = rot_angle
         header_wcs2 = generateExtensionHeader(chip,
-            xlen=chip.npix_x,
-            ylen=chip.npix_y,
-            ra=ra,
-            dec=dec,
-            pa=pa,
-            gain=chip.gain,
-            readout=chip.read_noise,
-            dark=chip.dark_noise,
-            saturation=90000,
-            pixel_scale=chip.pix_scale,
-            row_num=chip.rowID,
-            col_num=chip.colID,
-            extName='raw')
+                                              xlen=chip.npix_x,
+                                              ylen=chip.npix_y,
+                                              ra=ra,
+                                              dec=dec,
+                                              pa=pa,
+                                              gain=chip.gain,
+                                              readout=chip.read_noise,
+                                              dark=chip.dark_noise,
+                                              saturation=90000,
+                                              pixel_scale=chip.pix_scale,
+                                              row_num=chip.rowID,
+                                              col_num=chip.colID,
+                                              extName='raw')
 
         h_wcs2 = WCS(header_wcs2)
         x2, y2 = h_wcs2.world_to_pixel(sky_1)
@@ -657,19 +677,19 @@ class TestSpecDisperse(unittest.TestCase):
         rot_angle = 10
         chip.rotate_angle = rot_angle
         header_wcs2 = generateExtensionHeader(chip,
-            xlen=chip.npix_x,
-            ylen=chip.npix_y,
-            ra=ra,
-            dec=dec,
-            pa=pa,
-            gain=chip.gain,
-            readout=chip.read_noise,
-            dark=chip.dark_noise,
-            saturation=90000,
-            pixel_scale=chip.pix_scale,
-            row_num=chip.rowID,
-            col_num=chip.colID,
-            extName='raw')
+                                              xlen=chip.npix_x,
+                                              ylen=chip.npix_y,
+                                              ra=ra,
+                                              dec=dec,
+                                              pa=pa,
+                                              gain=chip.gain,
+                                              readout=chip.read_noise,
+                                              dark=chip.dark_noise,
+                                              saturation=90000,
+                                              pixel_scale=chip.pix_scale,
+                                              row_num=chip.rowID,
+                                              col_num=chip.colID,
+                                              extName='raw')
 
         h_wcs2 = WCS(header_wcs2)
         x2, y2 = h_wcs2.world_to_pixel(sky_1)
@@ -680,19 +700,19 @@ class TestSpecDisperse(unittest.TestCase):
         rot_angle = 50
         chip.rotate_angle = rot_angle
         header_wcs2 = generateExtensionHeader(chip,
-            xlen=chip.npix_x,
-            ylen=chip.npix_y,
-            ra=ra,
-            dec=dec,
-            pa=pa,
-            gain=chip.gain,
-            readout=chip.read_noise,
-            dark=chip.dark_noise,
-            saturation=90000,
-            pixel_scale=chip.pix_scale,
-            row_num=chip.rowID,
-            col_num=chip.colID,
-            extName='raw')
+                                              xlen=chip.npix_x,
+                                              ylen=chip.npix_y,
+                                              ra=ra,
+                                              dec=dec,
+                                              pa=pa,
+                                              gain=chip.gain,
+                                              readout=chip.read_noise,
+                                              dark=chip.dark_noise,
+                                              saturation=90000,
+                                              pixel_scale=chip.pix_scale,
+                                              row_num=chip.rowID,
+                                              col_num=chip.colID,
+                                              extName='raw')
 
         h_wcs2 = WCS(header_wcs2)
         x2, y2 = h_wcs2.world_to_pixel(sky_1)
@@ -701,11 +721,9 @@ class TestSpecDisperse(unittest.TestCase):
         self.assertTrue(rot_angle - angle < np.abs(0.001))
 
 
-
-
 if __name__ == '__main__':
 
-    os.environ['UNIT_TEST_DATA_ROOT']="/Users/zhangxin/Work/SlitlessSim/CSST_SIM/CSST_develop/csst-simulation/tests/testData"
+    os.environ['UNIT_TEST_DATA_ROOT'] = "/Users/zhangxin/Work/SlitlessSim/CSST_SIM/CSST_develop/csst-simulation/tests/testData"
     testDir = os.getenv('UNIT_TEST_DATA_ROOT')
     # conff= os.path.join(testDir, 'CSST_GI2.conf')
     # throughputf= os.path.join(testDir, 'GI.Throughput.1st.fits')
@@ -723,4 +741,4 @@ if __name__ == '__main__':
 
     unittest.TextTestRunner(verbosity=2).run(suit)
     # runner = unittest.TextTestRunner()
-    # runner.run(suit)
\ No newline at end of file
+    # runner.run(suit)
diff --git a/tests/test_Straylight.py b/tests/test_Straylight.py
index 97761f7a4f7f93dcc5794a88ae5c2f78a6fd15ec..90f82a98a85da31fae83b1096be593d4634b1047 100644
--- a/tests/test_Straylight.py
+++ b/tests/test_Straylight.py
@@ -1,10 +1,10 @@
 #
-#need add environment parameter  UNIT_TEST_DATA_ROOT, link to "testData/"
-#linx and mac can run as follow, need modify the name of file directory
-#export UNIT_TEST_DATA_ROOT=/Users/zhangxin/Work/SlitlessSim/CSST_SIM/CSST_develop/csst-simulation/tests/testData
+# need add environment parameter  UNIT_TEST_DATA_ROOT, link to "testData/"
+# linx and mac can run as follow, need modify the name of file directory
+# export UNIT_TEST_DATA_ROOT=/Users/zhangxin/Work/SlitlessSim/CSST_SIM/CSST_develop/csst-simulation/tests/testData
 #
 import unittest
-from ObservationSim.Straylight import Straylight
+from observation_sim.sky_background import Straylight
 
 import numpy as np
 import math
@@ -17,8 +17,10 @@ import matplotlib.pyplot as plt
 
 import os
 
-hubbleAverZodiacal = {'nuv':0.0035,'u':0.0163,'g':0.1109,'r':0.1471,'i':0.1568,'z':0.0953,'y':0.0283}
-hubbleAverEarthShine = {'nuv':0.00024,'u':0.0051,'g':0.0506,'r':0.0591,'i':0.0568,'z':0.0315,'y':0.0090}
+hubbleAverZodiacal = {'nuv': 0.0035, 'u': 0.0163, 'g': 0.1109,
+                      'r': 0.1471, 'i': 0.1568, 'z': 0.0953, 'y': 0.0283}
+hubbleAverEarthShine = {'nuv': 0.00024, 'u': 0.0051, 'g': 0.0506,
+                        'r': 0.0591, 'i': 0.0568, 'z': 0.0315, 'y': 0.0090}
 
 # def transRaDec2D(ra, dec):
 #     x1 = np.cos(dec / 57.2957795) * np.cos(ra / 57.2957795);
@@ -28,63 +30,69 @@ hubbleAverEarthShine = {'nuv':0.00024,'u':0.0051,'g':0.0506,'r':0.0591,'i':0.056
 
 
 def getAngle132(x1=0, y1=0, z1=0, x2=0, y2=0, z2=0, x3=0, y3=0, z3=0):
-    cosValue = 0;
-    angle = 0;
+    cosValue = 0
+    angle = 0
 
-    x11 = x1 - x3;
-    y11 = y1 - y3;
-    z11 = z1 - z3;
+    x11 = x1 - x3
+    y11 = y1 - y3
+    z11 = z1 - z3
 
-    x22 = x2 - x3;
-    y22 = y2 - y3;
-    z22 = z2 - z3;
+    x22 = x2 - x3
+    y22 = y2 - y3
+    z22 = z2 - z3
 
-    tt = np.sqrt((x11 * x11 + y11 * y11 + z11 * z11) * (x22 * x22 + y22 * y22 + z22 * z22));
+    tt = np.sqrt((x11 * x11 + y11 * y11 + z11 * z11)
+                 * (x22 * x22 + y22 * y22 + z22 * z22))
     if (tt == 0):
-        return 0;
+        return 0
 
-    cosValue = (x11 * x22 + y11 * y22 + z11 * z22) / tt;
+    cosValue = (x11 * x22 + y11 * y22 + z11 * z22) / tt
 
     if (cosValue > 1):
-        cosValue = 1;
+        cosValue = 1
     if (cosValue < -1):
-        cosValue = -1;
-    angle = math.acos(cosValue);
-    return angle * 360 / (2 * math.pi);
+        cosValue = -1
+    angle = math.acos(cosValue)
+    return angle * 360 / (2 * math.pi)
 
-def calculateAnglePwithEarth(sat = np.array([0,0,0]), pointing = np.array([0,0,0]), sun = np.array([0,0,0])):
+
+def calculateAnglePwithEarth(sat=np.array([0, 0, 0]), pointing=np.array([0, 0, 0]), sun=np.array([0, 0, 0])):
     modSat = np.sqrt(sat[0]*sat[0] + sat[1]*sat[1]+sat[2]*sat[2])
-    modPoint = np.sqrt(pointing[0]*pointing[0] + pointing[1]*pointing[1] + pointing[2]*pointing[2])
-    withLocalZenithAngle = (pointing[0] * sat[0] + pointing[1] * sat[1] + pointing[2] * sat[2]) / (modPoint*modSat)
+    modPoint = np.sqrt(pointing[0]*pointing[0] +
+                       pointing[1]*pointing[1] + pointing[2]*pointing[2])
+    withLocalZenithAngle = (
+        pointing[0] * sat[0] + pointing[1] * sat[1] + pointing[2] * sat[2]) / (modPoint*modSat)
 
     innerM_sat_sun = sat[0] * sun[0] + sat[1] * sun[1] + sat[2] * sun[2]
     cosAngle = innerM_sat_sun / (modSat * cons.au.value/1000)
     isInSunSide = 1
-    if (cosAngle < -0.3385737): #cos109.79
-        isInSunSide = -1;
+    if (cosAngle < -0.3385737):  # cos109.79
+        isInSunSide = -1
     elif cosAngle >= -0.3385737 and cosAngle <= 0.3385737:
-        isInSunSide = 0;
+        isInSunSide = 0
+
+    return math.acos(withLocalZenithAngle)*180/math.pi, isInSunSide
 
-    return math.acos(withLocalZenithAngle)*180/math.pi,isInSunSide
 
 class TestStraylight(unittest.TestCase):
 
-    def __init__(self,methodName='runTest', filter = 'i', grating = "GI"):
-        super(TestStraylight,self).__init__(methodName)
+    def __init__(self, methodName='runTest', filter='i', grating="GI"):
+        super(TestStraylight, self).__init__(methodName)
         # print(file_name)
         # fn = os.path.join(os.getenv('UNIT_TEST_DATA_ROOT'), file_name)
         # self.pointingData = np.loadtxt(os.path.join(fn, 'Straylight_test.dat'), dtype=np.double)
         self.filePath('csst_msc_sim/test_sls_and_straylight')
         self.filter = filter
         self.grating = grating
-        
+
     def filePath(self, file_name):
         fn = os.path.join(os.getenv('UNIT_TEST_DATA_ROOT'), file_name)
-        self.pointingData = np.loadtxt(os.path.join(fn, 'Straylight_test.dat'), dtype=np.double)
+        self.pointingData = np.loadtxt(os.path.join(
+            fn, 'Straylight_test.dat'), dtype=np.double)
 
     def test_EarthShineFilter(self):
         d_sh = self.pointingData.shape
-        sl_e_pix = np.zeros([d_sh[0],3],dtype=np.double)
+        sl_e_pix = np.zeros([d_sh[0], 3], dtype=np.double)
 
         for i in np.arange(d_sh[0]):
             # if i > 50:
@@ -92,17 +100,19 @@ class TestStraylight(unittest.TestCase):
             ju = self.pointingData[i, 5]
             # pointing = transRaDec2D(self.pointingData[i, 0], self.pointingData[i, 1])
             # print(ju, pointing, surveylist[i,3:9])
-            sl = Straylight(jtime=ju, sat_pos=self.pointingData[i, 6:9], pointing_radec=np.array([self.pointingData[i, 0], self.pointingData[i, 1]]),sun_pos=self.pointingData[i,9:12])
+            sl = Straylight(jtime=ju, sat_pos=self.pointingData[i, 6:9], pointing_radec=np.array(
+                [self.pointingData[i, 0], self.pointingData[i, 1]]), sun_pos=self.pointingData[i, 9:12])
             e1, py = sl.calculateEarthShineFilter(filter=self.filter)
-            earthZenithAngle, isInSunSide = calculateAnglePwithEarth(sat=self.pointingData[i, 6:9], pointing= sl.pointing, sun=self.pointingData[i,9:12])
+            earthZenithAngle, isInSunSide = calculateAnglePwithEarth(
+                sat=self.pointingData[i, 6:9], pointing=sl.pointing, sun=self.pointingData[i, 9:12])
             # e2, _ = sl.calculateZodiacalFilter2(filter='i', sun_pos=sl.sun_pos)
             # e3 = sl.calculateStarLightFilter(filter='i', pointYaxis=py)
             # e_all = sl.calculateStrayLightFilter(filter='i')
             # s_pix, spec = sl.calculateStrayLightGrating(grating='GI')
-            sl_e_pix[i,0] = e1
+            sl_e_pix[i, 0] = e1
             sl_e_pix[i, 1] = earthZenithAngle
             sl_e_pix[i, 2] = isInSunSide
-        median  = np.median(sl_e_pix[:,0])
+        median = np.median(sl_e_pix[:, 0])
         print(' average Earthshine %s: %e' % (self.filter, median))
         self.assertTrue(median-hubbleAverEarthShine[self.filter] < 0.1)
         plt.figure()
@@ -117,27 +127,29 @@ class TestStraylight(unittest.TestCase):
 
     def test_ZodiacalFilter(self):
         d_sh = self.pointingData.shape
-        sl_e_pix = np.zeros([d_sh[0],2],dtype=np.double)
+        sl_e_pix = np.zeros([d_sh[0], 2], dtype=np.double)
 
         for i in np.arange(d_sh[0]):
             ju = self.pointingData[i, 5]
-            sl = Straylight(jtime=ju, sat_pos=self.pointingData[i, 6:9], pointing_radec=np.array([self.pointingData[i, 0], self.pointingData[i, 1]]),sun_pos=self.pointingData[i,9:12])
-            e1, _ = sl.calculateZodiacalFilter2(filter=self.filter, sun_pos=sl.sun_pos)
-            sl_e_pix[i,0] = e1
-            sl_e_pix[i,1] = getAngle132(x1=self.pointingData[i,9], y1=self.pointingData[i,10], z1=self.pointingData[i,11], x2=sl.pointing[0],
-                                        y2=sl.pointing[1], z2=sl.pointing[2], x3=0, y3=0, z3=0)
+            sl = Straylight(jtime=ju, sat_pos=self.pointingData[i, 6:9], pointing_radec=np.array(
+                [self.pointingData[i, 0], self.pointingData[i, 1]]), sun_pos=self.pointingData[i, 9:12])
+            e1, _ = sl.calculateZodiacalFilter2(
+                filter=self.filter, sun_pos=sl.sun_pos)
+            sl_e_pix[i, 0] = e1
+            sl_e_pix[i, 1] = getAngle132(x1=self.pointingData[i, 9], y1=self.pointingData[i, 10], z1=self.pointingData[i, 11], x2=sl.pointing[0],
+                                         y2=sl.pointing[1], z2=sl.pointing[2], x3=0, y3=0, z3=0)
         plt.figure()
         plt.plot(sl_e_pix[:, 0], sl_e_pix[:, 1], 'r.')
         plt.xlabel('straylight-zodiacal(e-/pixel/s)')
         plt.ylabel('Angle between pointing and sun(degree)')
         plt.show()
-        median  = np.median(sl_e_pix[:,0])
+        median = np.median(sl_e_pix[:, 0])
         print(' average Zodiacal %s: %f' % (self.filter, median))
         self.assertTrue(median-hubbleAverZodiacal[self.filter] < 0.1)
 
     def test_StarFilter(self):
         d_sh = self.pointingData.shape
-        sl_e_pix = np.zeros(d_sh[0],dtype=np.double)
+        sl_e_pix = np.zeros(d_sh[0], dtype=np.double)
 
         tnum = 10
         for i in np.arange(tnum):
@@ -146,20 +158,21 @@ class TestStraylight(unittest.TestCase):
             ju = self.pointingData[i, 5]
             # pointing = transRaDec2D(self.pointingData[i, 0], self.pointingData[i, 1])
             # print(ju, pointing, surveylist[i,3:9])
-            sl = Straylight(jtime=ju, sat_pos=self.pointingData[i, 6:9], pointing_radec=np.array([self.pointingData[i, 0], self.pointingData[i, 1]]),sun_pos=self.pointingData[i,9:12])
+            sl = Straylight(jtime=ju, sat_pos=self.pointingData[i, 6:9], pointing_radec=np.array(
+                [self.pointingData[i, 0], self.pointingData[i, 1]]), sun_pos=self.pointingData[i, 9:12])
             e1, py = sl.calculateEarthShineFilter(filter=self.filter)
             # e2, _ = sl.calculateZodiacalFilter2(filter='i', sun_pos=sl.sun_pos)
             e3 = sl.calculateStarLightFilter(filter=self.filter, pointYaxis=py)
             # e_all = sl.calculateStrayLightFilter(filter='i')
             # s_pix, spec = sl.calculateStrayLightGrating(grating='GI')
             sl_e_pix[i] = e3
-        median  = np.median(sl_e_pix[0:tnum])
+        median = np.median(sl_e_pix[0:tnum])
         print(' average Earthshine %s: %e' % (self.filter, median))
         self.assertTrue(median-hubbleAverEarthShine[self.filter] < 0.2)
 
     def test_GratingStraylight(self):
         d_sh = self.pointingData.shape
-        sl_e_pix = np.zeros(d_sh[0],dtype=np.double)
+        sl_e_pix = np.zeros(d_sh[0], dtype=np.double)
 
         tnum = 10
         for i in np.arange(tnum):
@@ -168,7 +181,8 @@ class TestStraylight(unittest.TestCase):
             ju = self.pointingData[i, 5]
             # pointing = transRaDec2D(self.pointingData[i, 0], self.pointingData[i, 1])
             # print(ju, pointing, surveylist[i,3:9])
-            sl = Straylight(jtime=ju, sat_pos=self.pointingData[i, 6:9], pointing_radec=np.array([self.pointingData[i, 0], self.pointingData[i, 1]]),sun_pos=self.pointingData[i,9:12])
+            sl = Straylight(jtime=ju, sat_pos=self.pointingData[i, 6:9], pointing_radec=np.array(
+                [self.pointingData[i, 0], self.pointingData[i, 1]]), sun_pos=self.pointingData[i, 9:12])
             # e1, py = sl.calculateEarthShineFilter(filter=self.filter)
             # e2, _ = sl.calculateZodiacalFilter2(filter='i', sun_pos=sl.sun_pos)
             # e3 = sl.calculateStarLightFilter(filter=self.filter, pointYaxis=py)
@@ -179,18 +193,15 @@ class TestStraylight(unittest.TestCase):
         plt.plot(spec['WAVELENGTH'], spec['FLUX'], 'r')
         plt.xlabel('WAVELENGTH')
         plt.ylabel('F$\lambda$(erg/s/cm2/A/arcsec2)')
-        plt.xlim(2000,10000)
+        plt.xlim(2000, 10000)
         plt.show()
-        median  = np.median(sl_e_pix[0:tnum])
+        median = np.median(sl_e_pix[0:tnum])
         print(' average Earthshine %s: %e' % (self.grating, median))
         self.assertTrue(median < 0.8)
 
 
-
-
-
 if __name__ == '__main__':
-    os.environ['UNIT_TEST_DATA_ROOT']="/Users/zhangxin/Work/SlitlessSim/CSST_SIM/CSST_develop/csst-simulation/tests/testData"
+    os.environ['UNIT_TEST_DATA_ROOT'] = "/Users/zhangxin/Work/SlitlessSim/CSST_SIM/CSST_develop/csst-simulation/tests/testData"
 
     # suit = unittest.TestSuite()
     # case1 = TestStraylight('test_EarthShineFilter', filter = 'i')
@@ -201,4 +212,4 @@ if __name__ == '__main__':
     # suit.addTest(case3)
     # case4 = TestStraylight('test_GratingStraylight', grating = 'GI')
     # suit.addTest(case4)
-    # unittest.TextTestRunner(verbosity=2).run(suit)
\ No newline at end of file
+    # unittest.TextTestRunner(verbosity=2).run(suit)
diff --git a/tests/test_astrometry.py b/tests/test_astrometry.py
index e073ac97bfdead3e2195c4a114c65e6b95ec1343..3e84e7d4bac1508c9c371fe774d10339d39ccf12 100644
--- a/tests/test_astrometry.py
+++ b/tests/test_astrometry.py
@@ -4,7 +4,7 @@ import sys
 from astropy.time import Time
 from datetime import datetime
 
-from ObservationSim.Astrometry.Astrometry_util import on_orbit_obs_position
+from observation_sim.astrometry.Astrometry_util import on_orbit_obs_position
 
 
 class TestAstrometry(unittest.TestCase):
diff --git a/tests/test_darknoise_func.py b/tests/test_darknoise_func.py
index 92a1e5d36eed4d7639b3c3b362d90e0ad7afaca4..42bf398a5b4d5114f67377aff8f45931843e191d 100644
--- a/tests/test_darknoise_func.py
+++ b/tests/test_darknoise_func.py
@@ -1,19 +1,22 @@
 import unittest
 
-import sys,os,math
+import sys
+import os
+import math
 from itertools import islice
 import numpy as np
 import galsim
 import yaml
 
-from ObservationSim.Instrument import Chip, Filter, FilterParam, FocalPlane
-#from ObservationSim.Instrument.Chip import ChipUtils as chip_utils
+from observation_sim.instruments import Chip, Filter, FilterParam, FocalPlane
 
 ### test FUNCTION --- START ###
+
+
 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:
@@ -25,8 +28,8 @@ 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
 ### test FUNCTION --- END ###
 
@@ -35,16 +38,18 @@ def defineCCD(iccd, config_file):
     with open(config_file, "r") as stream:
         try:
             config = yaml.safe_load(stream)
-            #for key, value in config.items():
+            # for key, value in config.items():
             #    print (key + " : " + str(value))
         except yaml.YAMLError as exc:
             print(exc)
     chip = Chip(chipID=iccd, config=config)
     chip.img = galsim.ImageF(chip.npix_x, chip.npix_y)
     focal_plane = FocalPlane(chip_list=[iccd])
-    chip.img.wcs= focal_plane.getTanWCS(192.8595, 27.1283, -113.4333*galsim.degrees, chip.pix_scale)
+    chip.img.wcs = focal_plane.getTanWCS(
+        192.8595, 27.1283, -113.4333*galsim.degrees, chip.pix_scale)
     return chip
 
+
 def defineFilt(chip):
     filter_param = FilterParam()
     filter_id, filter_type = chip.getChipFilter()
@@ -60,7 +65,8 @@ def defineFilt(chip):
 class detModule_coverage(unittest.TestCase):
     def __init__(self, methodName='runTest'):
         super(detModule_coverage, self).__init__(methodName)
-        self.dataPath = os.path.join(os.getenv('UNIT_TEST_DATA_ROOT'), 'csst_msc_sim/csst_fz_msc')
+        self.dataPath = os.path.join(
+            os.getenv('UNIT_TEST_DATA_ROOT'), 'csst_msc_sim/csst_fz_msc')
         self.iccd = 1
 
     def test_add_dark(self):
@@ -70,16 +76,19 @@ class detModule_coverage(unittest.TestCase):
         print(chip.chipID)
         print(chip.cen_pix_x, chip.cen_pix_y)
 
-        exptime=150.
-        base_img = get_base_img(img=chip.img, chip=chip, read_noise=chip.read_noise, readout_time=chip.readout_time, dark_noise=chip.dark_noise, exptime=exptime, InputDark=None)
+        exptime = 150.
+        base_img = get_base_img(img=chip.img, chip=chip, read_noise=chip.read_noise,
+                                readout_time=chip.readout_time, dark_noise=chip.dark_noise, exptime=exptime, InputDark=None)
 
         ny = int(chip.npix_y/2)
-        self.assertTrue( np.abs(np.max(base_img) - (exptime*chip.dark_noise+(ny-1)*(chip.readout_time/ny)*chip.dark_noise )) < 1e-6 )
-        self.assertTrue( np.min(base_img) == 3 )
+        self.assertTrue(np.abs(np.max(base_img) - (exptime*chip.dark_noise +
+                        (ny-1)*(chip.readout_time/ny)*chip.dark_noise)) < 1e-6)
+        self.assertTrue(np.min(base_img) == 3)
 
-        base_img = get_base_img(img=chip.img, chip=chip, read_noise=chip.read_noise, readout_time=chip.readout_time, dark_noise=chip.dark_noise, exptime=150., InputDark="testTag")
-        self.assertTrue( np.abs(np.max(base_img) - ((ny-1)*(chip.readout_time/ny)*chip.dark_noise )) < 1e-6 )
-        
+        base_img = get_base_img(img=chip.img, chip=chip, read_noise=chip.read_noise,
+                                readout_time=chip.readout_time, dark_noise=chip.dark_noise, exptime=150., InputDark="testTag")
+        self.assertTrue(np.abs(np.max(base_img) - ((ny-1) *
+                        (chip.readout_time/ny)*chip.dark_noise)) < 1e-6)
 
 
 if __name__ == '__main__':
diff --git a/tests/test_effect_unit.py b/tests/test_effect_unit.py
index d77c9b0bd84e8b0faeebb90270e953be9005ecf2..2a3bc46b9a029f8f767aa17ca9ae3be3b35dd6ba 100644
--- a/tests/test_effect_unit.py
+++ b/tests/test_effect_unit.py
@@ -1,9 +1,12 @@
 import unittest
 import numpy as np
-from ObservationSim.Instrument.Chip import Effects
+from observation_sim.instruments.chip import effects
 import galsim
 import matplotlib.pyplot as plt
-import os,sys,math,copy
+import os
+import sys
+import math
+import copy
 from numpy.random import Generator, PCG64
 import warnings
 from astropy.io import fits
@@ -13,20 +16,20 @@ warnings.filterwarnings("ignore", '.*Numba.*',)
 width = 9216
 height = 9232
 
+
 class DetTest(unittest.TestCase):
 
     def __init__(self, methodName='runTest'):
-        super(DetTest,self).__init__(methodName)
+        super(DetTest, self).__init__(methodName)
         self.filePath('csst_msc_sim/test_sls_and_straylight')
 
     def filePath(self, file_name):
         self.datafn = os.path.join(os.getenv('UNIT_TEST_DATA_ROOT'), file_name)
-        self.outDataFn = os.path.join(self.datafn,'output')
+        self.outDataFn = os.path.join(self.datafn, 'output')
         if os.path.isdir(self.outDataFn):
             pass
         else:
             os.mkdir(self.outDataFn)
-        
 
     def test_prnu(self):
         '''
@@ -35,13 +38,14 @@ class DetTest(unittest.TestCase):
         print('PRNU Test:')
         sigma = 0.01
         seed = 20210911
-        prnuimg = Effects.PRNU_Img(width, height, sigma=sigma, seed=seed)
+        prnuimg = effects.PRNU_Img(width, height, sigma=sigma, seed=seed)
         meanval, stdval = np.mean(prnuimg.array), np.std(prnuimg.array)
-        print('  Mean & STDDEV of PRNU image are %6.4f & %6.4f.' % (meanval, stdval))
+        print('  Mean & STDDEV of PRNU image are %6.4f & %6.4f.' %
+              (meanval, stdval))
         print('  PRNU Image Array:')
-        print('  ',prnuimg.array)
-        self.assertTrue(np.abs(meanval-1)<1e-6)
-        self.assertTrue(np.abs(stdval-sigma)<0.002)
+        print('  ', prnuimg.array)
+        self.assertTrue(np.abs(meanval-1) < 1e-6)
+        self.assertTrue(np.abs(stdval-sigma) < 0.002)
         print('\nUnit test for PRNU has been passed.')
         del prnuimg
 
@@ -50,15 +54,17 @@ class DetTest(unittest.TestCase):
         Test add dark current to image. Expected result: an image with dark current 3.4 e- and noise=1.844 e-.
         '''
         rng_poisson = galsim.BaseDeviate(20210911)
-        dark_noise = galsim.DeviateNoise(galsim.PoissonDeviate(rng_poisson, 0.02*(150+0.5*40)))
-        img = galsim.Image(200,200,dtype=np.float32, init_value=0)
-        print('Initial Mean & STD = %6.3f & %6.3f' % (np.mean(img.array), np.std(img.array)))
+        dark_noise = galsim.DeviateNoise(
+            galsim.PoissonDeviate(rng_poisson, 0.02*(150+0.5*40)))
+        img = galsim.Image(200, 200, dtype=np.float32, init_value=0)
+        print('Initial Mean & STD = %6.3f & %6.3f' %
+              (np.mean(img.array), np.std(img.array)))
         img.addNoise(dark_noise)
         meanval = np.mean(img.array)
         stdval = np.std(img.array)
         print('Dark added Mean & STD = %6.3f & %6.3f' % (meanval, stdval))
-        self.assertTrue(np.abs(meanval-3.4)<0.05)
-        self.assertTrue(np.abs(stdval-1.844)<0.02)
+        self.assertTrue(np.abs(meanval-3.4) < 0.05)
+        self.assertTrue(np.abs(stdval-1.844) < 0.02)
         print('\nUnit test for dark current has been passed.')
         del img
 
@@ -66,149 +72,161 @@ class DetTest(unittest.TestCase):
         '''
         Test saturation and bleeding. Expected result: an image with bleeding effect.
         '''
-        img = galsim.Image(500,500,dtype=np.float32)
-        star = galsim.Gaussian(flux=60e5,fwhm=3)
-        img = star.drawImage(image=img,center=(150,200))
+        img = galsim.Image(500, 500, dtype=np.float32)
+        star = galsim.Gaussian(flux=60e5, fwhm=3)
+        img = star.drawImage(image=img, center=(150, 200))
         # gal = galsim.Sersic(n=1, half_light_radius=3,flux=50e5)
         # img = gal.drawImage(image=img,center=(350,300))
         img.addNoise(galsim.GaussianNoise(sigma=7))
         # plt.imshow(img.array)
         # plt.show()
-        filename1 = os.path.join(self.outDataFn,'test_satu_initimg.fits')
+        filename1 = os.path.join(self.outDataFn, 'test_satu_initimg.fits')
         img.write(filename1)
-        newimg = Effects.SaturBloom(img, fullwell=9e4)
+        newimg = effects.SaturBloom(img, fullwell=9e4)
         # plt.imshow(newimg.array)
         # plt.show()
-        filename2 = os.path.join(self.outDataFn,'test_satu_bleedimg.fits')
+        filename2 = os.path.join(self.outDataFn, 'test_satu_bleedimg.fits')
         newimg.write(filename2)
-        del img,newimg, star
+        del img, newimg, star
 
     def test_nonlinear(self):
         '''
         Test non-linear effect. Expected result: an image with non-linearity effect.
         '''
-        imgarr = np.arange(1,9e4,4).reshape((150,150))
+        imgarr = np.arange(1, 9e4, 4).reshape((150, 150))
         img = galsim.Image(copy.deepcopy(imgarr))
-        filename1 = os.path.join(self.outDataFn,'test_nonlinear_initimg.fits')
+        filename1 = os.path.join(self.outDataFn, 'test_nonlinear_initimg.fits')
         img.write(filename1)
-        newimg = Effects.NonLinearity(img, beta1=5E-7, beta2=0)
-        filename2 = os.path.join(self.outDataFn,'test_nonlinear_finalimg.fits')
+        newimg = effects.NonLinearity(img, beta1=5E-7, beta2=0)
+        filename2 = os.path.join(
+            self.outDataFn, 'test_nonlinear_finalimg.fits')
         newimg.write(filename2)
         plt.scatter(imgarr.flatten(), newimg.array.flatten(), s=2, alpha=0.5)
-        plt.plot([-1e3,9e4],[-1e3,9e4],color='black', lw=1, ls='--')
+        plt.plot([-1e3, 9e4], [-1e3, 9e4], color='black', lw=1, ls='--')
         plt.xlabel('input (e-)')
         plt.ylabel('output (e-)')
-        plt.savefig(os.path.join(self.outDataFn,'test_nonlinearity.png'), dpi=200)
+        plt.savefig(os.path.join(self.outDataFn,
+                    'test_nonlinearity.png'), dpi=200)
         plt.show()
-        del img,newimg,imgarr
+        del img, newimg, imgarr
 
     def test_badpixel_HtrDtr(self):
-        img = galsim.Image(500,500,init_value=1000)
+        img = galsim.Image(500, 500, init_value=1000)
         rgbadpix = Generator(PCG64(20210911))
         badfraction = 5E-5*(rgbadpix.random()*0.5+0.7)
-        img = Effects.DefectivePixels(img, IfHotPix=True, IfDeadPix=True, fraction=badfraction, seed=20210911, biaslevel=0)
-        img.write(os.path.join(self.outDataFn,'test_badpixel_HtrDtr.fits'))
+        img = effects.DefectivePixels(
+            img, IfHotPix=True, IfDeadPix=True, fraction=badfraction, seed=20210911, biaslevel=0)
+        img.write(os.path.join(self.outDataFn, 'test_badpixel_HtrDtr.fits'))
         del img
+
     def test_badpixel_HfsDtr(self):
-        img = galsim.Image(500,500,init_value=1000)
+        img = galsim.Image(500, 500, init_value=1000)
         rgbadpix = Generator(PCG64(20210911))
         badfraction = 5E-5*(rgbadpix.random()*0.5+0.7)
-        img = Effects.DefectivePixels(img, IfHotPix=False, IfDeadPix=True, fraction=badfraction, seed=20210911, biaslevel=0)
-        img.write(os.path.join(self.outDataFn,'test_badpixel_HfsDtr.fits'))
+        img = effects.DefectivePixels(
+            img, IfHotPix=False, IfDeadPix=True, fraction=badfraction, seed=20210911, biaslevel=0)
+        img.write(os.path.join(self.outDataFn, 'test_badpixel_HfsDtr.fits'))
         del img
+
     def test_badpixel_HtrDfs(self):
-        img = galsim.Image(500,500,init_value=1000)
+        img = galsim.Image(500, 500, init_value=1000)
         rgbadpix = Generator(PCG64(20210911))
         badfraction = 5E-5*(rgbadpix.random()*0.5+0.7)
-        img = Effects.DefectivePixels(img, IfHotPix=True, IfDeadPix=False, fraction=badfraction, seed=20210911, biaslevel=0)
-        img.write(os.path.join(self.outDataFn,'test_badpixel_HtrDfs.fits'))
+        img = effects.DefectivePixels(
+            img, IfHotPix=True, IfDeadPix=False, fraction=badfraction, seed=20210911, biaslevel=0)
+        img.write(os.path.join(self.outDataFn, 'test_badpixel_HtrDfs.fits'))
         del img
+
     def test_badpixel_HfsDfs(self):
-        img = galsim.Image(500,500,init_value=1000)
+        img = galsim.Image(500, 500, init_value=1000)
         rgbadpix = Generator(PCG64(20210911))
         badfraction = 5E-5*(rgbadpix.random()*0.5+0.7)
-        img = Effects.DefectivePixels(img, IfHotPix=False, IfDeadPix=False, fraction=badfraction, seed=20210911, biaslevel=0)
-        img.write(os.path.join(self.outDataFn,'test_badpixel_HfsDfs.fits'))
+        img = effects.DefectivePixels(
+            img, IfHotPix=False, IfDeadPix=False, fraction=badfraction, seed=20210911, biaslevel=0)
+        img.write(os.path.join(self.outDataFn, 'test_badpixel_HfsDfs.fits'))
         del img
 
     def test_badlines(self):
-        img = galsim.Image(500,500,init_value=-1000)
+        img = galsim.Image(500, 500, init_value=-1000)
         img.addNoise(galsim.GaussianNoise(sigma=7))
-        newimg = Effects.BadColumns(copy.deepcopy(img), seed=20210911)
-        newimg.write(os.path.join(self.outDataFn,'test_badlines.fits'))
-        del newimg,img
+        newimg = effects.BadColumns(copy.deepcopy(img), seed=20210911)
+        newimg.write(os.path.join(self.outDataFn, 'test_badlines.fits'))
+        del newimg, img
 
     # def test_cte(self):
     #     img = galsim.Image(200,200,init_value=1000)
     #     img.array[50,80] = 1e4
     #     img.array[150,150] = 3e4
-    #     newimgcol = Effects.CTE_Effect(copy.deepcopy(img),direction='column')
-    #     newimgrow = Effects.CTE_Effect(copy.deepcopy(img),direction='row')
+    #     newimgcol = effects.CTE_Effect(copy.deepcopy(img),direction='column')
+    #     newimgrow = effects.CTE_Effect(copy.deepcopy(img),direction='row')
     #     newimgcol.write(os.path.join(self.outDataFn,'test_ctecol.fits'))
     #     newimgrow.write(os.path.join(self.outDataFn,'test_cterow.fits'))
     #     del img,newimgcol,newimgrow
 
     def test_readnoise(self):
-        img = galsim.Image(200,200,init_value=1000)
+        img = galsim.Image(200, 200, init_value=1000)
         seed = 20210911
         rng_readout = galsim.BaseDeviate(seed)
         readout_noise = galsim.GaussianNoise(rng=rng_readout, sigma=5)
         img.addNoise(readout_noise)
-        img.write(os.path.join(self.outDataFn,'test_readnoise.fits'))
+        img.write(os.path.join(self.outDataFn, 'test_readnoise.fits'))
         stdval = np.std(img.array)
-        self.assertTrue(np.abs(stdval-5)<0.01*5)
+        self.assertTrue(np.abs(stdval-5) < 0.01*5)
         print('\nUnit test for readout noise has been passed.')
         del img
 
     def test_addbias(self):
-        img = galsim.Image(200,200,init_value=0)
-        img = Effects.AddBiasNonUniform16(img,bias_level=500, nsecy = 2, nsecx=8,seed=20210911)
+        img = galsim.Image(200, 200, init_value=0)
+        img = effects.AddBiasNonUniform16(
+            img, bias_level=500, nsecy=2, nsecx=8, seed=20210911)
         img.write('./output/test_addbias.fits')
         del img
 
     def test_apply16gains(self):
-        img = galsim.Image(500,500,init_value=100)
-        img,_ = Effects.ApplyGainNonUniform16(img, gain=1.5, nsecy=2, nsecx=8, seed=202102)
-        img.write(os.path.join(self.outDataFn,'test_apply16gains.fits'))
+        img = galsim.Image(500, 500, init_value=100)
+        img, _ = effects.ApplyGainNonUniform16(
+            img, gain=1.5, nsecy=2, nsecx=8, seed=202102)
+        img.write(os.path.join(self.outDataFn, 'test_apply16gains.fits'))
         rightedge = int(500/8)*8
         print('gain=%6.2f' % 1.5)
-        meanimg = np.mean(img.array[:,:rightedge])
-        sigmaimg = np.std(img.array[:,:rightedge])
-        print('mean, sigma = %6.2f, %6.2f' % (meanimg,sigmaimg))
-        self.assertTrue(np.abs(meanimg-100/1.5)<1)
-        self.assertTrue(np.abs(sigmaimg/meanimg-0.01)<0.001)
+        meanimg = np.mean(img.array[:, :rightedge])
+        sigmaimg = np.std(img.array[:, :rightedge])
+        print('mean, sigma = %6.2f, %6.2f' % (meanimg, sigmaimg))
+        self.assertTrue(np.abs(meanimg-100/1.5) < 1)
+        self.assertTrue(np.abs(sigmaimg/meanimg-0.01) < 0.001)
         print('\nUnit test for applying 16 channel gains has been passed.')
         del img
 
-
     def test_cosmicray(self):
-        attachedSizes = np.loadtxt(os.path.join(self.datafn,'wfc-cr-attachpixel.dat'))
-        cr_map,_ = Effects.produceCR_Map(
-                xLen=500, yLen=500, exTime=150+0.5*40, 
-                cr_pixelRatio=0.003*(1+0.5*40/150), 
-                gain=1, attachedSizes=attachedSizes, seed=20210911)
+        attachedSizes = np.loadtxt(os.path.join(
+            self.datafn, 'wfc-cr-attachpixel.dat'))
+        cr_map, _ = effects.produceCR_Map(
+            xLen=500, yLen=500, exTime=150+0.5*40,
+            cr_pixelRatio=0.003*(1+0.5*40/150),
+            gain=1, attachedSizes=attachedSizes, seed=20210911)
         crimg = galsim.Image(cr_map)
-        crimg.write(os.path.join(self.outDataFn,'test_cosmicray.fits'))
-        del cr_map,crimg
+        crimg.write(os.path.join(self.outDataFn, 'test_cosmicray.fits'))
+        del cr_map, crimg
 
     def test_shutter(self):
-        img = galsim.Image(5000,5000,init_value=1000)
-        shuttimg = Effects.ShutterEffectArr(img, t_exp=150, t_shutter=1.3, dist_bearing=735, dt=1E-3)    # shutter effect normalized image for this chip
+        img = galsim.Image(5000, 5000, init_value=1000)
+        # shutter effect normalized image for this chip
+        shuttimg = effects.ShutterEffectArr(
+            img, t_exp=150, t_shutter=1.3, dist_bearing=735, dt=1E-3)
         img *= shuttimg
-        img.write(os.path.join(self.outDataFn,'test_shutter.fits'))
+        img.write(os.path.join(self.outDataFn, 'test_shutter.fits'))
         del img
 
     def test_vignette(self):
-        img = galsim.Image(2000,2000,init_value=1000)
+        img = galsim.Image(2000, 2000, init_value=1000)
         print(img.bounds)
         # # img.bounds = galsim.BoundsI(1, width, 1, height)
-        img.setOrigin(10000,10000)
-        flat_img = Effects.MakeFlatSmooth(img.bounds,20210911)
+        img.setOrigin(10000, 10000)
+        flat_img = effects.MakeFlatSmooth(img.bounds, 20210911)
         flat_normal = flat_img / np.mean(flat_img.array)
-        flat_normal.write(os.path.join(self.outDataFn,'test_vignette.fits'))
-        del flat_img,img,flat_normal
-
+        flat_normal.write(os.path.join(self.outDataFn, 'test_vignette.fits'))
+        del flat_img, img, flat_normal
 
 
 if __name__ == '__main__':
-    unittest.main()
\ No newline at end of file
+    unittest.main()
diff --git a/tests/test_focalplane.py b/tests/test_focalplane.py
index 0e7ce189242fd41329984d34581af79f853bd5f9..74ab61b7ece12f2aa1ca15d3f888f437f7e84bd1 100644
--- a/tests/test_focalplane.py
+++ b/tests/test_focalplane.py
@@ -1,7 +1,7 @@
 import unittest
 import os
 import galsim
-from ObservationSim.Instrument import FocalPlane, Chip
+from observation_sim.instruments import FocalPlane, Chip
 
 
 class TestFocalPlane(unittest.TestCase):
diff --git a/tests/test_imaging.py b/tests/test_imaging.py
index e7175d62074da17dbff4627444f18fd2a4ea306e..7af8d32156e138b4020ed7da5882c3f2cde8c094 100644
--- a/tests/test_imaging.py
+++ b/tests/test_imaging.py
@@ -15,12 +15,12 @@ import copy
 from astropy.cosmology import FlatLambdaCDM
 from astropy import constants
 from astropy import units as U
-from ObservationSim.MockObject._util import getObservedSED
-from ObservationSim.MockObject import CatalogBase, Galaxy
+from observation_sim.mock_objects._util import getObservedSED
+from observation_sim.mock_objects import CatalogBase, Galaxy
 
-from ObservationSim.Instrument import Chip, Filter, FilterParam, FocalPlane
-from ObservationSim.PSF.PSFInterp import PSFInterp
-from ObservationSim.MockObject._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getABMAG
+from observation_sim.instruments import Chip, Filter, FilterParam, FocalPlane
+from observation_sim.PSF.PSFInterp import PSFInterp
+from observation_sim.mock_objects._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getABMAG
 
 
 class Catalog(CatalogBase):
diff --git a/tests/test_prescan_overscan_func.py b/tests/test_prescan_overscan_func.py
index 1a6a1303edc31c8b8482037f1d17248cfc7af11e..b1a11a345646204603da70045c1bda9c04b4254a 100644
--- a/tests/test_prescan_overscan_func.py
+++ b/tests/test_prescan_overscan_func.py
@@ -6,8 +6,7 @@ import numpy as np
 import galsim
 import yaml
 
-from ObservationSim.Instrument import Chip, Filter, FilterParam, FocalPlane
-#from ObservationSim.Instrument.Chip import ChipUtils as chip_utils
+from observation_sim.instruments import Chip, Filter, FilterParam, FocalPlane
 
 ### test FUNCTION --- START ###
 def AddPreScan(GSImage, pre1=27, pre2=4, over1=71, over2=80, nsecy = 2, nsecx=8):
diff --git a/tools/create_chip_json.py b/tools/create_chip_json.py
index b08337566c48707a89550db1e837e7c25087c058..aca80c3ecc1cf2a6ee2eac9b938e8da4927fd857 100644
--- a/tools/create_chip_json.py
+++ b/tools/create_chip_json.py
@@ -14,17 +14,19 @@ chip_filename = 'chip_definition.json'
 #     "npix_y":       7680,
 #     "x_cen":        -273.35, # [mm]
 #     "y_cen":        211.36,  # [mm]
-#     "rotate_angle": 90.     # [deg] 
+#     "rotate_angle": 90.     # [deg]
 # }
 # chip_list[chip_id] = chip_dict
 
+
 def get_chip_row_col_main_fp(chip_id):
     rowID = ((chip_id - 1) % 5) + 1
     colID = 6 - ((chip_id - 1) // 5)
     return rowID, colID
 
+
 def get_chip_center_main_fp(chip_id, pixel_size=1e-2):
-    
+
     row, col = get_chip_row_col_main_fp(chip_id)
     npix_x = 9216
     npix_y = 9232
@@ -39,16 +41,20 @@ def get_chip_center_main_fp(chip_id, pixel_size=1e-2):
         xcen = (npix_x//2 + gx1//2) * xrem - (gx2-gx1)
     if chip_id <= 5 or chip_id == 10:
         xcen = (npix_x//2 + gx1//2) * xrem + (gx2-gx1)
-    
+
     # ylim of a given CCD chip
     yrem = (row - 1) - nchip_y // 2
     ycen = (npix_y + gy) * yrem
     return xcen * pixel_size, ycen * pixel_size
 
+
 def create_chip_dict_main_fp(chip_id, pixel_size=1e-2):
-    filter_list = ["GV", "GI", "y", "z", "y", "GI", "GU", "r", "u", "NUV", "i", "GV", "GU", "g", "NUV", "NUV", "g", "GU", "GV", "i", "NUV", "u", "r", "GU", "GI", "y", "z", "y", "GI", "GV"]
-    chip_label_list = [3,3,3,1,1,1,3,2,2,1,1,1,4,2,3,2,1,1,4,2,4,1,1,2,4,2,2,4,2,2]
-    chip_id_list = [26, 21, 16, 11, 6, 1, 27, 22, 17, 12, 7, 2, 28, 23, 18, 13, 8, 3, 29, 24, 19, 14, 9, 4, 30, 25, 20, 15, 10, 5]
+    filter_list = ["GV", "GI", "y", "z", "y", "GI", "GU", "r", "u", "NUV", "i", "GV", "GU", "g",
+                   "NUV", "NUV", "g", "GU", "GV", "i", "NUV", "u", "r", "GU", "GI", "y", "z", "y", "GI", "GV"]
+    chip_label_list = [3, 3, 3, 1, 1, 1, 3, 2, 2, 1, 1, 1,
+                       4, 2, 3, 2, 1, 1, 4, 2, 4, 1, 1, 2, 4, 2, 2, 4, 2, 2]
+    chip_id_list = [26, 21, 16, 11, 6, 1, 27, 22, 17, 12, 7, 2, 28,
+                    23, 18, 13, 8, 3, 29, 24, 19, 14, 9, 4, 30, 25, 20, 15, 10, 5]
     npix_x = 9216
     npix_y = 9232
     idx = chip_id_list.index(chip_id)
@@ -63,10 +69,10 @@ def create_chip_dict_main_fp(chip_id, pixel_size=1e-2):
     chip_dict = {
         "chip_name":    chip_name,
         "pix_size":     1e-2,  # [mm]
-        "pix_scale":    0.074, # [arcsec/pix]
+        "pix_scale":    0.074,  # [arcsec/pix]
         "npix_x":       npix_x,
         "npix_y":       npix_y,
-        "x_cen":        xcen, # [mm]
+        "x_cen":        xcen,  # [mm]
         "y_cen":        ycen,  # [mm]
         "rotate_angle": rotate_angle,     # [deg]
         "n_psf_samples": 900,
@@ -80,6 +86,7 @@ def create_chip_dict_main_fp(chip_id, pixel_size=1e-2):
     }
     return chip_dict
 
+
 def set_fgs_chips(filepath):
     with open(filepath, "r") as f:
         data = json.load(f)
@@ -94,7 +101,7 @@ def set_fgs_chips(filepath):
         data[chip_id]["full_well"] = 90000
     with open(filepath, "w") as f:
         json.dump(data, f, indent=4)
-    
+
 
 def add_main_fp(filepath):
     for i in range(30):
@@ -102,6 +109,7 @@ def add_main_fp(filepath):
         chip_dict = create_chip_dict_main_fp(chip_id)
         add_dict_to_json(filepath, str(chip_id), chip_dict)
 
+
 def add_dict_to_json(filepath, key, value):
     with open(filepath, 'r') as f:
         data = json.load(f)
@@ -109,8 +117,9 @@ def add_dict_to_json(filepath, key, value):
     with open(filepath, "w") as f:
         json.dump(data, f, indent=4)
 
-if __name__=="__main__":
-    src = "../ObservationSim/Instrument/data/ccd/chip_definition.json"
+
+if __name__ == "__main__":
+    src = "../observation_sim/instruments/data/ccd/chip_definition.json"
     shutil.copy(src, chip_filename)
     add_main_fp(chip_filename)
-    set_fgs_chips(chip_filename)
\ No newline at end of file
+    set_fgs_chips(chip_filename)
diff --git a/tools/getPSF.py b/tools/get_PSF.py
similarity index 63%
rename from tools/getPSF.py
rename to tools/get_PSF.py
index f35218e92f19a571da416090a2fa668a2d952593..c13ea06632233216630fbf9d62f31315c836369c 100644
--- a/tools/getPSF.py
+++ b/tools/get_PSF.py
@@ -1,26 +1,26 @@
 import os
 import numpy as np
-import ObservationSim.PSF.PSFInterp as PSFInterp
-from ObservationSim.Instrument import Chip, Filter, FilterParam
+import observation_sim.PSF.PSFInterp as PSFInterp
+from observation_sim.instruments import Chip, Filter, FilterParam
 import yaml
 import galsim
 import astropy.io.fits as fitsio
 
 # Setup PATH
 SIMPATH = "/share/simudata/CSSOSDataProductsSims/data/CSSTSimImage_C8/testRun_FGS"
-config_filename= SIMPATH+"/config_C6_fits.yaml"
-cat_filename   = SIMPATH+"/MSC_00000000/MSC_10106100000000_chip_40_filt_FGS.cat"
+config_filename = SIMPATH+"/config_C6_fits.yaml"
+cat_filename = SIMPATH+"/MSC_00000000/MSC_10106100000000_chip_40_filt_FGS.cat"
 
 # Read cat file
-catFn = open(cat_filename,"r")
+catFn = open(cat_filename, "r")
 line = catFn.readline()
-print(cat_filename,'\n',line)
+print(cat_filename, '\n', line)
 imgPos = []
 chipID = -1
 for line in catFn:
     line = line.strip()
     columns = line.split()
-    
+
     if chipID == -1:
         chipID = int(columns[1])
     else:
@@ -37,41 +37,46 @@ with open(config_filename, "r") as stream:
     try:
         config = yaml.safe_load(stream)
         for key, value in config.items():
-            print (key + " : " + str(value))
+            print(key + " : " + str(value))
     except yaml.YAMLError as exc:
         print(exc)
 
 # Setup Chip
 chip = Chip(chipID=chipID, config=config)
-print('chip.bound::', chip.bound.xmin, chip.bound.xmax, chip.bound.ymin, chip.bound.ymax)
+print('chip.bound::', chip.bound.xmin, chip.bound.xmax,
+      chip.bound.ymin, chip.bound.ymax)
 
 for iobj in range(nobj):
     print("\nget psf for iobj-", iobj, '\t', 'bandpass:', end=" ", flush=True)
     # Setup Position on focalplane
-    x, y = imgPos[iobj, :] # try get the PSF at some location (1234, 1234) on the chip
+    # try get the PSF at some location (1234, 1234) on the chip
+    x, y = imgPos[iobj, :]
     x = x+chip.bound.xmin
     y = y+chip.bound.ymin
 
     pos_img = galsim.PositionD(x, y)
-    
+
     # Setup sub-bandpass
     # (There are 4 sub-bandpasses for each PSF sample)
     filter_param = FilterParam()
     filter_id, filter_type = chip.getChipFilter()
     filt = Filter(
-        filter_id=filter_id, 
-        filter_type=filter_type, 
-        filter_param=filter_param, 
+        filter_id=filter_id,
+        filter_type=filter_type,
+        filter_param=filter_param,
         ccd_bandpass=chip.effCurve)
     bandpass_list = filt.bandpass_sub_list
     for i in range(len(bandpass_list)):
         print(i, end=" ", flush=True)
-        bandpass = bandpass_list[i] # say you want to access the PSF for the sub-bandpass at the blue end for that chip
-        
+        # say you want to access the PSF for the sub-bandpass at the blue end for that chip
+        bandpass = bandpass_list[i]
+
         # Get corresponding PSF model
-        psf_model = PSFInterp(chip=chip, npsf=100, PSF_data_file=config["psf_setting"]["psf_dir"])
-        psf  = psf_model.get_PSF(chip=chip, pos_img=pos_img, bandpass=bandpass, galsimGSObject=False)
-        
+        psf_model = PSFInterp(chip=chip, npsf=100,
+                              PSF_data_file=config["psf_setting"]["psf_dir"])
+        psf = psf_model.get_PSF(
+            chip=chip, pos_img=pos_img, bandpass=bandpass, galsimGSObject=False)
+
         if True:
             fn = "psf_{:}.{:}.{:}.fits".format(chipID, iobj, i)
             if fn != None:
@@ -81,6 +86,3 @@ for iobj in range(nobj):
             hdu.data = psf
             hdu.header.set('pixScale', 5)
             hdu.writeto(fn)
-
-
-
diff --git a/tools/indexFits_hdf5.py b/tools/index_fits_hdf5.py
similarity index 68%
rename from tools/indexFits_hdf5.py
rename to tools/index_fits_hdf5.py
index 1585ea4a3b675975d6574f0c3cfc3ff3d5ff0321..779cbc0e550af590b9e28765067d1f20735d7ddd 100644
--- a/tools/indexFits_hdf5.py
+++ b/tools/index_fits_hdf5.py
@@ -26,7 +26,8 @@ import galsim
 
 def test_fits(nfits=100, dir_cat=None):
     for ifits in range(nfits):
-        gal = galsim.Gaussian(sigma=np.random.uniform(0.2, 0.3)).shear(g1=np.random.uniform(-0.5, 0.5), g2=np.random.uniform(-0.5, 0.5))
+        gal = galsim.Gaussian(sigma=np.random.uniform(0.2, 0.3)).shear(
+            g1=np.random.uniform(-0.5, 0.5), g2=np.random.uniform(-0.5, 0.5))
         arr = gal.drawImage(nx=64, ny=64, scale=0.074).array
 
         hdu = fitsio.PrimaryHDU()
@@ -38,41 +39,44 @@ def test_fits(nfits=100, dir_cat=None):
         hdu.header.set('mag_g', 22+np.random.uniform(-1, 1))
         hdu.header.set('pixScale', 0.074)
 
-        fout=dir_cat+"stampCats/testStamp_{:}.fits".format(ifits)
+        fout = dir_cat+"stampCats/testStamp_{:}.fits".format(ifits)
         if os.path.exists(fout):
             os.remove(fout)
         hdu.writeto(fout)
 
 
 def write_StampsIndex(dir_cat=None, DEBUG=False):
-    MAXNUMBERINDEX  = 10000
+    MAXNUMBERINDEX = 10000
     NSIDE = 128
     fp = h5py.File(dir_cat+'stampCatsIndex.hdf5', 'w')
     grp1 = fp.create_group('Stamps')
 
     dataSet_Size = np.zeros(healpy.nside2npix(NSIDE), dtype=np.int64)
-    fitsList = os.listdir(dir_cat+'stampCats/')  #获取fits文件列表
+    fitsList = os.listdir(dir_cat+'stampCats/')  # 获取fits文件列表
     for istamp in range(len(fitsList)):
         print(istamp, ': ', fitsList[istamp], end='\r')
 
-        hdu=fitsio.open(dir_cat+"stampCats/"+fitsList[istamp])
+        hdu = fitsio.open(dir_cat+"stampCats/"+fitsList[istamp])
         tra = hdu[0].header['RA']
-        tdec= hdu[0].header['DEC']
+        tdec = hdu[0].header['DEC']
 
-        healpixID= healpy.ang2pix(NSIDE, tra, tdec, nest=False, lonlat=True)
+        healpixID = healpy.ang2pix(NSIDE, tra, tdec, nest=False, lonlat=True)
 
-        if not(str(healpixID) in grp1):
+        if not (str(healpixID) in grp1):
             grp2 = grp1.create_group(str(healpixID))
         else:
             grp2 = grp1[str(healpixID)]
 
-        if not('ra' in grp2):
-            dset_ra = grp2.create_dataset('ra', (0,), dtype='f16' ,  maxshape=(MAXNUMBERINDEX, ))
-            dset_dec= grp2.create_dataset('dec', (0,), dtype='f16',  maxshape=(MAXNUMBERINDEX, ))
+        if not ('ra' in grp2):
+            dset_ra = grp2.create_dataset(
+                'ra', (0,), dtype='f16',  maxshape=(MAXNUMBERINDEX, ))
+            dset_dec = grp2.create_dataset(
+                'dec', (0,), dtype='f16',  maxshape=(MAXNUMBERINDEX, ))
             dt = h5py.special_dtype(vlen=str)
-            dset_fn = grp2.create_dataset('filename', (0,), dtype=dt, maxshape=(MAXNUMBERINDEX, ))
+            dset_fn = grp2.create_dataset(
+                'filename', (0,), dtype=dt, maxshape=(MAXNUMBERINDEX, ))
         else:
-            dset_ra  = grp2['ra']
+            dset_ra = grp2['ra']
             dset_dec = grp2['dec']
             dset_fn = grp2['filename']
 
@@ -82,13 +86,13 @@ def write_StampsIndex(dir_cat=None, DEBUG=False):
         grp2['filename'].resize((dataSet_Size[healpixID],))
 
         dset_ra[dataSet_Size[healpixID]-1] = tra
-        dset_dec[dataSet_Size[healpixID]-1]= tdec
-        dset_fn[dataSet_Size[healpixID]-1]= fitsList[istamp]
+        dset_dec[dataSet_Size[healpixID]-1] = tdec
+        dset_fn[dataSet_Size[healpixID]-1] = fitsList[istamp]
     fp.close()
 
     if DEBUG:
         print('\n')
-        ff = h5py.File(dir_cat+"stampCatsIndex.hdf5","r")
+        ff = h5py.File(dir_cat+"stampCatsIndex.hdf5", "r")
         ss = 0
         for kk in ff['Stamps'].keys():
             print(kk, ff['Stamps'][kk]['ra'].size)
@@ -98,6 +102,5 @@ def write_StampsIndex(dir_cat=None, DEBUG=False):
 
 if __name__ == '__main__':
     dir_temp = "./Catalog_test/"
-    #test_fits(dir_cat=dir_temp)
+    # test_fits(dir_cat=dir_temp)
     write_StampsIndex(dir_cat=dir_temp)
-
diff --git a/tools/TargetLocationCheck.py b/tools/target_location_check.py
similarity index 67%
rename from tools/TargetLocationCheck.py
rename to tools/target_location_check.py
index 69020761fbc5fe38b5615e2b5c0b6c65c92e8a96..34293be892b00d330c8fac94037a3502e2b6055e 100644
--- a/tools/TargetLocationCheck.py
+++ b/tools/target_location_check.py
@@ -1,15 +1,17 @@
-# NOTE: This is a stand-alone function, meaning that you do not need 
-#       to install the entire CSST image simulation pipeline. 
+# NOTE: This is a stand-alone function, meaning that you do not need
+#       to install the entire CSST image simulation pipeline.
 
-# For a given object's coordinate (Ra, Dec), the function will predict 
-# the object's image position and corresponding filter in the focal plane 
+# For a given object's coordinate (Ra, Dec), the function will predict
+# the object's image position and corresponding filter in the focal plane
 # under a specified CSST pointing centered at (rap, decp).
 
 import galsim
 import numpy as np
 import argparse
 import matplotlib.pyplot as plt
-import os, sys
+import os
+import sys
+
 
 def focalPlaneInf(ra_target, dec_target, ra_point, dec_point, image_rot=-113.4333, figout="zTargetOnCCD.pdf"):
     """
@@ -37,60 +39,71 @@ def focalPlaneInf(ra_target, dec_target, ra_point, dec_point, image_rot=-113.433
     or type >> python TargetLocationCheck.py ra_target dec_target ra_point dec_point -image_rot=floatNum 
     or type >> python TargetLocationCheck.py ra_target dec_target ra_point dec_point -image_rot=floatNum -figout=FigureName
     """
-    print("^_^ Input target coordinate: [Ra, Dec] = [%10.6f, %10.6f]"%(ra_target,dec_target))
-    print("^_^ Input telescope pointing center: [Ra, Dec] = [%10.6f, %10.6f]"%(ra_point,dec_point))
-    print("^_^ Input camera orientation: %12.6f degree(s)"%image_rot)
+    print("^_^ Input target coordinate: [Ra, Dec] = [%10.6f, %10.6f]" % (
+        ra_target, dec_target))
+    print("^_^ Input telescope pointing center: [Ra, Dec] = [%10.6f, %10.6f]" % (
+        ra_point, dec_point))
+    print("^_^ Input camera orientation: %12.6f degree(s)" % image_rot)
     print(" ")
     # load ccd parameters
     xsize, ysize, xchip, ychip, xgap, ygap, xnchip, ynchip = ccdParam()
-    print("^_^ Pixel range of focal plane: x = [%5d, %5d], y = [%5d, %5d]"%(-xsize/2,xsize/2,-ysize/2,ysize/2))
-    # wcs 
-    wcs     = getTanWCS(ra_point, dec_point, image_rot, pix_scale=0.074)
-    skyObj  = galsim.CelestialCoord(ra=ra_target*galsim.degrees,dec=dec_target*galsim.degrees)
-    pixObj  = wcs.toImage(skyObj)
+    print("^_^ Pixel range of focal plane: x = [%5d, %5d], y = [%5d, %5d]" % (
+        -xsize/2, xsize/2, -ysize/2, ysize/2))
+    # wcs
+    wcs = getTanWCS(ra_point, dec_point, image_rot, pix_scale=0.074)
+    skyObj = galsim.CelestialCoord(
+        ra=ra_target*galsim.degrees, dec=dec_target*galsim.degrees)
+    pixObj = wcs.toImage(skyObj)
     xpixObj = pixObj.x
     ypixObj = pixObj.y
-    print("^_^ Image position of   target: [xImage, yImage] = [%9.3f, %9.3f]"%(xpixObj,ypixObj))
-    
+    print("^_^ Image position of   target: [xImage, yImage] = [%9.3f, %9.3f]" % (
+        xpixObj, ypixObj))
+
     # first determine if the target is in the focal plane
     xin = (xpixObj+xsize/2)*(xpixObj-xsize/2)
     yin = (ypixObj+ysize/2)*(ypixObj-ysize/2)
-    if xin>0 or yin>0: raise ValueError("!!! Input target is out of the focal plane")
-    
+    if xin > 0 or yin > 0:
+        raise ValueError("!!! Input target is out of the focal plane")
+
     # second determine the location of the target
     trigger = False
     for i in range(30):
-        ichip  = i+1
-        ischip = str("0%d"%ichip)[-2:]
-        fId, fType         = getChipFilter(ichip)
+        ichip = i+1
+        ischip = str("0%d" % ichip)[-2:]
+        fId, fType = getChipFilter(ichip)
         ix0, ix1, iy0, iy1 = getChipLim(ichip)
-        ixin   = (xpixObj-ix0)*(xpixObj-ix1)
-        iyin   = (ypixObj-iy0)*(ypixObj-iy1)
-        if ixin<=0 and iyin<=0:
+        ixin = (xpixObj-ix0)*(xpixObj-ix1)
+        iyin = (ypixObj-iy0)*(ypixObj-iy1)
+        if ixin <= 0 and iyin <= 0:
             trigger = True
-            idx     = xpixObj - ix0
-            idy     = ypixObj - iy0
+            idx = xpixObj - ix0
+            idy = ypixObj - iy0
             print("    ---------------------------------------------")
-            print("    ** Target locates in CHIP#%s with filter %s **"%(ischip,fType))
-            print("    ** Target position in the chip: [x, y] = [%7.2f, %7.2f]"%(idx, idy))
+            print("    ** Target locates in CHIP#%s with filter %s **" %
+                  (ischip, fType))
+            print(
+                "    ** Target position in the chip: [x, y] = [%7.2f, %7.2f]" % (idx, idy))
             print("    ---------------------------------------------")
             break
-    if not trigger: print("^|^ Target locates in CCD gap")
+    if not trigger:
+        print("^|^ Target locates in CCD gap")
 
     # show the figure
-    print("    Target on CCD layout is saved into %s"%figout)
+    print("    Target on CCD layout is saved into %s" % figout)
     ccdLayout(xpixObj, ypixObj, figout=figout)
 
     return
 
+
 def ccdParam():
     xt, yt = 59516, 49752
     x0, y0 = 9216, 9232
-    xgap, ygap = (534,1309), 898
+    xgap, ygap = (534, 1309), 898
     xnchip, ynchip = 6, 5
     ccdSize = xt, yt, x0, y0, xgap, ygap, xnchip, ynchip
     return ccdSize
 
+
 def getTanWCS(ra, dec, img_rot, pix_scale=0.074):
     """ 
     Get the WCS of the image mosaic using Gnomonic/TAN projection
@@ -105,40 +118,53 @@ def getTanWCS(ra, dec, img_rot, pix_scale=0.074):
         WCS of the focal plane
     """
     xcen, ycen = 0, 0
-    img_rot    = img_rot * galsim.degrees
-    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
-
-    moscen     = galsim.PositionD(x=xcen, y=ycen)
-    sky_center = galsim.CelestialCoord(ra=ra*galsim.degrees, dec=dec*galsim.degrees)
-    affine     = galsim.AffineTransform(dudx, dudy, dvdx, dvdy, origin=moscen)
-    WCS        = galsim.TanWCS(affine, sky_center, units=galsim.arcsec)
+    img_rot = img_rot * galsim.degrees
+    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
+
+    moscen = galsim.PositionD(x=xcen, y=ycen)
+    sky_center = galsim.CelestialCoord(
+        ra=ra*galsim.degrees, dec=dec*galsim.degrees)
+    affine = galsim.AffineTransform(dudx, dudy, dvdx, dvdy, origin=moscen)
+    WCS = galsim.TanWCS(affine, sky_center, units=galsim.arcsec)
 
     return WCS
 
+
 def getChipFilter(chipID):
     """
     Return the filter index and type for a given chip #(chipID)
     """
-    filter_type_list = ["nuv","u", "g", "r", "i","z","y","GU", "GV", "GI"]
+    filter_type_list = ["nuv", "u", "g", "r", "i", "z", "y", "GU", "GV", "GI"]
     # TODO: maybe a more elegent way other than hard coded?
     # e.g. use something like a nested dict:
-    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 [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"
     filter_id = filter_type_list.index(filter_type)
 
     return filter_id, filter_type
 
+
 def getChipLim(chipID):
     """
     Calculate the edges in pixel for a given CCD chip on the focal plane
@@ -173,20 +199,22 @@ def getChipLim(chipID):
 
     return nx0-1, nx1-1, ny0-1, ny1-1
 
+
 def ccdLayout(xpixTar, ypixTar, figout="ccdLayout.pdf"):
-    fig = plt.figure(figsize=(10.0,8.0))
-    ax = fig.add_axes([0.1,0.1,0.80,0.80]) 
+    fig = plt.figure(figsize=(10.0, 8.0))
+    ax = fig.add_axes([0.1, 0.1, 0.80, 0.80])
     # plot the layout of the ccd distribution
     for i in range(30):
         ichip = i+1
         fId, fType = getChipFilter(ichip)
-        ischip = str("0%d"%ichip)[-2:]
+        ischip = str("0%d" % ichip)[-2:]
         ix0, ix1, iy0, iy1 = getChipLim(ichip)
-        ax.plot([ix0,ix1],[iy0,iy0],"k-", linewidth=2.5)
-        ax.plot([ix0,ix1],[iy1,iy1],"k-", linewidth=2.5)
-        ax.plot([ix0,ix0],[iy0,iy1],"k-", linewidth=2.5)
-        ax.plot([ix1,ix1],[iy0,iy1],"k-", linewidth=2.5)
-        ax.text(ix0+500,iy0+1500,"%s#%s"%(fType, ischip), fontsize=12, color="grey")
+        ax.plot([ix0, ix1], [iy0, iy0], "k-", linewidth=2.5)
+        ax.plot([ix0, ix1], [iy1, iy1], "k-", linewidth=2.5)
+        ax.plot([ix0, ix0], [iy0, iy1], "k-", linewidth=2.5)
+        ax.plot([ix1, ix1], [iy0, iy1], "k-", linewidth=2.5)
+        ax.text(ix0+500, iy0+1500, "%s#%s" %
+                (fType, ischip), fontsize=12, color="grey")
     ax.plot(xpixTar, ypixTar, "r*", ms=12)
     ax.set_xlabel("$X\,[\mathrm{pixels}]$", fontsize=20)
     ax.set_ylabel("$Y\,[\mathrm{pixels}]$", fontsize=20)
@@ -194,6 +222,7 @@ def ccdLayout(xpixTar, ypixTar, figout="ccdLayout.pdf"):
     ax.axis('off')
     plt.savefig(figout)
 
+
 def parseArguments():
     # Create argument parser
     parser = argparse.ArgumentParser()
@@ -203,7 +232,7 @@ def parseArguments():
     parser.add_argument("dec_target",   type=float)
     parser.add_argument("ra_point",  type=float)
     parser.add_argument("dec_point", type=float)
-    
+
     # Optional arguments
     parser.add_argument("-image_rot", type=float, default=-113.4333)
     parser.add_argument("-figout",    type=str,   default="zTargetOnCCD.pdf")
@@ -213,10 +242,11 @@ def parseArguments():
 
     return args
 
+
 if __name__ == "__main__":
     # Parse the arguments
     args = parseArguments()
 
     # Run function
-    focalPlaneInf(args.ra_target, args.dec_target, args.ra_point, args.dec_point, args.image_rot, args.figout)
-
+    focalPlaneInf(args.ra_target, args.dec_target, args.ra_point,
+                  args.dec_point, args.image_rot, args.figout)