Пример #1
0
    def __init__(self,
                 input,
                 telescopeName,
                 psfModel=1.0,
                 inputType='fitscube',
                 fluxType='intensity',
                 saveConvCube=True,
                 yamlfile='lvmdatasim.yaml'):
        """ 
        Initialize for Simulator
        """
        self.input = input
        self.inputType = inputType
        self.fluxType = fluxType
        self.telescopeName = telescopeName
        self.psfModel = psfModel
        self.saveConvCube = saveConvCube
        self.yamlfile = yamlfile

        self.data, self.hdr = self.readInput()

        self.telescope = Telescope(telescopeName)
        """ still need to define how user sets parameters of exposure and simulation"
        """

        import lvmdatasimdefaults
        self.simparam = lvmdatasimdefaults.param
        self.convdata = None
Пример #2
0
def teleinput():
    '''Page to input custom telescope and observability parameters'''

    form = CustomTelescopeForm()
    location_properties = ['longitude', 'latitude', 'elevation', 'min_altitude', 'max_altitude', 'start_date', 'end_date', 'resolution']#, 'fast_return']
    if form.validate_on_submit():
        # create new telescope instance
        custom_telescope = Telescope()
        flash = [] # array to keep messages to flash the user to confirm their choices
        for prop in Telescope.property_dict.keys():
            if prop != 'name':
                val = getattr(form, prop).data
                setattr(custom_telescope, prop, val)
                # flash a message to the user confirming their choices
                if val is not None: flash.append('{} = {}'.format(prop, val))

        # error checking already done by form.py
        custom_telescope._C_T_calculable = True 

        # make a copy of the exoplanet array so as to not alter the master copy
        custom_exoplanet_array = copy.deepcopy(exoplanet_array)
        
        # calculate new metrics
        for planet in custom_exoplanet_array:
            planet.decision_metric_(custom_telescope)
        # sort and truncate custom_exoplanet_array
        functions.sort_and_truncate_by_property(custom_exoplanet_array, 'decision_metric')
        
        # copy print properties, since location may append it
        observable_properties = copy.deepcopy(print_properties)

        # if telescope location is given, see which planets are visible
        for property in location_properties:
            value = getattr(form, property).data
            if value is not None and property != 'start_date' and property != 'end_date':
                flash.append('{} = {}'.format(property, value))

        longitude    = form.longitude.data
        latitude     = form.latitude.data
        elevation    = form.elevation.data
        start_date   = form.start_date.data
        end_date     = form.end_date.data
        min_altitude = form.min_altitude.data
        max_altitude = form.max_altitude.data
        resolution   = form.resolution.data
        if longitude is not None and latitude is not None:

            # create json for exoplanet array, celery demands
            json_exoplanet_array = functions.planet_array_to_json_array(custom_exoplanet_array, 'host.')

            # start task
            task = observability.apply_async(args=(json_exoplanet_array, longitude, latitude, elevation, start_date, end_date, min_altitude, max_altitude, resolution))
            
            # render template, ajax calls to celery task will fill in the page
            return render_template('observability.html', home=False, custom=True, print_properties=print_properties, flash=flash, exoplanet_array=custom_exoplanet_array, task_id=task.id,
                _ra_dec_img_url=functions.ra_dec_img_url, _deg_to_ra_hms=functions.deg_to_ra_hms, _deg_to_dec_dms=functions.deg_to_dec_dms, _round_sig_figs=functions.round_sig_figs)

        # choose a random planet
        if len(custom_exoplanet_array) > 0:
            randomPlanet = functions.random_planet_selector(custom_exoplanet_array)
        else: randomPlanet = False

        # graph of decision metric vs rank
        tooltip_dict = {
            'name'            : [],
            'mass'            : [],
            'radius'          : [],
            'orbital_period'  : [],
            'semi_major_axis' : [],
            'temp_calculated' : [],
            'detection_type'  : [],
            'decision_metric' : [],
            'filter'          : [],
            't_exp'           : [],
        }
        graph = functions.metric_rank_bar_graph(custom_exoplanet_array, tooltip_dict)
        
        # render new table
        return render_template('table.html', graph=graph, home=False, custom=True, flash=flash, print_properties=print_properties, exoplanet_array=custom_exoplanet_array, randomPlanet=randomPlanet,
            _ra_dec_img_url=functions.ra_dec_img_url, _deg_to_ra_hms=functions.deg_to_ra_hms, _deg_to_dec_dms=functions.deg_to_dec_dms, _round_sig_figs=functions.round_sig_figs)
    
    # render the input form for telescope data
    return render_template('teleinput.html', property_list=Telescope.property_dict.keys(), location_properties=location_properties, form=form)
