44from roman_imsim .effects import roman_effects
55from .utils import sca_number_to_file
66
7+
78class brighter_fatter (roman_effects ):
89 def __init__ (self , params , base , logger , rng , rng_iter = None ):
910 super ().__init__ (params , base , logger , rng , rng_iter )
10- # self.saturation_level = self.params['saturation_level'] if 'saturation_level' in self.params else 100000
11-
11+
1212 self .model = getattr (self , self .params ['model' ])
1313 if self .model is None :
14- self .logger .warning ("%s hasn't been implemented yet, the simple model will be applied for %s" % (str (self .params ['model' ]), str (self .__class__ .__name__ )))
14+ self .logger .warning ("%s hasn't been implemented yet, the simple model will be applied for %s" % (
15+ str (self .params ['model' ]), str (self .__class__ .__name__ )))
1516 self .model = self .simple_model
16-
17+
1718 def simple_model (self , image ):
1819 self .logger .warning ("No bfe effect will be applied." )
1920 return image
20-
21+
2122 def lab_model (self , image ):
2223 """
2324 Apply brighter-fatter effect.
@@ -41,132 +42,136 @@ def lab_model(self, image):
4142 self .logger .warning ("No BFE kernel data file provided; no bfe effect will be applied." )
4243 return image
4344 self .df = fio .FITS (os .path .join (self .sca_filepath , sca_number_to_file [self .sca ]))
44-
45+
4546 self .logger .warning ("Lab measured model will be applied for brighter-fatter effect." )
4647
47- nbfe = 2 # # kernel of bfe in shape (2 x nbfe+1)*(2 x nbfe+1)
48+ nbfe = 2 # kernel of bfe in shape (2 x nbfe+1)*(2 x nbfe+1)
4849 bin_size = 128
4950 n_max = 32
5051 m_max = 32
5152 num_grids = 4
5253 n_sub = n_max // num_grids
5354 m_sub = m_max // num_grids
5455
55- ## =======================================================================
56- ## solve boundary shfit kernel aX components
57- ## =======================================================================
58- a_area = self .df ['BFE' ][:,:,:, :] # 5x5x32x32
59- a_components = np .zeros ( (4 , 2 * nbfe + 1 , 2 * nbfe + 1 , n_max , m_max ) ) # 4x5x5x32x32
56+ # =======================================================================
57+ # solve boundary shfit kernel aX components
58+ # =======================================================================
59+ a_area = self .df ['BFE' ][:, :, :, :] # 5x5x32x32
60+ a_components = np .zeros ((4 , 2 * nbfe + 1 , 2 * nbfe + 1 , n_max , m_max )) # 4x5x5x32x32
6061
61- ## solve aR aT aL aB for each a
62- for n in range (n_max ): # m_max and n_max = 32 (binned in 128x128)
62+ # solve aR aT aL aB for each a
63+ for n in range (n_max ): # m_max and n_max = 32 (binned in 128x128)
6364 for m in range (m_max ):
64- a = a_area [:,:, n , m ] ## a in (2 x nbfe+1)*(2 x nbfe+1)
65-
66- ## assume two parity symmetries
67- a = ( a + np .fliplr (a ) + np .flipud (a ) + np .flip (a ) )/ 4.
68-
69- r = 0.5 * ( 3.25 / 4.25 )** (1.5 ) / 1.5 ## source-boundary projection
70- B = (a [2 ,2 ], a [3 ,2 ], a [2 ,3 ], a [3 ,3 ],
71- a [4 ,2 ], a [2 ,4 ], a [3 ,4 ], a [4 ,4 ] )
72-
73- A = np .array ( [ [ - 2 , - 2 , 0 , 0 , 0 , 0 , 0 ],
74- [ 0 , 1 , 0 , - 1 , - 2 , 0 , 0 ],
75- [ 1 , 0 , - 1 , 0 , - 2 , 0 , 0 ],
76- [ 0 , 0 , 0 , 0 , 2 , - 2 , 0 ],
77- [ 0 , 0 , 0 , 1 , 0 ,- 2 * r , 0 ],
78- [ 0 , 0 , 1 , 0 , 0 ,- 2 * r , 0 ],
79- [ 0 , 0 , 0 , 0 , 0 , 1 + r , - 1 ],
80- [ 0 , 0 , 0 , 0 , 0 , 0 , 2 ] ])
81-
82-
83- s1 ,s2 ,s3 ,s4 ,s5 ,s6 ,s7 = np .linalg .lstsq (A , B , rcond = None )[0 ]
84-
85- aR = np .array ( [[ 0. , - s7 ,- r * s6 , r * s6 , s7 ],
86- [ 0. , - s6 , - s5 , s5 , s6 ],
87- [ 0. , - s3 , - s1 , s1 , s3 ],
88- [ 0. , - s6 , - s5 , s5 , s6 ],
89- [ 0. , - s7 ,- r * s6 , r * s6 , s7 ],])
90-
91-
92- aT = np .array ( [[ 0. , 0. , 0. , 0. , 0. ],
93- [ - s7 , - s6 , - s4 , - s6 , - s7 ],
94- [ - r * s6 , - s5 , - s2 , - s5 , - r * s6 ],
95- [ r * s6 , s5 , s2 , s5 , r * s6 ],
96- [ s7 , s6 , s4 , s6 , s7 ],])
97-
65+ a = a_area [:, :, n , m ] # a in (2 x nbfe+1)*(2 x nbfe+1)
66+
67+ # assume two parity symmetries
68+ a = (a + np .fliplr (a ) + np .flipud (a ) + np .flip (a ))/ 4.
69+
70+ r = 0.5 * (3.25 / 4.25 )** (1.5 ) / 1.5 # source-boundary projection
71+ B = (a [2 , 2 ], a [3 , 2 ], a [2 , 3 ], a [3 , 3 ],
72+ a [4 , 2 ], a [2 , 4 ], a [3 , 4 ], a [4 , 4 ])
73+
74+ A = np .array ([[- 2 , - 2 , 0 , 0 , 0 , 0 , 0 ],
75+ [0 , 1 , 0 , - 1 , - 2 , 0 , 0 ],
76+ [1 , 0 , - 1 , 0 , - 2 , 0 , 0 ],
77+ [0 , 0 , 0 , 0 , 2 , - 2 , 0 ],
78+ [0 , 0 , 0 , 1 , 0 , - 2 * r , 0 ],
79+ [0 , 0 , 1 , 0 , 0 , - 2 * r , 0 ],
80+ [0 , 0 , 0 , 0 , 0 , 1 + r , - 1 ],
81+ [0 , 0 , 0 , 0 , 0 , 0 , 2 ]])
82+
83+ s1 , s2 , s3 , s4 , s5 , s6 , s7 = np .linalg .lstsq (A , B , rcond = None )[0 ]
84+
85+ aR = np .array ([[0. , - s7 , - r * s6 , r * s6 , s7 ],
86+ [0. , - s6 , - s5 , s5 , s6 ],
87+ [0. , - s3 , - s1 , s1 , s3 ],
88+ [0. , - s6 , - s5 , s5 , s6 ],
89+ [0. , - s7 , - r * s6 , r * s6 , s7 ],])
90+
91+ aT = np .array ([[0. , 0. , 0. , 0. , 0. ],
92+ [- s7 , - s6 , - s4 , - s6 , - s7 ],
93+ [- r * s6 , - s5 , - s2 , - s5 , - r * s6 ],
94+ [r * s6 , s5 , s2 , s5 , r * s6 ],
95+ [s7 , s6 , s4 , s6 , s7 ],])
9896
9997 aL = aR [::- 1 , ::- 1 ]
10098 aB = aT [::- 1 , ::- 1 ]
10199
100+ a_components [0 , :, :, n , m ] = aR [:, :]
101+ a_components [1 , :, :, n , m ] = aT [:, :]
102+ a_components [2 , :, :, n , m ] = aL [:, :]
103+ a_components [3 , :, :, n , m ] = aB [:, :]
102104
105+ # =============================
106+ # Apply bfe to image
107+ # =============================
103108
104-
105- a_components [0 , :,:, n , m ] = aR [:,:]
106- a_components [1 , :,:, n , m ] = aT [:,:]
107- a_components [2 , :,:, n , m ] = aL [:,:]
108- a_components [3 , :,:, n , m ] = aB [:,:]
109-
110- ##=============================
111- ## Apply bfe to image
112- ##=============================
113-
114- ## pad and expand kernels
115- ## The img is clipped by the saturation level here to cap the brighter fatter effect and avoid unphysical behavior
109+ # pad and expand kernels
110+ # The img is clipped by the saturation level here to cap the brighter fatter effect
111+ # and avoid unphysical behavior
116112
117113 # array_pad = image.copy().array
118114 # saturation_array = np.ones_like(array_pad) * self.saturation_level
119115 # where_sat = np.where(array_pad > saturation_array)
120116 # array_pad[ where_sat ] = saturation_array[ where_sat ]
121117 # array_pad = array_pad[4:-4,4:-4]
122118 saturate = self .cross_refer ('saturate' )
123- array_pad = saturate .apply (image = image .copy ()).array [4 :- 4 ,4 :- 4 ] # img of interest 4088x4088
124- array_pad = np .pad (array_pad , [(4 + nbfe ,4 + nbfe ),(4 + nbfe ,4 + nbfe )], mode = 'symmetric' ) #4100x4100 array
125-
119+ array_pad = saturate .apply (image = image .copy ()).array [4 :- 4 , 4 :- 4 ] # img of interest 4088x4088
120+ array_pad = np .pad (array_pad , [(4 + nbfe , 4 + nbfe ), (4 + nbfe , 4 + nbfe )],
121+ mode = 'symmetric' ) # 4100x4100 array
126122
127- dQ_components = np .zeros ( (4 , bin_size * n_max , bin_size * m_max ) ) #(4, 4096, 4096) in order of [aR, aT, aL, aB]
123+ # (4, 4096, 4096) in order of [aR, aT, aL, aB]
124+ dQ_components = np .zeros ((4 , bin_size * n_max , bin_size * m_max ))
128125
126+ # run in sub grids to reduce memory
129127
130- ### run in sub grids to reduce memory
131-
132- ## pad and expand kernels
128+ # pad and expand kernels
133129 t = np .zeros ((bin_size * n_sub , n_sub ))
134130 for row in range (t .shape [0 ]):
135- t [row , row // (bin_size ) ] = 1
136-
137-
131+ t [row , row // (bin_size )] = 1
138132
139133 for gj in range (num_grids ):
140134 for gi in range (num_grids ):
141135
142- a_components_pad = np .zeros ( (4 , 2 * nbfe + 1 , 2 * nbfe + 1 , bin_size * n_sub + 2 * nbfe , bin_size * m_sub + 2 * nbfe ) ) #(4,5,5,sub_grid,sub_grid)
143-
136+ # (4,5,5,sub_grid,sub_grid)
137+ a_components_pad = np .zeros ((4 , 2 * nbfe + 1 , 2 * nbfe + 1 , bin_size
138+ * n_sub + 2 * nbfe , bin_size * m_sub + 2 * nbfe ))
144139
145140 for comp in range (4 ):
146141 for j in range (2 * nbfe + 1 ):
147142 for i in range (2 * nbfe + 1 ):
148- tmp = (t .dot ( a_components [comp ,j ,i ,gj * n_sub :(gj + 1 )* n_sub ,gi * m_sub :(gi + 1 )* m_sub ] ) ).dot (t .T ) #sub_grid*sub_grid
149- a_components_pad [comp , j , i , :, :] = np .pad (tmp , [(nbfe ,nbfe ),(nbfe ,nbfe )], mode = 'symmetric' )
143+ # sub_grid*sub_grid
144+ tmp = (t .dot (a_components [comp , j , i , gj * n_sub :(gj + 1 )
145+ * n_sub , gi * m_sub :(gi + 1 )* m_sub ])).dot (t .T )
146+ a_components_pad [comp , j , i , :, :] = np .pad (
147+ tmp , [(nbfe , nbfe ), (nbfe , nbfe )], mode = 'symmetric' )
150148
151- #convolve aX_ij with Q_ij
149+ # convolve aX_ij with Q_ij
152150 for comp in range (4 ):
153151 for dy in range (- nbfe , nbfe + 1 ):
154152 for dx in range (- nbfe , nbfe + 1 ):
155- dQ_components [comp , gj * bin_size * n_sub : (gj + 1 )* bin_size * n_sub , gi * bin_size * m_sub : (gi + 1 )* bin_size * m_sub ]\
156- += a_components_pad [comp , nbfe + dy , nbfe + dx , nbfe - dy :nbfe - dy + bin_size * n_sub , nbfe - dx :nbfe - dx + bin_size * m_sub ]\
157- * array_pad [ - dy + nbfe + gj * bin_size * n_sub : - dy + nbfe + (gj + 1 )* bin_size * n_sub , - dx + nbfe + gi * bin_size * m_sub : - dx + nbfe + (gi + 1 )* bin_size * m_sub ]
153+ dQ_components [comp , gj * bin_size * n_sub : (gj + 1 )* bin_size * n_sub ,
154+ gi * bin_size * m_sub : (gi + 1 )* bin_size * m_sub ]\
155+ += a_components_pad [comp , nbfe + dy , nbfe + dx , nbfe - dy :nbfe - dy + bin_size * n_sub ,
156+ nbfe - dx :nbfe - dx + bin_size * m_sub ]\
157+ * array_pad [- dy + nbfe + gj * bin_size * n_sub : - dy + nbfe
158+ + (gj + 1 )* bin_size * n_sub , - dx + nbfe + gi * bin_size * m_sub : - dx
159+ + nbfe + (gi + 1 )* bin_size * m_sub ]
158160
159161 dj = int (np .sin (comp * np .pi / 2 ))
160162 di = int (np .cos (comp * np .pi / 2 ))
161163
162- dQ_components [comp , gj * bin_size * n_sub : (gj + 1 )* bin_size * n_sub , gi * bin_size * m_sub : (gi + 1 )* bin_size * m_sub ]\
163- *= 0.5 * (array_pad [ nbfe + gj * bin_size * n_sub : nbfe + (gj + 1 )* bin_size * n_sub , nbfe + gi * bin_size * m_sub : nbfe + (gi + 1 )* bin_size * m_sub ] + \
164- array_pad [dj + nbfe + gj * bin_size * n_sub : dj + nbfe + (gj + 1 )* bin_size * n_sub , di + nbfe + gi * bin_size * m_sub : di + nbfe + (gi + 1 )* bin_size * m_sub ] )
164+ dQ_components [comp , gj * bin_size * n_sub : (gj + 1 )* bin_size * n_sub ,
165+ gi * bin_size * m_sub : (gi + 1 )* bin_size * m_sub ]\
166+ *= 0.5 * (array_pad [nbfe + gj * bin_size * n_sub : nbfe + (gj + 1 )* bin_size * n_sub ,
167+ nbfe + gi * bin_size * m_sub : nbfe + (gi + 1 )* bin_size * m_sub ]
168+ + array_pad [dj + nbfe + gj * bin_size * n_sub : dj + nbfe + (gj + 1 )* bin_size * n_sub
169+ , di + nbfe + gi * bin_size * m_sub : di + nbfe + (gi + 1 )* bin_size * m_sub ])
165170
166- image .array [:,:] -= dQ_components .sum (axis = 0 )
167- image .array [:,1 :] += dQ_components [0 ][:,:- 1 ]
168- image .array [1 :,:] += dQ_components [1 ][:- 1 ,:]
169- image .array [:,:- 1 ] += dQ_components [2 ][:,1 :]
170- image .array [:- 1 ,:] += dQ_components [3 ][1 :,:]
171+ image .array [:, :] -= dQ_components .sum (axis = 0 )
172+ image .array [:, 1 :] += dQ_components [0 ][:, :- 1 ]
173+ image .array [1 :, :] += dQ_components [1 ][:- 1 , :]
174+ image .array [:, :- 1 ] += dQ_components [2 ][:, 1 :]
175+ image .array [:- 1 , :] += dQ_components [3 ][1 :, :]
171176
172- return image
177+ return image
0 commit comments