Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate exposure time calculator into the plugin? #66

Open
wyrzykow opened this issue Nov 15, 2024 · 6 comments
Open

Integrate exposure time calculator into the plugin? #66

wyrzykow opened this issue Nov 15, 2024 · 6 comments
Assignees
Labels
enhancement New feature or request User Issue Raised by a user

Comments

@wyrzykow
Copy link

LT has a very nice exp.time calculator on the web: https://telescope.livjm.ac.uk/TelInst/calc/
If that was part of the AEON plugin, it would help automatise the requests from TOMs.
I asked LT for the source code.

@wyrzykow
Copy link
Author

@jchate6 jchate6 added enhancement New feature or request User Issue Raised by a user labels Nov 15, 2024
@github-project-automation github-project-automation bot moved this to Triage in TOM Toolkit Nov 15, 2024
@rachel3834
Copy link

I agree that would be a very desirable feature for the TOM facilities module to have in general.

We took a preliminary look at the LT's ETC code and it appears to be a purely JS application and doesn't offer an API that we could query. In principle, we could integrate this code with the LT module in the Toolkit but we'd prefer to query a service offered by the observatory because that would make it easier for them to update, every time their re-coat the mirrors for instance.

This led to a wider discussion about how we can best implement such a service from an AEON perspective. Given the very wide range of instruments at all the observatories, a fully general-purpose solution may potentially become very complex. Rather than let the perfect be the enemy of the good, I think the first step is for us to start a conversation with the LT folks and explore whether they can add an API for their tool. Similarly, we'd like to update the one for LCO.

@wyrzykow
Copy link
Author

Fair point. An API would be the probably the best solution and I'm sure this would work for LCO, and also probably for LT, if we help them re-write their webpage (no people available at the moment, as far as I know).

Some telescopes we work with in BHTOM do not even have their own webpages, let alone an Exposure Time Calculator. I have been collaborating with a group of students to develop a generic universal Exposure Time Calculator that utilizes all the data we have collected for a given telescope to provide an estimated exposure time. However, this would need to be integrated into the telescope plugin.

What do you think about offering both solutions? We could create a simple built-in exposure time calculator for each observatory, but if they provide an API, that could override the built-in version.

@wyrzykow
Copy link
Author

wyrzykow commented Nov 16, 2024

Here is a re-write of the JS code I made (with some help of ChatGPT), we could use this in the plugin as a good start.
The only missing bit is the sky background, but this could be solved as a drop-down menu (j and sj variables, now fixed).

import math

