diff --git a/.travis.yml b/.travis.yml index 6621e7de..e1438232 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ dist: trusty compiler: gcc env: - - OS_TYPE=centos OS_VERSION=7 DOCKER_IMAGE=lsstdesc/stack-sims:w_2019_23-sims_w_2019_23 + - OS_TYPE=centos OS_VERSION=7 DOCKER_IMAGE=lsstdesc/stack-sims:w_2019_37-sims_w_2019_37 services: - docker diff --git a/python/desc/imsim/ImageSimulator.py b/python/desc/imsim/ImageSimulator.py index 7f1cd728..90a833c5 100644 --- a/python/desc/imsim/ImageSimulator.py +++ b/python/desc/imsim/ImageSimulator.py @@ -417,9 +417,6 @@ def __call__(self, gs_objects): if nan_fluxes > 0: logger.info("%s objects had nan fluxes", nan_fluxes) - # Recover the memory devoted to the GalSimCelestialObject instances. - gs_objects.reset() - add_cosmic_rays(gs_interpreter, IMAGE_SIMULATOR.phot_params) full_well = int(IMAGE_SIMULATOR.config['ccd']['full_well']) apply_channel_bleeding(gs_interpreter, full_well) diff --git a/python/desc/imsim/camera_info.py b/python/desc/imsim/camera_info.py index 42cf5fae..0b05cf03 100644 --- a/python/desc/imsim/camera_info.py +++ b/python/desc/imsim/camera_info.py @@ -2,7 +2,7 @@ Class to encapsulate info from lsst.obs.lsst.imsim.ImsimMapper().camera. """ import astropy.time -import lsst.afw.geom as afw_geom +import lsst.geom as lsst_geom from lsst.obs.lsst.imsim import ImsimMapper __all__ = ['CameraInfo', 'getHourAngle'] @@ -65,15 +65,15 @@ def mosaic_section(amp_info): Returns ------- - lsst.afw.geom.Box2I + lsst.geom.Box2I """ yseg, xseg = (int(x) for x in amp_info.getName()[-2:]) width = amp_info.getBBox().getWidth() height = amp_info.getBBox().getHeight() xmin = xseg*width ymin = 0 if yseg == 1 else height - return afw_geom.Box2I(afw_geom.Point2I(xmin, ymin), - afw_geom.Extent2I(width, height)) + return lsst_geom.Box2I(lsst_geom.Point2I(xmin, ymin), + lsst_geom.Extent2I(width, height)) def getHourAngle(observatory, mjd, ra): diff --git a/python/desc/imsim/camera_readout.py b/python/desc/imsim/camera_readout.py index 245d62d2..90d32161 100644 --- a/python/desc/imsim/camera_readout.py +++ b/python/desc/imsim/camera_readout.py @@ -23,7 +23,7 @@ from astropy.io import fits import astropy.time import galsim -import lsst.afw.geom as afwGeom +import lsst.geom as lsst_geom import lsst.afw.image as afwImage with warnings.catch_warnings(): warnings.simplefilter('ignore') @@ -567,7 +567,7 @@ def _noao_section_keyword(bbox, flipx=False, flipy=False): Parameters ---------- - bbox : lsst.afw.geom.Box2I + bbox : lsst.geom.Box2I Bounding box. flipx : bool Flag to indicate that data should be flipped in the x-direction. @@ -598,16 +598,16 @@ def set_itl_bboxes(amp): lsst.afw.table.tableLib.AmpInfoRecord The updated AmpInfoRecord. """ - amp.setRawBBox(afwGeom.Box2I(afwGeom.Point2I(0, 0), - afwGeom.Extent2I(544, 2048))) - amp.setRawDataBBox(afwGeom.Box2I(afwGeom.Point2I(3, 0), - afwGeom.Extent2I(509, 2000))) - amp.setRawHorizontalOverscanBBox(afwGeom.Box2I(afwGeom.Point2I(512, 0), - afwGeom.Extent2I(48, 2000))) - amp.setRawVerticalOverscanBBox(afwGeom.Box2I(afwGeom.Point2I(0, 2000), - afwGeom.Extent2I(544, 48))) - amp.setRawPrescanBBox(afwGeom.Box2I(afwGeom.Point2I(0, 0), - afwGeom.Extent2I(3, 2000))) + amp.setRawBBox(lsst_geom.Box2I(lsst_geom.Point2I(0, 0), + lsst_geom.Extent2I(544, 2048))) + amp.setRawDataBBox(lsst_geom.Box2I(lsst_geom.Point2I(3, 0), + lsst_geom.Extent2I(509, 2000))) + amp.setRawHorizontalOverscanBBox(lsst_geom.Box2I(lsst_geom.Point2I(512, 0), + lsst_geom.Extent2I(48, 2000))) + amp.setRawVerticalOverscanBBox(lsst_geom.Box2I(lsst_geom.Point2I(0, 2000), + lsst_geom.Extent2I(544, 48))) + amp.setRawPrescanBBox(lsst_geom.Box2I(lsst_geom.Point2I(0, 0), + lsst_geom.Extent2I(3, 2000))) return amp @@ -626,16 +626,16 @@ def set_e2v_bboxes(amp): lsst.afw.table.tableLib.AmpInfoRecord The updated AmpInfoRecord. """ - amp.setRawBBox(afwGeom.Box2I(afwGeom.Point2I(0, 0), - afwGeom.Extent2I(542, 2022))) - amp.setRawDataBBox(afwGeom.Box2I(afwGeom.Point2I(10, 0), - afwGeom.Extent2I(522, 2002))) - amp.setRawHorizontalOverscanBBox(afwGeom.Box2I(afwGeom.Point2I(522, 0), - afwGeom.Extent2I(20, 2002))) - amp.setRawVerticalOverscanBBox(afwGeom.Box2I(afwGeom.Point2I(0, 2002), - afwGeom.Extent2I(542, 20))) - amp.setRawPrescanBBox(afwGeom.Box2I(afwGeom.Point2I(0, 0), - afwGeom.Extent2I(10, 2002))) + amp.setRawBBox(lsst_geom.Box2I(lsst_geom.Point2I(0, 0), + lsst_geom.Extent2I(542, 2022))) + amp.setRawDataBBox(lsst_geom.Box2I(lsst_geom.Point2I(10, 0), + lsst_geom.Extent2I(522, 2002))) + amp.setRawHorizontalOverscanBBox(lsst_geom.Box2I(lsst_geom.Point2I(522, 0), + lsst_geom.Extent2I(20, 2002))) + amp.setRawVerticalOverscanBBox(lsst_geom.Box2I(lsst_geom.Point2I(0, 2002), + lsst_geom.Extent2I(542, 20))) + amp.setRawPrescanBBox(lsst_geom.Box2I(lsst_geom.Point2I(0, 0), + lsst_geom.Extent2I(10, 2002))) return amp @@ -654,16 +654,16 @@ def set_phosim_bboxes(amp): lsst.afw.table.tableLib.AmpInfoRecord The updated AmpInfoRecord. """ - amp.setRawBBox(afwGeom.Box2I(afwGeom.Point2I(0, 0), - afwGeom.Extent2I(519, 2001))) - amp.setRawDataBBox(afwGeom.Box2I(afwGeom.Point2I(4, 1), - afwGeom.Extent2I(509, 2000))) - amp.setRawHorizontalOverscanBBox(afwGeom.Box2I(afwGeom.Point2I(513, 1), - afwGeom.Extent2I(6, 2000))) - amp.setRawVerticalOverscanBBox(afwGeom.Box2I(afwGeom.Point2I(0, 2001), - afwGeom.Extent2I(519, 0))) - amp.setRawPrescanBBox(afwGeom.Box2I(afwGeom.Point2I(0, 1), - afwGeom.Extent2I(4, 2000))) + amp.setRawBBox(lsst_geom.Box2I(lsst_geom.Point2I(0, 0), + lsst_geom.Extent2I(519, 2001))) + amp.setRawDataBBox(lsst_geom.Box2I(lsst_geom.Point2I(4, 1), + lsst_geom.Extent2I(509, 2000))) + amp.setRawHorizontalOverscanBBox(lsst_geom.Box2I(lsst_geom.Point2I(513, 1), + lsst_geom.Extent2I(6, 2000))) + amp.setRawVerticalOverscanBBox(lsst_geom.Box2I(lsst_geom.Point2I(0, 2001), + lsst_geom.Extent2I(519, 0))) + amp.setRawPrescanBBox(lsst_geom.Box2I(lsst_geom.Point2I(0, 1), + lsst_geom.Extent2I(4, 2000))) return amp PixelParameters = namedtuple('PixelParameters', diff --git a/python/desc/imsim/imSim.py b/python/desc/imsim/imSim.py index b74e5c0b..df6510a0 100644 --- a/python/desc/imsim/imSim.py +++ b/python/desc/imsim/imSim.py @@ -54,7 +54,6 @@ __all__ = ['PhosimInstanceCatalogParseError', 'photometricParameters', 'phosim_obs_metadata', - 'sources_from_list', 'metadata_from_file', 'read_config', 'get_config', 'get_logger', 'get_image_dirs', 'get_obs_lsstSim_camera', @@ -62,7 +61,7 @@ '_POINT_SOURCE', '_SERSIC_2D', '_RANDOM_WALK', '_FITS_IMAGE', 'parsePhoSimInstanceFile', 'add_treering_info', 'airmass', 'FWHMeff', 'FWHMgeom', 'make_psf', - 'save_psf', 'load_psf', 'TracebackDecorator'] + 'save_psf', 'load_psf', 'TracebackDecorator', 'GsObjectList'] class PhosimInstanceCatalogParseError(RuntimeError): @@ -159,268 +158,6 @@ def uss_mem(): return my_process.memory_full_info().uss/1024.**3 -def sources_from_list(object_lines, obs_md, phot_params, file_name, - target_chip=None, log_level='INFO'): - """. - - Parse the object lines from a phosim-style instance catalog and - repackage as GalSimCelestialObjects after applying on-chip - selections and consistency cuts on mag_norm, extinction - parameters, and galaxy shape and knot parameters. - - Parameters - ---------- - object_lines: list - List of object line entries from the instance catalog. - obs_md: ObservationMetaData - Visit-specific metadata from the instance catalog. - phot_params: PhotometricParameters - Visit-specific photometric data needed for computing object - fluxes. - file_name: str - The filename path of the instance catalog, used for inferring - the location of the Dynamic SEDs used by the sprinkled objects. - target_chip: str [None] - For multiprocessing mode, this is the name of the chip - (e.g., "R:2,2 S:1,1") being simulated. If None, then - of the object lines are partitioned among all 189 science - sensors in the LSST focalplane. Since this is a costly - calculation, doing it only for the target chip saves a lot - of compute time. - log_level: str ['INFO'] - Logging level. - - Returns - ------- - list, dict: A list of all the GalSimCelestialObjects that pass - the focalplane-level selections and a dict of those objects keyed - by chip name. - """ - camera = get_obs_lsstSim_camera() - config = get_config() - logger = get_logger(log_level, name=(target_chip if target_chip is - not None else 'sources_from_list')) - - num_objects = len(object_lines) - - logger.debug('allocating object arrays, %s GB', uss_mem()) - # RA, Dec in the coordinate system expected by PhoSim - ra_phosim = np.zeros(num_objects, dtype=float) - dec_phosim = np.zeros(num_objects, dtype=float) - - sed_name = [None]*num_objects - mag_norm = 55.0*np.ones(num_objects, dtype=float) - gamma1 = np.zeros(num_objects, dtype=float) - gamma2 = np.zeros(num_objects, dtype=float) - gamma2_sign = config['wl_params']['gamma2_sign'] - kappa = np.zeros(num_objects, dtype=float) - - internal_av = np.zeros(num_objects, dtype=float) - internal_rv = np.zeros(num_objects, dtype=float) - galactic_av = np.zeros(num_objects, dtype=float) - galactic_rv = np.zeros(num_objects, dtype=float) - semi_major_arcsec = np.zeros(num_objects, dtype=float) - semi_minor_arcsec = np.zeros(num_objects, dtype=float) - position_angle_degrees = np.zeros(num_objects, dtype=float) - sersic_index = np.zeros(num_objects, dtype=float) - npoints = np.zeros(num_objects, dtype=int) - redshift = np.zeros(num_objects, dtype=float) - pixel_scale = np.zeros(num_objects, dtype=float) - rotation_angle = np.zeros(num_objects, dtype=float) - fits_image_file = dict() - - unique_id = [None]*num_objects - object_type = np.zeros(num_objects, dtype=int) - - logger.debug('looping over %s objects; %s GB', num_objects, uss_mem()) - i_obj = -1 - for line in object_lines: - params = line.strip().split() - if params[0] != 'object': - continue - i_obj += 1 - unique_id[i_obj] = params[1] - ra_phosim[i_obj] = float(params[2]) - dec_phosim[i_obj] = float(params[3]) - mag_norm[i_obj] = float(params[4]) - sed_name[i_obj] = params[5] - redshift[i_obj] = float(params[6]) - gamma1[i_obj] = float(params[7]) - gamma2[i_obj] = gamma2_sign*float(params[8]) - kappa[i_obj] = float(params[9]) - if params[12].lower() == 'point': - object_type[i_obj] = _POINT_SOURCE - i_gal_dust_model = 14 - if params[13].lower() != 'none': - i_gal_dust_model = 16 - internal_av[i_obj] = float(params[14]) - internal_rv[i_obj] =float(params[15]) - if params[i_gal_dust_model].lower() != 'none': - galactic_av[i_obj] = float(params[i_gal_dust_model+1]) - galactic_rv[i_obj] = float(params[i_gal_dust_model+2]) - elif params[12].lower() == 'sersic2d': - object_type[i_obj] = _SERSIC_2D - semi_major_arcsec[i_obj] = float(params[13]) - semi_minor_arcsec[i_obj] = float(params[14]) - position_angle_degrees[i_obj] = float(params[15]) - sersic_index[i_obj] = float(params[16]) - i_gal_dust_model = 18 - if params[17].lower() != 'none': - i_gal_dust_model = 20 - internal_av[i_obj] = float(params[18]) - internal_rv[i_obj] = float(params[19]) - if params[i_gal_dust_model].lower() != 'none': - galactic_av[i_obj] = float(params[i_gal_dust_model+1]) - galactic_rv[i_obj] =float(params[i_gal_dust_model+2]) - elif params[12].lower() == 'knots': - object_type[i_obj] = _RANDOM_WALK - semi_major_arcsec[i_obj] = float(params[13]) - semi_minor_arcsec[i_obj] = float(params[14]) - position_angle_degrees[i_obj] = float(params[15]) - npoints[i_obj] = int(params[16]) - i_gal_dust_model = 18 - if params[17].lower() != 'none': - i_gal_dust_model = 20 - internal_av[i_obj] = float(params[18]) - internal_rv[i_obj] = float(params[19]) - if params[i_gal_dust_model].lower() != 'none': - galactic_av[i_obj] = float(params[i_gal_dust_model+1]) - galactic_rv[i_obj] = float(params[i_gal_dust_model+2]) - elif (params[12].endswith('.fits') or params[12].endswith('.fits.gz')): - object_type[i_obj] = _FITS_IMAGE - fits_image_file[i_obj] = find_file_path(params[12], get_image_dirs()) - pixel_scale[i_obj] = float(params[13]) - rotation_angle[i_obj] = float(params[14]) - i_gal_dust_model = 16 - if params[15].lower() != 'none': - i_gal_dust_model = 18 - internal_av[i_obj] = float(params[16]) - internal_rv[i_obj] = float(params[17]) - if params[i_gal_dust_model].lower() != 'none': - galactic_av[i_obj] = float(params[i_gal_dust_model+1]) - galactic_rv[i_obj] = float(params[i_gal_dust_model+2]) - else: - raise RuntimeError("Do not know how to handle " - "object type: %s" % params[12]) - - logger.debug("computing pupil coords, %s GB", uss_mem()) - ra_appGeo, dec_appGeo \ - = PhoSimAstrometryBase._appGeoFromPhoSim(np.radians(ra_phosim), - np.radians(dec_phosim), - obs_md) - - ra_obs_rad, dec_obs_rad \ - = _observedFromAppGeo(ra_appGeo, dec_appGeo, - obs_metadata=obs_md, - includeRefraction=True) - - semi_major_radians = radiansFromArcsec(semi_major_arcsec) - semi_minor_radians = radiansFromArcsec(semi_minor_arcsec) - # Account for PA sign difference wrt phosim convention. - position_angle_radians = np.radians(360. - position_angle_degrees) - - x_pupil, y_pupil = _pupilCoordsFromObserved(ra_obs_rad, - dec_obs_rad, - obs_md) - - bp_dict = BandpassDict.loadTotalBandpassesFromFiles() - - object_is_valid = np.array([True]*num_objects) - - invalid_objects = np.where(np.logical_or(np.logical_or( - mag_norm>50.0, - np.logical_and(galactic_av==0.0, galactic_rv==0.0)), - np.logical_or( - np.logical_and(object_type==_SERSIC_2D, - semi_major_arcsec 0: - message = "\nOmitted %d suspicious objects from " % len(invalid_objects[0]) - message += "the instance catalog:\n" - n_bad_mag_norm = len(np.where(mag_norm>50.0)[0]) - message += " %d had mag_norm > 50.0\n" % n_bad_mag_norm - n_bad_av = len(np.where(np.logical_and(galactic_av==0.0, galactic_rv==0.0))[0]) - message += " %d had galactic_Av == galactic_Rv == 0\n" % n_bad_av - n_bad_axes = len(np.where(np.logical_and(object_type==_SERSIC_2D, - semi_major_arcsec