66from galsim .config import RegisterImageType
77from galsim .config .image_scattered import ScatteredImageBuilder
88from galsim .image import Image
9+ import gc
910
1011
11- class RomanSCAImageBuilder (ScatteredImageBuilder ):
12+ class RomanSCAImageBuilderCMOS (ScatteredImageBuilder ):
1213
1314 def setup (self , config , base , image_num , obj_num , ignore , logger ):
1415 """Do the initialization and setup for building the image.
@@ -123,8 +124,8 @@ def buildImage(self, config, base, image_num, obj_num, logger):
123124 full_xsize = base ["image_xsize" ]
124125 full_ysize = base ["image_ysize" ]
125126 wcs = base ["wcs" ]
126-
127-
127+ rdata = galsim . config . GetInputObj ( "resultant_data" , config , base , "ResultantDataLoader" )
128+ strategy = rdata . get ( "strategy" )
128129 full_image = Image (full_xsize , full_ysize , dtype = float )
129130 full_image .setOrigin (base ["image_origin" ])
130131 full_image .wcs = wcs
@@ -155,62 +156,97 @@ def buildImage(self, config, base, image_num, obj_num, logger):
155156 "x" : {"type" : "Random" , "min" : xmin , "max" : xmax },
156157 "y" : {"type" : "Random" , "min" : ymin , "max" : ymax },
157158 }
158-
159- nbatch = self .nobjects // 1000 + 1
160- full_array = galsim .PhotonArray (0 )
161- for batch in range (nbatch ):
162- start_obj_num = self .nobjects * batch // nbatch
163- end_obj_num = self .nobjects * (batch + 1 ) // nbatch
164- nobj_batch = end_obj_num - start_obj_num
165- if nbatch > 1 :
166- logger .warning (
167- "Start batch %d/%d with %d objects [%d, %d)" ,
168- batch + 1 ,
169- nbatch ,
170- nobj_batch ,
171- start_obj_num ,
172- end_obj_num ,
159+ #Create index and lists for resultant management
160+ max_dt = strategy [- 1 ][- 1 ]
161+ resultant_i = 0
162+ resultant_buffer = []
163+ #Iterate through all dt
164+ for dt in np .arange (1 ,max_dt + 1 ):
165+
166+ nbatch = self .nobjects // 1000 + 1
167+ full_array = galsim .PhotonArray (0 )
168+ for batch in range (nbatch ):
169+ start_obj_num = self .nobjects * batch // nbatch
170+ end_obj_num = self .nobjects * (batch + 1 ) // nbatch
171+ nobj_batch = end_obj_num - start_obj_num
172+ if nbatch > 1 :
173+ logger .warning (
174+ "Start batch %d/%d with %d objects [%d, %d)" ,
175+ batch + 1 ,
176+ nbatch ,
177+ nobj_batch ,
178+ start_obj_num ,
179+ end_obj_num ,
180+ )
181+ stamps , current_vars = galsim .config .BuildStamps (
182+ nobj_batch , base , logger = logger , obj_num = start_obj_num , do_noise = False
173183 )
174- stamps , current_vars = galsim .config .BuildStamps (
175- nobj_batch , base , logger = logger , obj_num = start_obj_num , do_noise = False
176- )
177- base ["index_key" ] = "image_num"
178-
179- for k in range (nobj_batch ):
180- # This is our signal that the object was skipped.
181- if stamps [k ] is None :
182- continue
183- bounds = full_image .bounds # stamps[k].bounds &
184- if not bounds .isDefined (): # pragma: no cover
185- # These noramlly show up as stamp==None, but technically it is possible
186- # to get a stamp that is off the main image, so check for that here to
187- # avoid an error. But this isn't covered in the imsim test suite.
188- continue
189-
190- # logger.debug("image %d: full bounds = %s", image_num, str(full_image.bounds))
191- # logger.debug(
192- # "image %d: stamp %d bounds = %s",
193- # image_num,
194- # k + start_obj_num,
195- # str(stamps[k].bounds),
196- # )
197- # logger.debug("image %d: Overlap = %s", image_num, str(bounds))
198- # full_image[bounds] += stamps[k][bounds]
199- #logger.warning(stamps[k])
200- full_array = galsim .PhotonArray .concatenate ([* stamps ,full_array ])
201-
202- stamps = None
203-
204- # # Bring the image so far up to a flat noise variance
205- # current_var = FlattenNoiseVariance(
206- # base, full_image, stamps, current_vars, logger)
207-
208- full_array .addTo (full_image )
209- full_array .write ("photonarray.fits" )
210- full_image .write ("phot_image.fits" )
184+ base ["index_key" ] = "image_num"
185+
186+ for k in range (nobj_batch ):
187+ # This is our signal that the object was skipped.
188+ if stamps [k ] is None :
189+ continue
190+ bounds = full_image .bounds # stamps[k].bounds &
191+ if not bounds .isDefined (): # pragma: no cover
192+ # These noramlly show up as stamp==None, but technically it is possible
193+ # to get a stamp that is off the main image, so check for that here to
194+ # avoid an error. But this isn't covered in the imsim test suite.
195+ continue
196+
197+ # logger.debug("image %d: full bounds = %s", image_num, str(full_image.bounds))
198+ # logger.debug(
199+ # "image %d: stamp %d bounds = %s",
200+ # image_num,
201+ # k + start_obj_num,
202+ # str(stamps[k].bounds),
203+ # )
204+ # logger.debug("image %d: Overlap = %s", image_num, str(bounds))
205+ # full_image[bounds] += stamps[k][bounds]
206+ #logger.warning(stamps[k])
207+ full_array = galsim .PhotonArray .concatenate ([* stamps ,full_array ])
208+
209+ stamps = None
210+
211+ # # Bring the image so far up to a flat noise variance
212+ # current_var = FlattenNoiseVariance(
213+ # base, full_image, stamps, current_vars, logger)
214+ #TODO : Apply BFE photon operation (uses current pre-read image and next photon array)
215+
216+ # Turn full_image into running pre-read image
217+ full_array .addTo (full_image )
218+ del full_array
219+ gc .collect ()
220+ # Decide what to do with readout based on resultant strategy
221+ if (np .array ([item for sub in strategy for item in sub ]) == dt ).any ():
222+ if (np .array (strategy [resultant_i ]) == dt ).any ():
223+ readout_im = full_image .copy ()
224+ readout_im = self .addNoiseToImage (readout_im , config , base , logger )
225+ resultant_buffer .extend ([readout_im ])
226+ if len (resultant_buffer )> 1 :
227+ #combine readout images
228+ resultant_buffer [0 ].array = resultant_buffer [0 ].array + resultant_buffer [1 ].array
229+ del resultant_buffer [- 1 ]
230+ gc .collect ()
231+
232+ if np .array (strategy [resultant_i ][- 1 ]) == dt :
233+ divisor = len (np .array (strategy [resultant_i ]))
234+ #divide summed images by the length of resultant to get the average and apply headers to the image array
235+ #TODO:apply header to the image array
236+ resultant_buffer [0 ].array = resultant_buffer [0 ].array / divisor
237+ resultant_buffer [0 ].write ('resultant_{0}.fits' .format (resultant_i ))
238+ resultant_i += 1
239+ resultant_buffer = []
240+ logger .warning ('resultant{0} done' .format (resultant_i ))
241+
242+
243+
244+ # full_array.write("photonarray.fits")
245+ # full_image.write("phot_image.fits")
246+
211247 return full_image , None
212248
213- def addNoise (self , image , config , base , image_num , obj_num , current_var , logger ):
249+ def addNoiseToImage (self , image , config , base , logger ):
214250 """Add the final noise to a Scattered image
215251
216252 Parameters:
@@ -224,7 +260,7 @@ def addNoise(self, image, config, base, image_num, obj_num, current_var, logger)
224260 """
225261 # check ignore noise
226262 if self .ignore_noise :
227- return
263+ return image
228264
229265 base ["current_noise_image" ] = base ["current_image" ]
230266 wcs = base ["wcs" ]
@@ -314,7 +350,11 @@ def addNoise(self, image, config, base, image_num, obj_num, current_var, logger)
314350 sky_image /= roman .gain
315351 sky_image .quantize ()
316352 image -= sky_image
353+ return image
354+
355+ def addNoise (self , image , config , base , image_num , obj_num , current_var , logger ):
356+ pass
317357
318358
319359# Register this as a valid type
320- RegisterImageType ("roman_sca " , RomanSCAImageBuilder ())
360+ RegisterImageType ("roman_sca_cmos " , RomanSCAImageBuilderCMOS ())
0 commit comments