desihub / specsim

Quick simulations of spectrograph response
2 stars 9 forks source link

changing airmass doesn't work for Simulator object #49

Closed sbailey closed 8 years ago

sbailey commented 8 years ago

I think this is a bug, but it might be user error: I create a Simulator object, simulate a spectrum, and then change the airmass and simulate it again. I'm getting the same sky vector back. However, if I create two different Simulator objects, I get back two different sky vectors as expected.

Works:

import specsim.simulator
from specsim.atmosphere import Moon
import astropy.units as u

wave = np.arange(3500, 9900) * u.Angstrom
flux = np.zeros(len(wave)) * u.erg / (u.s * u.cm**2 * u.Angstrom)

qsim1 = specsim.simulator.Simulator('desi')
qsim1.observation.exposure_time = 1000 * u.s
qsim1.atmosphere.airmass = 1.0
qsim1.source.update_in('sky', 'sky', wave, flux)
qsim1.source.update_out()
qsim1.simulate()

qsim2 = specsim.simulator.Simulator('desi')
qsim2.observation.exposure_time = 1000 * u.s
qsim2.atmosphere.airmass = 2.0
qsim2.source.update_in('sky', 'sky', wave, flux)
qsim2.source.update_out()
qsim2.simulate()

sky1 = qsim1.camera_output[2]['num_sky_electrons']
sky2 = qsim2.camera_output[2]['num_sky_electrons']

np.all(sky1-sky2 != 0)

Fails (same sky vector despite different airmasses):

import specsim.simulator
from specsim.atmosphere import Moon
import astropy.units as u

qsim = specsim.simulator.Simulator('desi')
qsim.observation.exposure_time = 1000 * u.s

wave = np.arange(3500, 9900) * u.Angstrom
flux = np.zeros(len(wave)) * u.erg / (u.s * u.cm**2 * u.Angstrom)

qsim.atmosphere.airmass = 1.0
qsim.source.update_in('sky', 'sky', wave, flux)
qsim.source.update_out()
qsim.simulate()
wx = qsim.camera_output[2]['wavelength']
sky1 = qsim.camera_output[2]['num_sky_electrons']

qsim.atmosphere.airmass = 2.0
qsim.source.update_in('sky', 'sky', wave, flux)
qsim.source.update_out()
qsim.simulate()
sky2 = qsim.camera_output[2]['num_sky_electrons']

np.all(sky1-sky2 != 0)

I'm using specsim master.

rainwoodman commented 8 years ago

Some cache is not invalidated? Is there catch ng and if so is there is func to invalidate recursi vely?

On Oct 11, 2016 11:37 AM, "sbailey" notifications@github.com wrote:

I think this is a bug, but it might be user error: I create a Simulator object, simulate a spectrum, and then change the airmass and simulate it again. I'm getting the same sky vector back. However, if I create two different Simulator objects, I get back two different sky vectors as expected.

Works:

import specsim.simulatorfrom specsim.atmosphere import Moonimport astropy.units as u

wave = np.arange(3500, 9900) * u.Angstrom flux = np.zeros(len(wave)) * u.erg / (u.s * u.cm*2 \ u.Angstrom)

qsim1 = specsim.simulator.Simulator('desi') qsim1.observation.exposure_time = 1000 * u.s qsim1.atmosphere.airmass = 1.0 qsim1.source.update_in('sky', 'sky', wave, flux) qsim1.source.update_out() qsim1.simulate()

qsim2 = specsim.simulator.Simulator('desi') qsim2.observation.exposure_time = 1000 * u.s qsim2.atmosphere.airmass = 2.0 qsim2.source.update_in('sky', 'sky', wave, flux) qsim2.source.update_out() qsim2.simulate()

sky1 = qsim1.camera_output[2]['num_sky_electrons'] sky2 = qsim2.camera_output[2]['num_sky_electrons']

np.all(sky1-sky2 != 0)

Fails (same sky vector despite different airmasses):

import specsim.simulatorfrom specsim.atmosphere import Moonimport astropy.units as u

qsim = specsim.simulator.Simulator('desi') qsim.observation.exposure_time = 1000 * u.s

wave = np.arange(3500, 9900) * u.Angstrom flux = np.zeros(len(wave)) * u.erg / (u.s * u.cm*2 \ u.Angstrom)

qsim.atmosphere.airmass = 1.0 qsim.source.update_in('sky', 'sky', wave, flux) qsim.source.update_out() qsim.simulate() wx = qsim.camera_output[2]['wavelength'] sky1 = qsim.camera_output[2]['num_sky_electrons']

qsim.atmosphere.airmass = 2.0 qsim.source.update_in('sky', 'sky', wave, flux) qsim.source.update_out() qsim.simulate() sky2 = qsim.camera_output[2]['num_sky_electrons']

np.all(sky1-sky2 != 0)

I'm using specsim master.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/desihub/specsim/issues/49, or mute the thread https://github.com/notifications/unsubscribe-auth/AAIbTHrnWuyFZ_uxAx83hobFL2YdyXc7ks5qy9dngaJpZM4KT9cu .

dkirkby commented 8 years ago

I'm looking into it now...

dkirkby commented 8 years ago

It looks like changing the airmass is working correctly, but your test does not compare the different airmass results:

qsim.simulate()
sky1 = qsim.camera_output[2]['num_sky_electrons']
...
qsim.simulate()
sky2 = qsim.camera_output[2]['num_sky_electrons']

The problem is that sky1 and sky2 are references to the same memory, but you can easily fix this by copying the earlier results:

sky1 = qsim.camera_output[2]['num_sky_electrons'].copy()

The documentation of the camera_output attribute already mentions this:

        Tables are listed in order of increasing wavelength and tabulated
        using the output pixels defined for each camera.  Tables are overwritten
        during each call to :meth:`simulate`.  See :doc:`/output` for details
        of the contents of each table in this list.

To be safe, I also added a unit test to specifically check that results change with airmass but its not identical to your test because internal unit tests always use test.yaml instead of desi.yaml:

def test_changing_airmass():
    sim = specsim.simulator.Simulator('test')

    sim.atmosphere.airmass = 1.0
    sim.simulate()
    sky1 = sim.camera_output[0]['num_sky_electrons'].copy()
    sim.atmosphere.airmass = 2.0
    sim.simulate()
    sky2 = sim.camera_output[0]['num_sky_electrons'].copy()

    sum1, sum2 = np.sum(sky1), np.sum(sky2)
    assert sum1 > 0 and sum2 > 0 and sum1 != sum2
sbailey commented 8 years ago

Thanks; I hadn't realized that the output arrays were internally re-used. Closing ticket.