Skip to content

Commit

Permalink
add unit test code for new InstCatTrimmer; delete unused GsObjectDict…
Browse files Browse the repository at this point in the history
… class
  • Loading branch information
jchiang87 committed Sep 13, 2018
1 parent 2786b1f commit 4a64601
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 54 deletions.
39 changes: 0 additions & 39 deletions python/desc/imsim/imSim.py
Original file line number Diff line number Diff line change
Expand Up @@ -536,45 +536,6 @@ def parsePhoSimInstanceFile(fileName, sensor_list, numRows=None):
([], gs_object_dict))


class GsObjectDict:
"""
Dictionary-like class to provide access to lists of
GalSimCelestialObjects from an instance catalog on a per-sensor
basis. This class uses InstCatTrimmer to downselect the object
entries via acceptance cones centered on the sensor of interest
and to defer the creation of the GalSimCelestialObjects until
the data for the specified sensor are requested.
"""
def __init__(self, instcat_trimmer, phot_params, radius=0.18):
"""
Parameters
----------
instcat_trimmer: InstCatTrimmer
This object manages the GalSimCelestialObject creation.
phot_params: PhotometricParameters
Photometric parameter info for the visit.
radius: float [0.18]
Acceptance cone radius, in degrees, for downselecting objects
for a single CCD.
"""
self.instcat_trimmer = instcat_trimmer
self.phot_params = phot_params
self.radius = radius

def __iter__(self):
for detector in self.instcat_trimmer._camera:
yield detector.getName()

def __getitem__(self, chip_name):
object_lines \
= self.instcat_trimmer.get_object_entries(chip_name,
radius=self.radius)
obs_md = self.instcat_trimmer.obs_md
file_name = self.instcat_trimmer.instcat_file
return GsObjectList(object_lines, obs_md, self.phot_params, file_name,
chip_name=chip_name)


class GsObjectList:
"""
List-like class to provide access to lists of objects from an
Expand Down
34 changes: 19 additions & 15 deletions python/desc/imsim/trim.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Function to apply chip-centered acceptance cones on instance catalogs.
"""
from collections import defaultdict
import numpy as np
import lsst.sims.coordUtils
from lsst.sims.utils import _angularSeparation
Expand Down Expand Up @@ -94,31 +95,22 @@ def get_object_entries(self, chip_name, radius=0.18, sort_magnorm=True):
Returns
-------
list: list of object entries from the original instance catalog.
list, int: (list of object entries from the original instance catalog,
number of sersic objects for minsource application)
Notes
-----
This function applies the 'minsource' criterion to the sersic
galaxies in the instance catalog if 'minsource' is included in
the instance catalog commands.
"""
ra0, dec0 = self.compute_chip_center(chip_name)
seps = degrees_separation(ra0, dec0, self._ra, self._dec)
index = np.where(seps < radius)

if (self.trimmer.minsource is not None and
sum(self._sersic[index]) < self.trimmer.minsource):
# Apply the minsource criterion.
return []

# Collect the selected objects.
selected = [self.object_lines[i] for i in index[0]]
if sort_magnorm:
# Sort by magnorm.
sorted_index = np.argsort(self._magnorm[index])
selected = [selected[i] for i in sorted_index]

return selected
return selected, sum(self._sersic[index])

class InstCatTrimmer(dict):
"""
Expand All @@ -137,7 +129,7 @@ class InstCatTrimmer(dict):
"""
def __init__(self, instcat, sensor_list, chunk_size=int(3e5),
radius=0.18, numRows=None):
radius=0.18, numRows=None, minsource=None):
"""
Parameters
----------
Expand All @@ -155,10 +147,15 @@ def __init__(self, instcat, sensor_list, chunk_size=int(3e5),
sensor.
numRows: int [None]
Maximum number of rows to read in from the instance catalog.
minsource: int [None]
Minimum number of galaxies in a given sensor acceptance cone.
If not None, this overrides the value in the instance catalog.
"""
super(InstCatTrimmer, self).__init__()
self.instcat_file = instcat
self._read_commands()
if minsource is not None:
self.minsource = minsource
self._process_objects(sensor_list, chunk_size, radius=radius,
numRows=numRows)

Expand All @@ -170,23 +167,30 @@ def _process_objects(self, sensor_list, chunk_size, radius=0.18,
for each sensor using the Disaggregator class to apply the
acceptance cone cut centered on each sensor.
"""
num_gals = defaultdict(lambda: 0)
self.update({sensor: [] for sensor in sensor_list})
with desc.imsim.fopen(self.instcat_file, mode='rt') as fd:
nread = 0
while numRows is None or nread < numRows:
object_lines = []
ichunk = 0
for ichunk, line in zip(range(chunk_size), fd):
nread += 1
if not line.startswith('object'):
continue
object_lines.append(line)
disaggregator = Disaggregator(object_lines, self)
for sensor in self:
obj_list = disaggregator.get_object_entries(sensor,
radius=radius)
obj_list, nsersic = disaggregator\
.get_object_entries(sensor, radius=radius)
self[sensor].extend(obj_list)
num_gals[sensor] += nsersic
if ichunk < chunk_size - 1:
break
for sensor in self:
# Apply minsource criterion on galaxies.
if self.minsource is not None and num_gals[sensor] < self.minsource:
self[sensor] = []

def _read_commands(self):
"""Read in the commands from the instance catalog."""
Expand Down
39 changes: 39 additions & 0 deletions tests/test_trimmer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""
Unit tests for InstCatTrimmer class.
"""
import os
import unittest
import desc.imsim


class InstCatTrimmerTestCase(unittest.TestCase):
"""
TestCase class for InstCatTrimmer.
"""
def setUp(self):
pass

def tearDown(self):
pass

def test_InstCatTrimmer(self):
"""Unit test for InstCatTrimmer class."""
instcat = os.path.join(os.environ['IMSIM_DIR'], 'tests',
'tiny_instcat.txt')
sensor = 'R:2,2 S:1,1'

# Check the application of minsource.
objs = desc.imsim.InstCatTrimmer(instcat, [sensor], minsource=10)
self.assertEqual(len(objs[sensor]), 24)

objs = desc.imsim.InstCatTrimmer(instcat, [sensor], minsource=12)
self.assertEqual(len(objs[sensor]), 0)

# Check various values of chunk_size.
for chunk_size in (5, 10, 100):
objs = desc.imsim.InstCatTrimmer(instcat, [sensor], minsource=None,
chunk_size=chunk_size)
self.assertEqual(len(objs[sensor]), 24)

if __name__ == '__main__':
unittest.main()

0 comments on commit 4a64601

Please sign in to comment.