def calculate_exposure_time(instrum, binn, filt, snr, mag, seeing, spinstrum=None, spslit=None, sparm=None, spsnr=None, spmag=None, spseeing=None):
    # Define instrument characteristics for imaging
    instrum_data = {
        "ioo": {"pixscale": 0.15, "darkcurrent": 0, "readnoise": 10},
        "ioi": {"pixscale": 0.18, "darkcurrent": 0, "readnoise": 17},
        "rise": {"pixscale": 0.54, "darkcurrent": 0, "readnoise": 10},
        "ringo": {"pixscale": 0.48, "darkcurrent": 0, "readnoise": 17}
    }

    # Define filter characteristics
    filter_data = {
        "fsu": {"zp": 22.17, "skybr": 21.0, "skyoff": 1.5},
        "fbb": {"zp": 24.90, "skybr": 22.3, "skyoff": 1.5},
        "fbv": {"zp": 24.96, "skybr": 21.4, "skyoff": 1.5},
        "fsg": {"zp": 25.14, "skybr": 21.7, "skyoff": 1.0},
        "fsr": {"zp": 25.39, "skybr": 20.4, "skyoff": 1.0},
        "fsi": {"zp": 25.06, "skybr": 19.3, "skyoff": 1.0},
        "fsz": {"zp": 24.52, "skybr": 18.3, "skyoff": 0.5},
        "fjj": {"zp": 24.50, "skybr": 16.6, "skyoff": 0.0},
        "fhh": {"zp": 24.00, "skybr": 12.5, "skyoff": 0.0},
        "frise": {"zp": 25.20, "skybr": 20.4, "skyoff": 1.0},
        "frise720": {"zp": 23.40, "skybr": 19.3, "skyoff": 1.0},
        "fringr": {"zp": 21, "skybr": 19.3, "skyoff": 1.0},
        "fringg": {"zp": 21.8, "skybr": 20.4, "skyoff": 1.0},
        "fringb": {"zp": 23, "skybr": 22.3, "skyoff": 1.5}
    }

    # Define binning values
    bin_values = {"two": 2, "one": 1}

    # Imaging calculation
    if instrum in instrum_data and binn in bin_values and filt in filter_data:
        pixscale = instrum_data[instrum]["pixscale"]
        darkcurrent = instrum_data[instrum]["darkcurrent"]
        readnoise = instrum_data[instrum]["readnoise"]
        bin_factor = bin_values[binn]
        zp = filter_data[filt]["zp"]
        skybr = filter_data[filt]["skybr"]
        skyoff = filter_data[filt]["skyoff"]

        # Calculate exposure time for photometry
        exposure_time = 0.1
        j=1.0
        skymag = skybr - skyoff*j
        ###
        areaofdisk = (seeing * 2) ** 2
        numberofpixels = areaofdisk / (pixscale * pixscale * bin_factor * bin_factor)
        starphotons = 10 ** ((zp - mag) / 2.5)
        skyphotons = 10 ** ((zp - skymag) / 2.5) * areaofdisk
        a = starphotons ** 2
        b = -snr ** 2 * (starphotons + skyphotons + darkcurrent)
        c = -snr ** 2 * numberofpixels * readnoise ** 2
        texpaa = (-b + math.sqrt(b * b - 4 * a * c)) / (2 * a)
        texpbb = (-b - math.sqrt(b * b - 4 * a * c)) / (2 * a)
        exposure_time = max(texpaa, texpbb)

        # Check for exposure time limits
        if exposure_time < 1.0:
            exposure_time = 1
        if exposure_time > 10800 or (starphotons * exposure_time / numberofpixels) > 10000:
            exposure_time = -1

        return exposure_time

    # Spectroscopy calculation
    elif spinstrum and spslit and sparm and spmag and spsnr:
        spectrometer_data = {
            "frodo": {"sppixscale": 0.82, "spdarkcurrent": 0, "spreadnoise": 10},
            "sprat": {"sppixscale": 0.48, "spdarkcurrent": 0, "spreadnoise": 9}
        }

        slit_data = {
            "spratslit": 2,
            "ifu": 10
        }

        arm_data = {
            "frredarmv": {"spzp": 16.0, "spskybr": 20.8, "spskyoff": 1.0, "spres": 5300, "wvpixscale": 0.8, "refwav": 7000},
            "frbluarmv": {"spzp": 14.5, "spskybr": 22.8, "spskyoff": 1.5, "spres": 5500, "wvpixscale": 0.35, "refwav": 4500},
            "frredarm": {"spzp": 15.60, "spskybr": 20.8, "spskyoff": 1.0, "spres": 2200, "wvpixscale": 1.9, "refwav": 7000},
            "frbluarm": {"spzp": 14.70, "spskybr": 22.8, "spskyoff": 1.5, "spres": 2600, "wvpixscale": 0.60, "refwav": 4500},
            "spredarm": {"spzp": 17.7, "spskybr": 20.8, "spskyoff": 1.0, "spres": 350, "wvpixscale": 9.0, "refwav": 7000},
            "spbluarm": {"spzp": 17.2, "spskybr": 22.8, "spskyoff": 1.5, "spres": 350, "wvpixscale": 3.0, "refwav": 4500}
        }

        sppixscale = spectrometer_data[spinstrum]["sppixscale"]
        spdarkcurrent = spectrometer_data[spinstrum]["spdarkcurrent"]
        spreadnoise = spectrometer_data[spinstrum]["spreadnoise"]
        slitwd = slit_data[spslit]
        spzp = arm_data[sparm]["spzp"]
        spskybr = arm_data[sparm]["spskybr"]
        spskyoff = arm_data[sparm]["spskyoff"]
        spres = arm_data[sparm]["spres"]
        wvpixscale = arm_data[sparm]["wvpixscale"]
        refwav = arm_data[sparm]["refwav"]

        # Calculate exposure times for spectroscopy
        exposure_time = 0.1
        sj = 1.0
        spskymag = spskybr - (spskyoff * sj)
        spatialarcs = (slitwd * spseeing * 2)
        spatialarea = spatialarcs / (sppixscale * sppixscale)
        specpixsc = refwav / (spres * wvpixscale)
        spnumberofpixels = spatialarea * specpixsc
        spstarphotons = 10 ** ((spzp - spmag) / 2.5) * (refwav / spres)
        spskyphotons = 10 ** ((spzp - spskymag) / 2.5) * (refwav / spres) * spatialarcs
        spa = spstarphotons ** 2
        spb = -spsnr ** 2 * (spstarphotons + spskyphotons + spdarkcurrent)
        spc = -spsnr ** 2 * spnumberofpixels * spreadnoise ** 2
        sptexpaa = (-spb + math.sqrt(spb * spb - 4 * spa * spc)) / (2 * spa)
        sptexpbb = (-spb - math.sqrt(spb * spb - 4 * spa * spc)) / (2 * spa)
        exposure_time = max(sptexpaa, sptexpbb)

        # Check for exposure time limits
        if exposure_time < 1.0:
            exposure_time = 1
        if exposure_time > 10800 or (spstarphotons * exposure_time / spnumberofpixels) > 10000:
            exposure_time = -1

        return exposure_time

# Example usage:
# For imaging
imaging_times = calculate_exposure_time("ioo", "two", "fsu", 50, 15, 1.0)

# For spectroscopy
spectroscopy_times = calculate_exposure_time(None, None, None, None, None, None, "sprat", "spratslit", "spbluarm", 50, 13.5,1.0)

print(f"Imaging Exposure Times: {imaging_times:.2f} s")
print(f"Spectroscopy Exposure Times: {spectroscopy_times:.2f} s")

@rachel3834
Copy link

Chris Copperwheat responded from the LT to explain that while they'd like to implement an API, this is out of scope for the foreseeable future. So it looks like embedding the ETC code is the way forward in the short term. Thanks for the refactored code @wyrzykow. I'm increasing the priority of this issue and putting it back in triage for the TOM Team to discuss when we plan the next sprint.

@wyrzykow
Copy link
Author

Thanks for increasing the priority, @rachel3834 !

I have tested this code in my simple bhtom3, https://github.com/BHTOM-Team/bhtom3
I have added the LT facility directly to the code. However, I failed to automatically set the values for exposure times in the input fields, instead, I only displayed suggested exp. times. And so far it only works for SPRAT.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request User Issue Raised by a user
Projects
Status: Backlog
Development

No branches or pull requests

3 participants