Пример #3
0
class LVMSimulator(object):
    """
    Manages the simulation of LVM data

    Parameters:
    -----------
        
    input: str
        path to input data file

    telescopeName: str
        Telescope name. Syntax is LVM[160,1000]-[SCI,CAL,SKY]-[N,S]. So for example, the spectrophotometric
        calibration 0.16m telescope at LCO (i.e. South) would be "LVM160-CAL-S"

    psfModel: float or int or list or str or None
        If float or int generates a symmetric 2D Gaussian kernel of FWHM=psfModel
        If list=[FWHM_a,FWHM_b,theta] and len(list)==3 generates elliptical and rotated Gaussian kernel 
        If str reads a fits file image as the kernel
        If None or False no psf convolution is performed

    inputType: str
        Can be one of the following:
        'fitscube' = native input datacube in fits format
        'lenscube' = lenslet convolved datacube in fits format
        'psfcube' = psf+lenslet convolved datacube in fits format
        'fitsrss' = RSS file with one spectrum per lenslet, first row is wavelength in A
        'asciirss' = ascii file with one spectrum per lenslet, first column is wavelength in A, headers must be commented with "#"

    fluxType: str
        Can be one of the following:
        'intensity' = input is assumed to be in units of erg/s/cm2/arcsec2 (for both cubes and RSS files)
        'flux' = input is assumed to be in units of erg/s/cm2/pixel (for cubes) or erg/s/cm2 (for RSS files)

    """
    def __init__(self,
                 input,
                 telescopeName,
                 psfModel=1.0,
                 inputType='fitscube',
                 fluxType='intensity',
                 saveConvCube=True,
                 yamlfile='lvmdatasim.yaml'):
        """ 
        Initialize for Simulator
        """
        self.input = input
        self.inputType = inputType
        self.fluxType = fluxType
        self.telescopeName = telescopeName
        self.psfModel = psfModel
        self.saveConvCube = saveConvCube
        self.yamlfile = yamlfile

        self.data, self.hdr = self.readInput()

        self.telescope = Telescope(telescopeName)
        """ still need to define how user sets parameters of exposure and simulation"
        """

        import lvmdatasimdefaults
        self.simparam = lvmdatasimdefaults.param
        self.convdata = None

    """
    Lensed cube should store PA in header, and if imputType=lenscube or psfcube code should check that PA in header is consistent with PA of observation, otherwise raise error.
    """

    def readInput(self):
        if self.inputType in ['fitscube', 'lenscube', 'psfcube']:
            """
            - Read self.input as fits cube and return data and header
            - Add a PIXSCALE keyword to the header if not present before passing it on
            """
            data = fits.open(self.input)
            if ('PIXSCALE' not in data[0].header.keys()) and (
                    'CDELT1' not in data[0].header.keys()) and (
                        'CD1_1' not in data[0].header.keys()):
                sys.exit('No WCS Information in input FITS header')
            elif 'PIXSCALE' not in data[0].header.keys():
                mywcs = wcs.WCS(data[0].header)
                pixscale = wcs.utils.proj_plane_pixel_scales(
                    mywcs).mean() * 3600.
                data[0].header.set(
                    'PIXSCALE', pixscale,
                    'Pixel scale calculated from WCS by LVMSimulator')
            if data[0].data.ndim == 3:
                return (data[0].data, data[0].header)
            elif data[0].data.ndim == 2:
                ny, nx = np.shape(data[0].data)
                return (data[0].data.reshape(1, ny, nx), data[0].header)

        elif self.inputType == 'fitsrss':
            """ 
            - Read self.input as fits RSS file with spectra for each spaxel and return data
            """
            data = fits.open(self.input)
            return (data.data, data.header)
        elif self.inputType == 'asciirss':
            """ 
            - Read self.input as ascii file with one spectrum per each spaxel (1st column = wavelength, each following column is one spectrum), and return data
            """
            data = np.genfromtxt(self.input, comments="#", unpack=True)
            return (data, '')
        else:
            sys.exit('Input Type \"' + self.inputType + '\" not recognized.')

    def makePsfKernel(self):
        try:
            pixscalecube = self.hdr['PIXSCALE']
        except:
            sys.exit(
                "Something went wrong. You made it this far with no 'PIXSCALE' defined in the data header."
            )

        if isinstance(self.psfModel, (float or int)):
            """
            Make Symmetric Gaussian 2D PSF
            - Need to calculate the scaling between the plate scale and the PSF model
            """
            return (Gaussian2DKernel(self.psfModel / 2.355 / pixscalecube,
                                     mode='oversample',
                                     factor=25))

        elif isinstance(self.psfModel, list):
            """
            Make rotated Gaussian 2D elliptical PSF
            
            """
            if len(self.psfModel) == 3:
                #Extract PSF model parameters from the list
                (a_stddev, b_stddev) = self.psfModel[0:2] / 2.355
                (a_stddev, b_stddev) = (a_stddev / pixscalecube,
                                        b_stddev / pixscalecube)
                theta = self.psfModel[2]

                return (Gaussian2DKernel(x_stddev=a_stddev,
                                         y_stddev=b_stddev,
                                         theta=theta,
                                         mode='oversample',
                                         factor=25))
            else:
                sys.exit(
                    "The provided PSF model is a list, but not of length three. It can not be interpreted as a_FWHM, b_FWHM, theta"
                )

        elif isinstance(self.psfModel, str):
            """
            Read 2D PSF from fits file
            - Right now rebining fits kernel with interpolation, it would be better to do an actual integration over a surface fit
            """
            if self.psfModel.endswith() != ".fits":
                sys.exit(
                    "psfModel is str but does not end in \".fits\" as expected"
                )
            else:
                psf = fits.open(self.psfModel)
                pixscalepsf = psf.header['PIXSCALE']
                wcs0 = wcs.WCS(naxis=2)
                wcs0.wcs.crpix = [0, 0]
                wcs0.wcs.crval = [0, 0]
                wcs0.wcs.cdelt = np.full(2, pixscalepsf)
                wcs1 = wcs.WCS(naxis=2)
                wcs1.wcs.crpix = [0, 0]
                wcs1.wcs.crval = [0, 0]
                wcs1.wcs.cdelt = np.full(2, pixscalecube)

                psf[0].header = wcs0.to_header()
                psfrebin = reproject_interp(psf, wcs1)

            return (psfrebin[0].data)

        elif self.psfModel is False:
            return self.psfModel

    def updateyaml(self):
        with open("lvmdatasimTemplate.yaml", 'r') as f:
            data = f.read()  # produces single string
        for key in self.simparam.keys():
            data = data.replace("%s__placeholder" % key,
                                str(self.simparam[key]))
        with open(self.yamlfile, 'w') as f:
            f.writelines(data)

    def makeCircularLensKernel(self):
        """
        Generate a 2D numpy array with the characteristic function of a circle of size 'radius' (center to corner)
        in units of pixels of the array. The image will have dimensions of imgsize x imgsize and the circle will
        be at the integer center.
        """
        rlensmm = np.mean(self.telescope.ifu.lensr)
        rlensarcsec = rlensmm * self.telescope.platescale()
        rlenspix = rlensarcsec / self.hdr['PIXSCALE']
        imgsize = 2 * rlenspix
        antialias = 5
        imgsize = int(imgsize * antialias)
        img = Image.new('L', (imgsize, imgsize), 0)
        ImageDraw.Draw(img).ellipse((0, 0, imgsize, imgsize),
                                    outline=1,
                                    fill=1)
        kernel = np.array(img, dtype=float)
        kernel /= np.sum(kernel)
        kernel = int_rebin(kernel,
                           (imgsize // antialias, imgsize // antialias))
        return kernel

    def makeHexLensKernel(self):
        """
        Generate a 2D numpy array with the characteristic function of a hexagon of size 'radius' (center to corner)
        in units of pixels of the array. The image will have dimensions of imgsize x imgsize and the hexagon will
        be at the integer center.
        """
        rlensmm = np.mean(self.telescope.ifu.lensr)
        rlensarcsec = rlensmm * self.telescope.platescale()
        rlenspix = rlensarcsec / self.hdr['PIXSCALE']
        imgsize = 2 * rlenspix
        antialias = 5
        imgsize = int(imgsize * antialias)
        center = imgsize // 2 + 1
        hexLayout = hexlib.Layout(hexlib.layout_pointy, rlenspix * antialias,
                                  hexlib.Point(center, center))
        polygon = hexlib.polygon_corners(hexLayout, hexlib.Hex(0, 0, 0))
        img = Image.new('L', (imgsize, imgsize), 0)
        ImageDraw.Draw(img).polygon(polygon, outline=1, fill=1)
        kernel = np.array(img, dtype=float)
        kernel /= np.sum(kernel)
        kernel = int_rebin(kernel,
                           (imgsize // antialias, imgsize // antialias))
        return kernel

    def convolveInput(self):
        """ results of call:
        0,0 - no convolution
        1,0 - psf convolution, no lens convolution
        0,1 - no psf convolution. lens convolution
        1,1 - psf and lens convolution
        """
        if self.inputType == "psfcube":
            # if is a psfcube dont do anything (0,0)
            self.convdata = self.data
        else:
            # if not psfcube it needs some sort of convolution
            if self.psfModel is not (False or None):
                # if psfModel defined then make psf kernel
                self.psfKernel = self.makePsfKernel()
                if self.inputType == ('fitscube'):
                    # if its fitscube kernel is convolution of psf+lenslet (1,1)
                    self.telescope.ifu.lensKernel = self.makeCircularLensKernel(
                    )
                    self.kernel = convolve_fft(self.telescope.ifu.lensKernel,
                                               self.psfKernel)
                elif self.inputType == ('lenscube'):
                    # if its lenscube kernel is only the psf (1,0)
                    self.kernel = self.psfKernel
            else:
                # if psfModel is not defined then kernel is lenslet only (0,1)
                self.telescope.ifu.lensKernel = self.makeCircularLensKernel()
                self.kernel = self.telescope.ifu.lensKernel
            self.convdata = np.zeros(np.shape(self.data))
            for i in range(np.shape(self.data)[0]):
                self.convdata[i, :, :] = convolve_fft(self.data[i, :, :],
                                                      self.kernel,
                                                      normalize_kernel=True)

    def getDataFluxes(self):
        """
        - Extract the spectral fluxes from data. 
        - If working on cube sample convolved cube at lenslet positions and scale fluxes by lenslet area with respect to average lenslet area
        - This version does not correct for DAR!!!!!
        - If working on an RSS file simply pass on the fluxes for each spaxel
        - Return a 2D np array of dimensions (Nspax, Nwave) in the format needed by specsim (do in one step, check scipy.interpolate.interp1d)
        -

        Main Dependent Parameters
        ----------
        'self.data' = data, sampled data or convolved data
        'self.telescope.ifu.lensx' = image pixel coordinate x  where the FOV will be centered and fluxes will be extracted. Default to center
        'self.telescope.ifu.lensy' = image pixel coordinate y  where the FOV will be centered and fluxes will be extracted. Default to center
        'self.telescope.ifu.lensr' = hexagon radius: This does not result in a convolution of the image with each indivdual PSF of each lens. That's too expensive. What is done is to scale the fluxes of an indivudal fiber by the area of the average lens size.
        potentially self.skycor and telescope model, otherwise use pixel
        """

        waveout = self.simulator.simulated[
            'wavelength'].data  # get this wavelength from the simspec config member
        nlens = len(self.telescope.ifu.lensID)
        lensrsky = np.array(
            self.telescope.ifu.lensr) * self.telescope.platescale(
                self.telescope.ifu.lensx, self.telescope.ifu.lensy)
        lensareasky = 3 * np.sqrt(
            3) * lensrsky**2 / 2  # lenslet area in arcsec2
        lensrpix = lensrsky / self.hdr['PIXSCALE']
        lensareapix = 3 * np.sqrt(
            3) * lensrpix**2 / 2  # lenslet area in number of pixels

        if self.inputType in ['fitsrss', 'asciirss']:
            wavein = self.convdata[0, :]
            fluxesin = self.convdata[1:, :]
            interp = interpolate.RectBivariateSpline(np.range(nlens), wavein,
                                                     fluxesin)
            fluxesout = interp(np.range(nlens), waveout)

            if self.fluxType == 'intensity':
                """Multiply input spaxel area in arcsec2
                """
                fluxesout *= np.repeat(lensareasky[:, np.newaxis],
                                       np.shape(fluxesout)[1],
                                       axis=1)

        elif self.inputType in ['fitscube', 'lenscube', 'psfcube']:
            # compute lenslet coordinates, do mask, evaluate spectra
            # resample data to output wavelength sampling
            self.lensra, self.lensdec = self.telescope.ifu2sky(
                self.simparam['ra'], self.simparam['dec'],
                self.simparam['theta'])
            mywcs = wcs.WCS(self.hdr)
            lenscubex, lenscubey = np.array(
                mywcs.wcs_world2pix(self.lensra, self.lensdec, 1)).astype(int)

            # The above is a placeholder

            # We will improve this with a cube of references
            fluxesin = np.zeros((nlens, np.shape(self.data)[0]))
            for i in range(nlens):
                fluxesin[i, :] = self.convdata[:, lenscubey[i], lenscubex[i]]

            if np.shape(self.data)[0] > 1:
                wavein = None
                "need to read this from header"
                interp = interpolate.RectBivariateSpline(
                    np.range(nlens), wavein, fluxesin)
                fluxesout = interp(np.range(nlens), waveout)
            elif np.shape(self.data)[0] == 1:
                fluxesout = np.repeat(fluxesin, len(waveout), axis=1)
                # Maybe we want the image to pupulate an emission line instead of a continuum source
            if self.fluxType == 'intensity':
                """Multiply input spaxel area in arcsec2
                """
                fluxesout *= np.repeat(lensareasky[:, np.newaxis],
                                       np.shape(fluxesout)[1],
                                       axis=1)

            elif self.fluxType == 'flux':
                """Multiply input by  spaxel area in pixels
                """
                fluxesout *= np.repeat(lensareapix[:, np.newaxis],
                                       np.shape(fluxesout)[1],
                                       axis=1)

        return fluxesout

    def simulate(self, forceConv=False):
        """
        Measure fluxes for each spaxel, create the simspec Simulator object, update it with user defined parameters, and run simulation
        """

        if (self.convdata is None) or forceConv:
            # If convdata does not exist or the user wants to reconvolve the input (i.e. forceConv=True) then convolve the input
            self.convolveInput()
        self.updateyaml()
        self.simulator = specsim.simulator.Simulator(
            self.yamlfile, num_fibers=len(self.telescope.ifu.lensID))
        self.fluxes = self.getDataFluxes(
        )  #intentionally broken, x and y are not defined
        # TO DO: add right keywords to simultate so we pass on fluxes array
        self.simulator.simulate(source_fluxes=self.fluxes * 1e-17 * u.erg /
                                (u.s * u.cm**2 * u.Angstrom))
Пример #4
0
import subprocess
init_pigpio = ["sudo", "pigpiod", "-t0"]
subprocess.Popen(init_pigpio,
                 stdout=subprocess.PIPE,
                 stderr=subprocess.DEVNULL)

print("Initializing...")
from Telescope import Telescope
from basicTrack import basicTrack as angleFunc
from Pointing_Angle import getRA
from astropy.coordinates.name_resolve import NameResolveError

# Server IP and port placeholders
telescope = Telescope(1, 1)

name = input('Input name of celestial body to be tracked: ')
while True:
    try:
        getRA(name)
        print("Located!")
        break
    except NameResolveError:
        print("Input name could not be resolved")
        name = input("Please try again: ")

trackParams = {
    'bodyName': name,
    'LAT': Telescope.getLAT,
    'LON': Telescope.getLON,
    'currentTimeDt': Telescope.getCurrentTime,
    'currentAngle': Telescope.getAngles
Пример #5
0
from StarChart import StarChart
from Telescope import Telescope

if __name__ == "__main__":
    chart = StarChart()
    scope = Telescope(0.5, 0.5, 250, 250, (0, 0, 0), (1, 0, 0))
    data = [(100, 0, 0), (100, -10, -10), (100, 10, 10)]
    chart.load_data(data)
    scope.calculate_view(chart.find_nearby_stars((0, 0, 0), (0, 0, 0)))
    scope.update_view()
Пример #6
0
import numpy as np
from Telescope import Telescope
import Pointing_Angle as pointer
from Pointing_Angle import getRA
from astropy.coordinates.name_resolve import NameResolveError

print(
    "This script will attempt to calibrate the positioning of the telescope.")
print(
    "You select a star to point at, and the telescope will try to point at that star."
)
print(
    "Then you provide a list of fine adjustments until the star is centered in the telescope's field of view"
)

t = Telescope(1, 2)

name = input('Input name of celestial body to calibrate against: ')
while True:
    try:
        getRA(name)
        print("Located!")
        angle = pointer.calcAngle(name, t.LAT, t.LON,
                                  Telescope.getCurrentTime(),
                                  Telescope.getAltAngle(),
                                  Telescope.getAzAngle())
        check = t.checkConstraints(angle)
        if check:
            print("Star is within viewing constraints!")
            break
        else:
Пример #7
0
def read_planet_telescope_data_csv(planet_src,
                                   tele_src,
                                   path_to_static,
                                   onlyConfirmed,
                                   to_remove=[]):
    '''
    Function to read in the planet and telescope data, determine if calculable, truncate and return arrays for both, and check if images are present in the static folder

    Parameters
    ----------
    planet_src : str
        A url for the csv containing planet data
    tele_src : str
        A full file path to the csv containing telescope data
    path_to_static : str
        A file path to the static folder, for checking and saving images, saving pickle files as a backup and saving pickle files to check observability

    Returns
    -------
    exoplanet_array : list of Exoplanet
    tele_array      : list of Telescope
    plottingsource  : dict
        A dictionary with Exoplanet properties as keys and a list as values, ready to be converted into a Bokeh plotting source
    '''

    try:
        ################
        # exoplanet read in

        start = time.perf_counter()
        print('Updated data ' + str(datetime.datetime.now()))

        # access database and read the data from the csv file
        if not onlyConfirmed:
            try:
                # submit form data to get unconfirmed planets too
                values = {
                    'Confirmed': 'on',
                    'Candidate': 'on',
                    'Other': 'on',
                    'query_f': '',
                    'search': ''
                }
                data = urllib.parse.urlencode(values).encode('utf-8')
                url = planet_src + '?status_1=on&status_2=on&status_4=on&query_f=&search=/'
                req = urllib.request.Request(url, data=data)
                planet_csv = urllib.request.urlopen(req)
            except:
                # didn't work, just get confirmed ones by default
                planet_csv = urllib.request.urlopen(planet_src)
                onlyConfirmed = True
        else:
            planet_csv = urllib.request.urlopen(planet_src)

        # convert the web file to string and split into rows (each row still a csv)
        planet_csv = str(planet_csv.read())
        planet_rows = planet_csv.split('\\r\\n')

        # remove the first row containing the table headers and the last blank row and create an empty array of exoplanet objects
        planet_rows.pop(0)
        planet_rows.pop()
        exoplanet_array = []
        host_star_array = []

        # split each row by comma and fill the empty exoplanet array with all assigned properties
        # specific to the exoplanets.eu database, Exoplanet.property_dict has the same headers in the same order
        for row in planet_rows:
            # split by comma (except when inside quotes)
            columns = re.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", row)

            planet_col = columns[:68]
            host_col = columns[68:]
            prop_units = list(Exoplanet.property_dict.items()) + [
                ('host.' + prop, val)
                for prop, val in Star.property_dict.items()
            ]

            # planet object (and host object contained inside)
            planet = Exoplanet()

            # add info
            for val, (prop, unit) in zip(columns, prop_units):
                try:
                    # attempt to float
                    if not np.isnan(float(val)) and not np.isinf(float(val)):
                        rsetattr(planet, prop, float(val))

                        # years will should be datetime timestamps, for plotting sake
                        if unit == 'year':
                            rsetattr(
                                planet, prop,
                                datetime.datetime.strptime(
                                    val, '%Y').timestamp() * 1000)

                    else:
                        # could float but the value is nan or inf, set a blank instead
                        rsetattr(planet, prop, '')

                # could not float
                except ValueError:
                    # dates should be datetime timestamps, for plotting sake
                    if unit == 'date':
                        rsetattr(
                            planet, prop,
                            datetime.datetime.strptime(
                                val, '%Y-%m-%d').timestamp() * 1000)

                        # yes/no strings converted to bool
                    elif val == 'yes':
                        rsetattr(planet, prop, True)
                    elif val == 'no':
                        rsetattr(planet, prop, False)

                        # save as string instead
                    else:
                        rsetattr(planet, prop, val.replace('"', ''))

            # append to lists
            exoplanet_array.append(planet)
            host_star_array.append(planet.host)

        # manually remove erroneous members of the list
        for planet in exoplanet_array:
            if planet.name in to_remove:
                exoplanet_array.remove(planet)
                host_star_array.remove(planet.host)

        ####################
        # telescope read in

        # read in telescope data
        tele_csv = open(tele_src, 'r')
        tele_csv = tele_csv.read()
        tele_csv = tele_csv.replace('NaN',
                                    '')  # replace NaN in csv with blank space
        tele_rows = tele_csv.split('\n')

        # remove the first row containing the table headers and last blank row and create an empty array of telescope objects
        tele_rows.pop(0)
        tele_rows.pop()
        tele_array = []

        # split each row by comma and fill the empty telescope array with all assigned properties
        for row in tele_rows:
            # split by comma
            columns = re.split(',', row)

            # telescope object
            telescope = Telescope()

            # append each new telescope and fill with values according to the dictionary
            for prop, index in Telescope.property_dict.items():
                val = columns[index]
                try:
                    # spectral bins and half well are ints
                    if prop == 'spectral_bins' or prop == 'Half_Well':
                        setattr(telescope, prop, int(val))

                    # otherwise attempt to float
                    else:
                        setattr(telescope, prop, float(val))

                # could not float, save as string instead
                except ValueError:
                    setattr(telescope, prop, val)

            # append telescope
            tele_array.append(telescope)

        ###################
        # other jobs to do

        # determine if calculable
        for planet in exoplanet_array:
            planet._metric_calculable_()
        for telescope in tele_array:
            telescope._C_T_calculable_()

        # check images of each planet exist in the static folder, if not download it from the internet
        new_names = []
        for planet in exoplanet_array:
            if not os.path.isfile(
                    path_to_static +
                    planet.name.replace(' ', '_').replace('/', '_') + '.gif'):
                url_pic = ra_dec_img_url(planet.host.ra, planet.host.dec)
                filename = path_to_static + planet.name.replace(
                    ' ', '_').replace('/', '_') + '.gif'
                urllib.request.urlretrieve(url_pic, filename)
                new_names.append(planet.name)

        # make bokeh plotting source
        source_dict = plotting_source_dict(exoplanet_array)

        ###################
        # save progress

        # save in pickle just in case
        with open(path_to_static + 'exoplanet_array.pkl', 'wb') as f:
            pickle.dump(exoplanet_array, f)
        with open(path_to_static + 'tele_array.pkl', 'wb') as f:
            pickle.dump(tele_array, f)
        with open(path_to_static + 'source_dict.pkl', 'wb') as f:
            pickle.dump(source_dict, f)

        end = time.perf_counter()
        print('Data read-in took ' + str(round(end - start, 3)) +
              ' seconds for %i planets (reduced to %i) and %i telescopes' %
              (len(planet_rows), len(exoplanet_array), len(tele_array)))
        if new_names:
            print('New planets since last update:')
            for name in new_names:
                print(name)

    except:
        # maybe a timeout error occured, just reload from stored pickle arrays instead
        with open(path_to_static + 'exoplanet_array.pkl', 'rb') as f:
            exoplanet_array = pickle.load(f)
        with open(path_to_static + 'tele_array.pkl', 'rb') as f:
            tele_array = pickle.load(f)
        with open(path_to_static + 'source_dict.pkl', 'rb') as f:
            source_dict = pickle.load(f)

        print('Could not load new data, loading data from last update instead')
        print('%i planets and %i telescopes' %
              (len(exoplanet_array), len(tele_array)))

    return (exoplanet_array, tele_array, source_dict)
Пример #8
0
from Telescope import Telescope
try:
    myTel = Telescope("LVM160-SCI-S")
    print("Telescope Import Successful")
except:
    print("Telescope Import Failed")