Exemple #1
0
    def interpret_header(self):
        """
        Read pertinent information from the image headers,
         especially location and radius of the Sun to calculate the default thematic map
        :return: setes self.date, self.cy, self.cx, and self.sun_radius_pixel
        """
        # handle special cases since date-obs field changed names
        if 'DATE_OBS' in self.header:
            self.date = self.header['DATE_OBS']
        elif 'DATE-OBS' in self.header:
            self.date = self.header['DATE-OBS']
        else:
            raise Exception("Image does not have a DATE_OBS or DATE-OBS field")

        self.cy, self.cx = self.header['CRPIX1'], self.header['CRPIX2']
        sun_radius_angular = sun.solar_semidiameter_angular_size(t=time.parse_time(self.date)).arcsec
        arcsec_per_pixel = self.header['CDELT1']
        self.sun_radius_pixel = (sun_radius_angular / arcsec_per_pixel)
Exemple #2
0
def plt_qlook_image(imres, figdir=None, verbose=True, synoptic=False):
    from matplotlib import pyplot as plt
    from sunpy import map as smap
    from sunpy import sun
    from matplotlib import colors
    import astropy.units as u
    from suncasa.utils import plot_mapX as pmX
    # from matplotlib import gridspec as gridspec

    if not figdir:
        figdir = './'

    nspw = len(set(imres['Spw']))
    plttimes = list(set(imres['BeginTime']))
    ntime = len(plttimes)
    # sort the imres according to time
    images = np.array(imres['ImageName'])
    btimes = Time(imres['BeginTime'])
    etimes = Time(imres['EndTime'])
    spws = np.array(imres['Spw'])
    suc = np.array(imres['Succeeded'])
    inds = btimes.argsort()
    images_sort = images[inds].reshape(ntime, nspw)
    btimes_sort = btimes[inds].reshape(ntime, nspw)
    suc_sort = suc[inds].reshape(ntime, nspw)
    if verbose:
        print('{0:d} figures to plot'.format(ntime))
    plt.ioff()
    fig = plt.figure(figsize=(8, 8))

    plt.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=0, hspace=0)
    axs = []
    ims = []
    pltst = 0
    for i in range(ntime):
        plt.ioff()
        plttime = btimes_sort[i, 0]
        tofd = plttime.mjd - np.fix(plttime.mjd)
        suci = suc_sort[i]
        if not synoptic:
            if tofd < 16. / 24. or sum(
                    suci
            ) < nspw - 2:  # if time of the day is before 16 UT (and 24 UT), skip plotting (because the old antennas are not tracking)
                continue
            else:
                if pltst == 0:
                    i0 = i
                    pltst = 1
        else:
            if pltst == 0:
                i0 = i
                pltst = 1
        if i == i0:
            if synoptic:
                timetext = fig.text(0.01,
                                    0.98,
                                    plttime.iso[:10],
                                    color='w',
                                    fontweight='bold',
                                    fontsize=12,
                                    ha='left')
            else:
                timetext = fig.text(0.01,
                                    0.98,
                                    plttime.iso[:19],
                                    color='w',
                                    fontweight='bold',
                                    fontsize=12,
                                    ha='left')
        else:
            if synoptic:
                timetext.set_text(plttime.iso[:10])
            else:
                timetext.set_text(plttime.iso[:19])
        if verbose:
            print('Plotting image at: ', plttime.iso)
        for n in range(nspw):
            plt.ioff()
            if i == i0:
                if nspw == 1:
                    ax = fig.add_subplot(111)
                else:
                    ax = fig.add_subplot(nspw / 2, 2, n + 1)
                axs.append(ax)
            else:
                ax = axs[n]
            image = images_sort[i, n]
            if suci[n] or os.path.exists(image):
                try:
                    eomap = smap.Map(image)
                except:
                    continue
                data = eomap.data
                sz = data.shape
                if len(sz) == 4:
                    data = data.reshape((sz[2], sz[3]))
                data[np.isnan(data)] = 0.0
                # add a basin flux to the image to avoid negative values
                data = data + 0.8e5
                data[data < 0] = 0.0
                data = np.sqrt(data)
                eomap = smap.Map(data, eomap.meta)
                # resample the image for plotting
                dim = u.Quantity([256, 256], u.pixel)
                eomap = eomap.resample(dim)
            else:
                # make an empty map
                data = np.zeros((256, 256))
                header = {
                    "DATE-OBS": plttime.isot,
                    "EXPTIME": 0.,
                    "CDELT1": 10.,
                    "NAXIS1": 256,
                    "CRVAL1": 0.,
                    "CRPIX1": 128.5,
                    "CUNIT1": "arcsec",
                    "CTYPE1": "HPLN-TAN",
                    "CDELT2": 10.,
                    "NAXIS2": 256,
                    "CRVAL2": 0.,
                    "CRPIX2": 128.5,
                    "CUNIT2": "arcsec",
                    "CTYPE2": "HPLT-TAN",
                    "HGLT_OBS":
                    sun.heliographic_solar_center(plttime)[1].value,
                    "HGLN_OBS": 0.,
                    "RSUN_OBS":
                    sun.solar_semidiameter_angular_size(plttime).value,
                    "RSUN_REF": sun.constants.radius.value,
                    "DSUN_OBS":
                    sun.sunearth_distance(plttime).to(u.meter).value,
                }
                eomap = smap.Map(data, header)
            if i == i0:
                eomap_ = pmX.Sunmap(eomap)
                # im = eomap_.imshow(axes=ax, cmap='jet', norm=colors.LogNorm(vmin=0.1, vmax=1e8))
                im = eomap_.imshow(axes=ax,
                                   cmap='jet',
                                   norm=colors.Normalize(vmin=150, vmax=700))
                ims.append(im)
                if not synoptic:
                    eomap_.draw_limb(axes=ax)
                eomap_.draw_grid(axes=ax)
                ax.set_xlim([-1080, 1080])
                ax.set_ylim([-1080, 1080])
                try:
                    cfreq = eomap.meta['crval3'] / 1.0e9
                    bdwid = eomap.meta['cdelt3'] / 1.0e9
                    ax.text(0.98,
                            0.01,
                            '{0:.1f} - {1:.1f} GHz'.format(
                                cfreq - bdwid / 2.0, cfreq + bdwid / 2.0),
                            color='w',
                            transform=ax.transAxes,
                            fontweight='bold',
                            ha='right')
                except:
                    pass
                ax.set_title(' ')
                ax.set_xlabel('')
                ax.set_ylabel('')
                ax.set_xticklabels([''])
                ax.set_yticklabels([''])
            else:
                ims[n].set_data(eomap.data)

        fig_tdt = plttime.to_datetime()
        if synoptic:
            fig_subdir = fig_tdt.strftime("%Y/")
            figname = 'eovsa_qlimg_' + plttime.iso[:10].replace('-',
                                                                '') + '.png'
        else:
            fig_subdir = fig_tdt.strftime("%Y/%m/%d/")
            figname = 'eovsa_qlimg_' + plttime.isot.replace(':', '').replace(
                '-', '')[:15] + '.png'
        figdir_ = figdir + fig_subdir
        if not os.path.exists(figdir_):
            os.makedirs(figdir_)
        if verbose:
            print('Saving plot to :' + figdir_ + figname)

        plt.savefig(figdir_ + figname)
    plt.close(fig)
def map_hpc_to_hg_rotate(m,
                         epi_lon=0*u.degree, epi_lat=90*u.degree,
                         lon_bin=1*u.degree, lat_bin=1*u.degree,
                         lon_num=None, lat_num=None, **kwargs):
    """
    Transform raw data in HPC coordinates to HG' coordinates
    HG' = HG, except center at wave epicenter
    """
    x, y = wcs.convert_pixel_to_data([m.data.shape[1], m.data.shape[0]],
                                     [m.scale.x.value, m.scale.y.value],
                                     [m.reference_pixel.x.value, m.reference_pixel.y.value],
                                     [m.reference_coordinate.x.value, m.reference_coordinate.y.value])

    hccx, hccy, hccz = wcs.convert_hpc_hcc(x,
                                           y,
                                           angle_units='arcsec',
                                           dsun_meters=m.dsun.to('meter').value,
                                           z=True)

    rot_hccz, rot_hccx, rot_hccy = euler_zyz((hccz,
                                              hccx,
                                              hccy),
                                             (0.,
                                              epi_lat.to('degree').value-90.,
                                              -epi_lon.to('degree').value))

    lon_map, lat_map = wcs.convert_hcc_hg(rot_hccx,
                                          rot_hccy,
                                          b0_deg=m.heliographic_latitude.to('degree').value,
                                          l0_deg=m.heliographic_longitude.to('degree').value,
                                          z=rot_hccz)

    lon_range = (np.nanmin(lon_map), np.nanmax(lon_map))
    lat_range = (np.nanmin(lat_map), np.nanmax(lat_map))

    # This method results in a set of lons and lats that in general does not
    # exactly span the range of the data.
    # lon = np.arange(lon_range[0], lon_range[1], lon_bin)
    # lat = np.arange(lat_range[0], lat_range[1], lat_bin)

    # This method gives a set of lons and lats that exactly spans the range of
    # the data at the expense of having to define values of cdelt1 and cdelt2
    if lon_num is None:
        cdelt1 = lon_bin.to('degree').value
        lon = np.arange(lon_range[0], lon_range[1], cdelt1)
    else:
        nlon = lon_num.to('pixel').value
        cdelt1 = (lon_range[1] - lon_range[0]) / (1.0*nlon - 1.0)
        lon = np.linspace(lon_range[0], lon_range[1], num=nlon)

    if lat_num is None:
        cdelt2 = lat_bin.to('degree').value
        lat = np.arange(lat_range[0], lat_range[1], cdelt2)
    else:
        nlat = lat_num.to('pixel').value
        cdelt2 = (lat_range[1] - lat_range[0]) / (1.0*nlat - 1.0)
        lat = np.linspace(lat_range[0], lat_range[1], num=nlat)

    # Create the grid
    x_grid, y_grid = np.meshgrid(lon, lat)

    ng_xyz = wcs.convert_hg_hcc(x_grid,
                                y_grid,
                                b0_deg=m.heliographic_latitude.to('degree').value,
                                l0_deg=m.heliographic_longitude.to('degree').value,
                                z=True)

    ng_zp, ng_xp, ng_yp = euler_zyz((ng_xyz[2],
                                     ng_xyz[0],
                                     ng_xyz[1]),
                                    (epi_lon.to('degree').value,
                                     90.-epi_lat.to('degree').value,
                                     0.))

    # The function ravel flattens the data into a 1D array
    points = np.vstack((lon_map.ravel(), lat_map.ravel())).T
    values = np.array(m.data).ravel()

    # Get rid of all of the bad (nan) indices (i.e. those off of the sun)
    index = np.isfinite(points[:, 0]) * np.isfinite(points[:, 1])
    # points = np.vstack((points[index,0], points[index,1])).T
    points = points[index]
    values = values[index]

    newdata = griddata(points, values, (x_grid, y_grid), **kwargs)
    newdata[ng_zp < 0] = np.nan

    try:
        rsun = m.rsun_obs.to(u.arcsec).value
    except:
        rsun = solar_semidiameter_angular_size(t=m.meta['date-obs']).to(u.arcsec).value

    dict_header = {
        'CDELT1': cdelt1,
        'NAXIS1': len(lon),
        'CRVAL1': lon.min(),
        'CRPIX1': crpix12_value_for_HG,
        'CRPIX2': crpix12_value_for_HG,
        'CUNIT1': "deg",
        'CTYPE1': "HG",
        'CDELT2': cdelt2,
        'NAXIS2': len(lat),
        'CRVAL2': lat.min(),
        'CUNIT2': "deg",
        'CTYPE2': "HG",
        'DATE_OBS': m.meta['date-obs'],
        'DSUN_OBS': m.dsun.to('m').value,
        "CRLN_OBS": m.carrington_longitude.to('degree').value,
        "HGLT_OBS": m.heliographic_latitude.to('degree').value,
        "HGLN_OBS": m.heliographic_longitude.to('degree').value,
        'EXPTIME': m.exposure_time.to('s').value,
        'RSUN': rsun
    }

    # Find out where the non-finites are
    mask = np.logical_not(np.isfinite(newdata))

    # Return a masked array is appropriate
    if mask is None:
        hg = Map(newdata, dict_header)
    else:
        hg = Map(ma.array(newdata, mask=mask), dict_header)

    hg.plot_settings = m.plot_settings
    return hg
def map_hg_to_hpc_rotate(m,
                         epi_lon=90*u.degree, epi_lat=0*u.degree,
                         xbin=2.4*u.arcsec, ybin=2.4*u.arcsec,
                         xnum=None, ynum=None,
                         solar_information=None, **kwargs):
    """
    Transform raw data in HG' coordinates to HPC coordinates

    HG' = HG, except center at wave epicenter
    """

    # Origin grid, HG'
    lon_grid, lat_grid = wcs.convert_pixel_to_data([m.data.shape[1], m.data.shape[0]],
                                                   [m.scale.x.value, m.scale.y.value],
                                                   [m.reference_pixel.x.value, m.reference_pixel.y.value],
                                                   [m.reference_coordinate.x.value, m.reference_coordinate.y.value])

    # Origin grid, HG' to HCC'
    # HCC' = HCC, except centered at wave epicenter
    x, y, z = wcs.convert_hg_hcc(lon_grid, lat_grid,
                                 b0_deg=m.heliographic_latitude.to('degree').value,
                                 l0_deg=m.carrington_longitude.to('degree').value,
                                 z=True)

    # Origin grid, HCC' to HCC''
    # Moves the wave epicenter to initial conditions
    # HCC'' = HCC, except assuming that HGLT_OBS = 0
    zpp, xpp, ypp = euler_zyz((z,
                               x,
                               y),
                              (epi_lon.to('degree').value,
                               90.-epi_lat.to('degree').value,
                               0.))

    # Add in a solar rotation.  Useful when creating simulated HPC data from
    # HG data.  This code was adapted from the wave simulation code of the
    # AWARE project.
    if solar_information is not None:
        hglt_obs = solar_information['hglt_obs'].to('degree').value
        solar_rotation_value = solar_information['angle_rotated'].to('degree').value
        #print(hglt_obs, solar_rotation_value)
        #print('before', zpp, xpp, ypp)
        zpp, xpp, ypp = euler_zyz((zpp,
                                   xpp,
                                   ypp),
                                  (0.,
                                   hglt_obs,
                                   solar_rotation_value))
        #print('after', zpp, xpp, ypp)
    # Origin grid, HCC to HPC (arcsec)
    # xx, yy = wcs.convert_hcc_hpc(current_wave_map.header, xpp, ypp)
    xx, yy = wcs.convert_hcc_hpc(xpp, ypp,
                                 dsun_meters=m.dsun.to('meter').value)

    # Destination HPC grid
    hpcx_range = (np.nanmin(xx), np.nanmax(xx))
    hpcy_range = (np.nanmin(yy), np.nanmax(yy))

    if xnum is None:
        cdelt1 = xbin.to('arcsec').value
        hpcx = np.arange(hpcx_range[0], hpcx_range[1], cdelt1)
    else:
        nx = xnum.to('pixel').value
        cdelt1 = (hpcx_range[1] - hpcx_range[0]) / (1.0*nx - 1.0)
        hpcx = np.linspace(hpcx_range[1], hpcx_range[0], num=nx)

    if ynum is None:
        cdelt2 = ybin.to('arcsec').value
        hpcy = np.arange(hpcy_range[0], hpcy_range[1], cdelt2)
    else:
        ny = ynum.to('pixel').value
        cdelt2 = (hpcy_range[1] - hpcy_range[0]) / (1.0*ny - 1.0)
        hpcy = np.linspace(hpcy_range[1], hpcy_range[0], num=ny)

    # Calculate the grid mesh
    newgrid_x, newgrid_y = np.meshgrid(hpcx, hpcy)

    #
    # CRVAL1,2 and CRPIX1,2 are calculated so that the co-ordinate system is
    # at the center of the image
    # Note that crpix[] counts pixels starting at 1

    try:
        rsun = m.rsun_obs.to(u.arcsec).value
    except:
        rsun = solar_semidiameter_angular_size(t=m.meta['date-obs']).to(u.arcsec).value

    crpix1 = hpcx.size // 2
    crval1 = 0.0#hpcx[crpix1 - 1]
    crpix2 = hpcy.size // 2
    crval2 = 0.0#hpcy[crpix2 - 1]
    dict_header = {
        "CDELT1": cdelt1,
        "NAXIS1": len(hpcx),
        "CRVAL1": crval1,
        "CRPIX1": crpix1,
        "CUNIT1": "arcsec",
        "CTYPE1": "HPLN-TAN",
        "CDELT2": cdelt2,
        "NAXIS2": len(hpcy),
        "CRVAL2": crval2,
        "CRPIX2": crpix2,
        "CUNIT2": "arcsec",
        "CTYPE2": "HPLT-TAN",
        "HGLT_OBS": m.heliographic_latitude.to('degree').value,  # 0.0
        # "HGLN_OBS": 0.0,
        "CRLN_OBS": m.carrington_longitude.to('degree').value,  # 0.0
        'DATE_OBS': m.meta['date-obs'],
        'DSUN_OBS': m.dsun.to('m').value,
        'EXPTIME': m.exposure_time.to('s').value,
        'RSUN': rsun
    }

    # Coordinate positions (HPC) with corresponding map data
    points = np.vstack((xx.ravel(), yy.ravel())).T
    values = np.asarray(deepcopy(m.data)).ravel()

    # Solar rotation can push the points off disk and into areas that have
    # nans.  if this is the case, then griddata fails
    # Two solutions
    # 1 - replace all the nans with zeros, in order to get the code to run
    # 2 - the initial condition of zpp.ravel() >= 0 should be extended
    #     to make sure that only finite points are used.

    # 2D interpolation from origin grid to destination grid
    xy_condition = np.logical_and(np.isfinite(points[:, 0]), np.isfinite(points[:, 1]))
    valid_points = np.logical_and(zpp.ravel() >= 0, xy_condition)
    # 2D interpolation from origin grid to destination grid
    grid = griddata(points[valid_points],
                    values[valid_points],
                    (newgrid_x, newgrid_y), **kwargs)

    # Find out where the non-finites are
    mask = np.logical_not(np.isfinite(grid))

    # Return a masked array is appropriate
    if mask is None:
        hpc = Map(grid, dict_header)
    else:
        hpc = Map(ma.array(grid, mask=mask), dict_header)

    hpc.plot_settings = m.plot_settings
    return hpc
def imreg(vis=None,
          ephem=None,
          msinfo=None,
          imagefile=None,
          timerange=None,
          reftime=None,
          fitsfile=None,
          beamfile=None,
          offsetfile=None,
          toTb=None,
          sclfactor=1.0,
          verbose=False,
          p_ang=False,
          overwrite=True,
          usephacenter=True,
          deletehistory=False,
          subregion=[],
          docompress=False):
    ''' 
    main routine to register CASA images
           Required Inputs:
               vis: STRING. CASA measurement set from which the image is derived
               imagefile: STRING or LIST. name of the input CASA image
               timerange: STRING or LIST. timerange used to generate the CASA image, must have the same length as the input images. 
                          Each element should be in CASA standard time format, e.g., '2012/03/03/12:00:00~2012/03/03/13:00:00'
           Optional Inputs:
               msinfo: DICTIONARY. CASA MS information, output from read_msinfo. If not provided, generate one from the supplied vis
               ephem: DICTIONARY. solar ephem, output from read_horizons. 
                      If not provided, query JPL Horizons based on time info of the vis (internet connection required)
               fitsfile: STRING or LIST. name of the output registered fits files
               reftime: STRING or LIST. Each element should be in CASA standard time format, e.g., '2012/03/03/12:00:00'
               offsetfile: optionally provide an offset with a series of solar x and y offsets with timestamps 
               toTb: Bool. Convert the default Jy/beam to brightness temperature?
               sclfactor: scale the image values up by its value (to compensate VLA 20 dB attenuator)
               verbose: Bool. Show more diagnostic info if True.
               usephacenter: Bool -- if True, correct for the RA and DEC in the ms file based on solar empheris.
                                     Otherwise assume the phasecenter is correctly pointed to the solar disk center
                                     (EOVSA case)
               subregion: Region selection. See 'help par.region' for details.
    Usage:
    >>> from suncasa.utils import helioimage2fits as hf
    >>> hf.imreg(vis='mydata.ms', imagefile='myimage.image', fitsfile='myimage.fits',
                 timerange='2017/08/21/20:21:10~2017/08/21/20:21:18')
    The output fits file is 'myimage.fits'

    History:
    BC (sometime in 2014): function was first wrote, followed by a number of edits by BC and SY
    BC (2019-07-16): Added checks for stokes parameter. Verified that for converting from Jy/beam to brightness temperature,
                     the convention of 2*k_b*T should always be used. I.e., for unpolarized source, stokes I, RR, LL, XX, YY, 
                     etc. in the output CASA images from (t)clean should all have same values of radio intensity 
                     (in Jy/beam) and brightness temperature (in K).

    '''

    if deletehistory:
        ms_clearhistory(vis)

    if not imagefile:
        raise ValueError('Please specify input image')
    if not timerange:
        raise ValueError('Please specify timerange of the input image')
    if type(imagefile) == str:
        imagefile = [imagefile]
    if type(timerange) == str:
        timerange = [timerange]
    if not fitsfile:
        fitsfile = [img + '.fits' for img in imagefile]
    if type(fitsfile) == str:
        fitsfile = [fitsfile]
    nimg = len(imagefile)
    if len(timerange) != nimg:
        raise ValueError(
            'Number of input images does not equal to number of timeranges!')
    if len(fitsfile) != nimg:
        raise ValueError(
            'Number of input images does not equal to number of output fits files!'
        )
    nimg = len(imagefile)
    if verbose:
        print(str(nimg) + ' images to process...')

    if reftime:  # use as reference time to find solar disk RA and DEC to register the image, but not the actual timerange associated with the image
        if type(reftime) == str:
            reftime = [reftime] * nimg
        if len(reftime) != nimg:
            raise ValueError(
                'Number of reference times does not match that of input images!'
            )
        helio = ephem_to_helio(vis,
                               ephem=ephem,
                               msinfo=msinfo,
                               reftime=reftime,
                               usephacenter=usephacenter)
    else:
        # use the supplied timerange to register the image
        helio = ephem_to_helio(vis,
                               ephem=ephem,
                               msinfo=msinfo,
                               reftime=timerange,
                               usephacenter=usephacenter)

    if toTb:
        (bmajs, bmins, bpas, beamunits,
         bpaunits) = getbeam(imagefile=imagefile, beamfile=beamfile)

    for n, img in enumerate(imagefile):
        if verbose:
            print('processing image #' + str(n) + ' ' + img)
        fitsf = fitsfile[n]
        timeran = timerange[n]
        # obtain duration of the image as FITS header exptime
        try:
            [tbg0, tend0] = timeran.split('~')
            tbg_d = qa.getvalue(qa.convert(qa.totime(tbg0), 'd'))[0]
            tend_d = qa.getvalue(qa.convert(qa.totime(tend0), 'd'))[0]
            tdur_s = (tend_d - tbg_d) * 3600. * 24.
            dateobs = qa.time(qa.quantity(tbg_d, 'd'), form='fits', prec=10)[0]
        except:
            print('Error in converting the input timerange: ' + str(timeran) +
                  '. Proceeding to the next image...')
            continue

        hel = helio[n]
        if not os.path.exists(img):
            warnings.warn('{} does not existed!'.format(img))
        else:
            if os.path.exists(fitsf) and not overwrite:
                raise ValueError(
                    'Specified fits file already exists and overwrite is set to False. Aborting...'
                )
            else:
                p0 = hel['p0']
                tb.open(img + '/logtable', nomodify=False)
                nobs = tb.nrows()
                tb.removerows([i + 1 for i in range(nobs - 1)])
                tb.close()
                ia.open(img)
                imr = ia.rotate(pa=str(-p0) + 'deg')
                if subregion is not []:
                    imr = imr.subimage(region=subregion)
                imr.tofits(fitsf, history=False, overwrite=overwrite)
                imr.close()
                imsum = ia.summary()
                ia.close()
                ia.done()

            # construct the standard fits header
            # RA and DEC of the reference pixel crpix1 and crpix2
            (imra, imdec) = (imsum['refval'][0], imsum['refval'][1])
            # find out the difference of the image center to the CASA phase center
            # RA and DEC difference in arcseconds
            ddec = degrees((imdec - hel['dec_fld'])) * 3600.
            dra = degrees((imra - hel['ra_fld']) * cos(hel['dec_fld'])) * 3600.
            # Convert into image heliocentric offsets
            prad = -radians(hel['p0'])
            dx = (-dra) * cos(prad) - ddec * sin(prad)
            dy = (-dra) * sin(prad) + ddec * cos(prad)
            if offsetfile:
                try:
                    offset = np.load(offsetfile)
                except:
                    raise ValueError(
                        'The specified offsetfile does not exist!')
                reftimes_d = offset['reftimes_d']
                xoffs = offset['xoffs']
                yoffs = offset['yoffs']
                timg_d = hel['reftime']
                ind = bisect.bisect_left(reftimes_d, timg_d)
                xoff = xoffs[ind - 1]
                yoff = yoffs[ind - 1]
            else:
                xoff = hel['refx']
                yoff = hel['refy']
            if verbose:
                print(
                    'offset of image phase center to visibility phase center (arcsec): dx={0:.2f}, dy={1:.2f}'
                    .format(dx, dy))
                print(
                    'offset of visibility phase center to solar disk center (arcsec): dx={0:.2f}, dy={1:.2f}'
                    .format(xoff, yoff))
            (crval1, crval2) = (xoff + dx, yoff + dy)
            # update the fits header to heliocentric coordinates

            hdu = pyfits.open(fitsf, mode='update')
            hdu[0].verify('fix')
            header = hdu[0].header
            dshape = hdu[0].data.shape
            ndim = hdu[0].data.ndim
            (cdelt1,
             cdelt2) = (-header['cdelt1'] * 3600., header['cdelt2'] * 3600.
                        )  # Original CDELT1, 2 are for RA and DEC in degrees
            header['cdelt1'] = cdelt1
            header['cdelt2'] = cdelt2
            header['cunit1'] = 'arcsec'
            header['cunit2'] = 'arcsec'
            header['crval1'] = crval1
            header['crval2'] = crval2
            header['ctype1'] = 'HPLN-TAN'
            header['ctype2'] = 'HPLT-TAN'
            header['date-obs'] = dateobs  # begin time of the image
            if not p_ang:
                hel['p0'] = 0
            try:
                # this works for pyfits version of CASA 4.7.0 but not CASA 4.6.0
                if tdur_s:
                    header.set('exptime', tdur_s)
                else:
                    header.set('exptime', 1.)
                header.set('p_angle', hel['p0'])
                header.set('hgln_obs', 0.)
                header.set('rsun_ref', sun.constants.radius.value)
                if sunpyver <= 1:
                    header.set(
                        'dsun_obs',
                        sun.sunearth_distance(Time(dateobs)).to(u.meter).value)
                    header.set(
                        'rsun_obs',
                        sun.solar_semidiameter_angular_size(
                            Time(dateobs)).value)
                    header.set(
                        'hglt_obs',
                        sun.heliographic_solar_center(Time(dateobs))[1].value)
                else:
                    header.set(
                        'dsun_obs',
                        sun.earth_distance(Time(dateobs)).to(u.meter).value)
                    header.set('rsun_obs',
                               sun.angular_radius(Time(dateobs)).value)
                    header.set('hglt_obs', sun.L0(Time(dateobs)).value)
            except:
                # this works for astropy.io.fits
                if tdur_s:
                    header.append(('exptime', tdur_s))
                else:
                    header.append(('exptime', 1.))
                header.append(('p_angle', hel['p0']))
                header.append(('hgln_obs', 0.))
                header.append(('rsun_ref', sun.constants.radius.value))
                if sunpyver <= 1:
                    header.append(
                        ('dsun_obs', sun.sunearth_distance(Time(dateobs)).to(
                            u.meter).value))
                    header.append(('rsun_obs',
                                   sun.solar_semidiameter_angular_size(
                                       Time(dateobs)).value))
                    header.append(('hglt_obs',
                                   sun.heliographic_solar_center(
                                       Time(dateobs))[1].value))
                else:
                    header.append(
                        ('dsun_obs',
                         sun.earth_distance(Time(dateobs)).to(u.meter).value))
                    header.append(
                        ('rsun_obs', sun.angular_radius(Time(dateobs)).value))
                    header.append(('hglt_obs', sun.L0(Time(dateobs)).value))

            # check if stokes parameter exist
            exist_stokes = False
            stokes_mapper = {
                'I': 1,
                'Q': 2,
                'U': 3,
                'V': 4,
                'RR': -1,
                'LL': -2,
                'RL': -3,
                'LR': -4,
                'XX': -5,
                'YY': -6,
                'XY': -7,
                'YX': -8
            }
            if 'CRVAL3' in header.keys():
                if header['CTYPE3'] == 'STOKES':
                    stokenum = header['CRVAL3']
                    exist_stokes = True
            if 'CRVAL4' in header.keys():
                if header['CTYPE4'] == 'STOKES':
                    stokenum = header['CRVAL4']
                    exist_stokes = True
            if exist_stokes:
                if stokenum in stokes_mapper.values():
                    stokesstr = list(stokes_mapper.keys())[list(
                        stokes_mapper.values()).index(stokenum)]
                else:
                    print('Stokes parameter {0:d} not recognized'.format(
                        stokenum))
                if verbose:
                    print('This image is in Stokes ' + stokesstr)
            else:
                print(
                    'STOKES Information does not seem to exist! Assuming Stokes I'
                )
                stokenum = 1

            # intensity units to brightness temperature
            if toTb:
                # get restoring beam info
                bmaj = bmajs[n]
                bmin = bmins[n]
                beamunit = beamunits[n]
                data = hdu[
                    0].data  # remember the data order is reversed due to the FITS convension
                keys = list(header.keys())
                values = list(header.values())
                # which axis is frequency?
                faxis = keys[values.index('FREQ')][-1]
                faxis_ind = ndim - int(faxis)
                # find out the polarization of this image
                k_b = qa.constants('k')['value']
                c_l = qa.constants('c')['value']
                # Always use 2*kb for all polarizations
                const = 2. * k_b / c_l**2
                if header['BUNIT'].lower() == 'jy/beam':
                    header['BUNIT'] = 'K'
                    header['BTYPE'] = 'Brightness Temperature'
                    for i in range(dshape[faxis_ind]):
                        nu = header['CRVAL' +
                                    faxis] + header['CDELT' + faxis] * (
                                        i + 1 - header['CRPIX' + faxis])
                        if header['CUNIT' + faxis] == 'KHz':
                            nu *= 1e3
                        if header['CUNIT' + faxis] == 'MHz':
                            nu *= 1e6
                        if header['CUNIT' + faxis] == 'GHz':
                            nu *= 1e9
                        if len(bmaj) > 1:  # multiple (per-plane) beams
                            bmajtmp = bmaj[i]
                            bmintmp = bmin[i]
                        else:  # one single beam
                            bmajtmp = bmaj[0]
                            bmintmp = bmin[0]
                        if beamunit == 'arcsec':
                            bmaj0 = np.radians(bmajtmp / 3600.)
                            bmin0 = np.radians(bmintmp / 3600.)
                        if beamunit == 'arcmin':
                            bmaj0 = np.radians(bmajtmp / 60.)
                            bmin0 = np.radians(bmintmp / 60.)
                        if beamunit == 'deg':
                            bmaj0 = np.radians(bmajtmp)
                            bmin0 = np.radians(bmintmp)
                        if beamunit == 'rad':
                            bmaj0 = bmajtmp
                            bmin0 = bmintmp
                        beam_area = bmaj0 * bmin0 * np.pi / (4. * log(2.))
                        factor = const * nu**2  # SI unit
                        jy_to_si = 1e-26
                        # print(nu/1e9, beam_area, factor)
                        factor2 = sclfactor
                        # if sclfactor:
                        #     factor2 = 100.
                        if faxis == '3':
                            data[:,
                                 i, :, :] *= jy_to_si / beam_area / factor * factor2
                        if faxis == '4':
                            data[
                                i, :, :, :] *= jy_to_si / beam_area / factor * factor2

            header = fu.headerfix(header)
            hdu.flush()
            hdu.close()

            if ndim - np.count_nonzero(np.array(dshape) == 1) > 3:
                docompress = False
                '''
                    Caveat: only 1D, 2D, or 3D images are currently supported by
                    the astropy fits compression. If a n-dimensional image data array
                    does not have at least n-3 single-dimensional entries,
                    force docompress to be False
                '''

                print(
                    'warning: The fits data contains more than 3 non squeezable dimensions. Skipping fits compression..'
                )
            if docompress:
                fitsftmp = fitsf + ".tmp.fits"
                os.system("mv {} {}".format(fitsf, fitsftmp))
                hdu = pyfits.open(fitsftmp)
                hdu[0].verify('fix')
                header = hdu[0].header
                data = hdu[0].data
                fu.write_compressed_image_fits(fitsf,
                                               data,
                                               header,
                                               compression_type='RICE_1',
                                               quantize_level=4.0)
                os.system("rm -rf {}".format(fitsftmp))
    if deletehistory:
        ms_restorehistory(vis)
    return fitsfile
Exemple #6
0
    def plot_filament_track(self):

    
        good, = np.where(self.dat['track_id'].values == self.tid)
    
    #get start time of track for filename
#        ofname = '{0}_track{1:6d}'.format(dat['event_starttime'][good[0]],i).replace(' ','0').replace(':','_')
        self.ofile = self.ifile.split('/')[-1].replace('fits.fz','png')
        sun = pyfits.open(self.ifile)
#Solar Halpha data   
        sundat = sun[1].data
#Set up image properties
        sc  = 1 
        dpi = 100*sc
#get image extent (i.e. physical coordinates)
        x0 = sun[1].header['CRVAL1']-sun[1].header['CRPIX1']
        y0 = sun[1].header['CRVAL2']-sun[1].header['CRPIX2']

        dx = 1.#assumed approximate
        dy = 1.#assumed approximate

#Correct for Halpha images automatic scaling of solar radius to 900``
        try:
            asr = solar_semidiameter_angular_size(self.dat['event_starttime'].values[good[0]])
        except:
            asr = solar_semidiameter_angular_size(self.dat['event_starttime'].values[good])

#store the scale factor
        sf = asr.value/900.
  
        sx, sy = np.shape(sundat)
    #add to stoptime (i.e. observed time) 
        self.stop = datetime.datetime.strptime(self.ofile[:-6],'%Y%m%d%H%M%S')
    
    #create figure and add sun
        self.fig, self.ax = plt.subplots(figsize=(sc*float(sx)/dpi,sc*float(sy)/dpi),dpi=dpi)
    #set sun to fill entire range
        self.fig.subplots_adjust(left=0,bottom=0,right=1,top=1)
#Turn off axis
        self.ax.set_axis_off()

        self.ax.imshow(sundat,cmap=plt.cm.gray,extent=[sf*x0,sf*(x0+dx*sx),sf*y0,sf*(y0+dy*sy)],origin='lower')
#text offset
        poff = 0.01
        self.ax.text(sf*x0+poff*sf*(dx*sx-x0),sf*y0+poff*sf*(dy*sy-y0),sun[1].header['DATE-OBS'],color='white',fontsize=38,fontweight='bold')
#        rs = plt.Circle((0.,0.),radius=1000.,color='gray',fill=False,linewidth=5,zorder=0)
#        ax.add_patch(rs)
    
    #plot track polygons for given id
        for j in good:
            inc = 'red'
            if self.dat['obs_observatory'].values[j] == 'HA2': inc='blue'
            poly = plt.Polygon(loads(self.dat['hpc_bbox'].values[j]).exterior,color=inc,linewidth=0.5,fill=None)
            self.ax.add_patch(poly)
    #over plot rotation track
        if good.size > 1:
     #array of time differences between obs and filament track
            td = np.abs(self.dat['event_starttime_dt'][good]-self.stop)
            nearest, = np.where(td == td.min())
            roplot = good[nearest][0] #nearest filament trace in time
        else: 
            roplot = good[0]
#plot rotation of nearest filament placement
        self.plot_rotation(self.dat['event_starttime_dt'][roplot],self.dat['hpc_bbox'].values[roplot],color='green')
    
    
    #Setup plots
#        ticks = [-1000.,-500.,0.,500.,1000.]
        lim = [sf*x0,sf*(x0+sx*dx)]
        self.ax.set_xlim(lim)
        self.ax.set_ylim(lim)
       
#remove axis labels just make an image
#        self.ax.set_xticks(ticks)
#        self.ax.set_yticks(ticks)
#        self.ax.set_xlabel('Solar X [arcsec]')
#        self.ax.set_ylabel('Solar Y [arcsec]')
    
    #save fig
        self.fig.savefig(self.pdir+self.ofile,bbox_inches=0,dpi=dpi)
        self.fig.clear()
        plt.close()
Exemple #7
0
def plt_qlook_image(imres, figdir=None, verbose=True, synoptic=False):
    from matplotlib import pyplot as plt
    from sunpy import map as smap
    from sunpy import sun
    from matplotlib import colors
    import astropy.units as u
    if not figdir:
        figdir = './'
    nspw = len(set(imres['Spw']))
    plttimes = list(set(imres['BeginTime']))
    ntime = len(plttimes)
    # sort the imres according to time
    images = np.array(imres['ImageName'])
    btimes = Time(imres['BeginTime'])
    etimes = Time(imres['EndTime'])
    spws = np.array(imres['Spw'])
    suc = np.array(imres['Succeeded'])
    inds = btimes.argsort()
    images_sort = images[inds].reshape(ntime, nspw)
    btimes_sort = btimes[inds].reshape(ntime, nspw)
    suc_sort = suc[inds].reshape(ntime, nspw)
    spws_sort = spws[inds].reshape(ntime, nspw)
    if verbose:
        print '{0:d} figures to plot'.format(ntime)
    plt.ioff()
    fig = plt.figure(figsize=(8, 8))
    plt.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=0, hspace=0)
    for i in range(ntime):
        plt.ioff()
        plt.clf()
        plttime = btimes_sort[i, 0]
        tofd = plttime.mjd - np.fix(plttime.mjd)
        suci = suc_sort[i]
        if not synoptic:
            if tofd < 16. / 24. or sum(
                    suci
            ) < nspw - 2:  # if time of the day is before 16 UT (and 24 UT), skip plotting (because the old antennas are not tracking)
                continue
        #fig=plt.figure(figsize=(9,6))
        #fig.suptitle('EOVSA @ '+plttime.iso[:19])
        if synoptic:
            fig.text(0.01,
                     0.98,
                     plttime.iso[:10],
                     color='w',
                     fontweight='bold',
                     fontsize=12,
                     ha='left')
        else:
            fig.text(0.01,
                     0.98,
                     plttime.iso[:19],
                     color='w',
                     fontweight='bold',
                     fontsize=12,
                     ha='left')
        if verbose:
            print 'Plotting image at: ', plttime.iso
        for n in range(nspw):
            plt.ioff()
            image = images_sort[i, n]
            #fig.add_subplot(nspw/3, 3, n+1)
            fig.add_subplot(nspw / 2, 2, n + 1)
            if suci[n]:
                try:
                    eomap = smap.Map(image)
                except:
                    continue
                sz = eomap.data.shape
                if len(sz) == 4:
                    eomap.data = eomap.data.reshape((sz[2], sz[3]))
                eomap.data[np.isnan(eomap.data)] = 0.0
                #resample the image for plotting
                dim = u.Quantity([256, 256], u.pixel)
                eomap = eomap.resample(dim)
                eomap.plot_settings['cmap'] = plt.get_cmap('jet')
                eomap.plot_settings['norm'] = colors.Normalize(vmin=-1e5,
                                                               vmax=1e6)
                eomap.plot()
                if not synoptic:
                    eomap.draw_limb()
                eomap.draw_grid()
                ax = plt.gca()
                ax.set_xlim([-1080, 1080])
                ax.set_ylim([-1080, 1080])
                spwran = spws_sort[i, n]
                freqran = [int(s) * 0.5 + 2.9 for s in spwran.split('~')]
                ax.text(0.98,
                        0.01,
                        '{0:.1f} - {1:.1f} GHz'.format(freqran[0], freqran[1]),
                        color='w',
                        transform=ax.transAxes,
                        fontweight='bold',
                        ha='right')
                ax.set_title(' ')
                #ax.set_title('spw '+spws_sort[i,n])
                #ax.text(0.01,0.02, plttime.isot,transform=ax.transAxes,color='white')
                ax.set_xlabel('')
                ax.set_ylabel('')
                ax.set_xticklabels([''])
                ax.set_yticklabels([''])
            else:
                #make an empty map
                data = np.zeros((512, 512))
                header = {
                    "DATE-OBS": plttime.isot,
                    "EXPTIME": 0.,
                    "CDELT1": 5.,
                    "NAXIS1": 512,
                    "CRVAL1": 0.,
                    "CRPIX1": 257,
                    "CUNIT1": "arcsec",
                    "CTYPE1": "HPLN-TAN",
                    "CDELT2": 5.,
                    "NAXIS2": 512,
                    "CRVAL2": 0.,
                    "CRPIX2": 257,
                    "CUNIT2": "arcsec",
                    "CTYPE2": "HPLT-TAN",
                    "HGLT_OBS":
                    sun.heliographic_solar_center(plttime)[1].value,
                    "HGLN_OBS": 0.,
                    "RSUN_OBS":
                    sun.solar_semidiameter_angular_size(plttime).value,
                    "RSUN_REF": sun.constants.radius.value,
                    "DSUN_OBS":
                    sun.sunearth_distance(plttime).to(u.meter).value,
                }
                eomap = smap.Map(data, header)
                eomap.plot_settings['cmap'] = plt.get_cmap('jet')
                eomap.plot_settings['norm'] = colors.Normalize(vmin=-1e5,
                                                               vmax=1e6)
                eomap.plot()
                if not synoptic:
                    eomap.draw_limb()
                eomap.draw_grid()
                ax = plt.gca()
                ax.set_xlim([-1080, 1080])
                ax.set_ylim([-1080, 1080])
                #ax.set_title('spw '+spwran+'( )'))
                spwran = spws_sort[i, n]
                freqran = [int(s) * 0.5 + 2.9 for s in spwran.split('~')]
                spwran = spws_sort[i, n]
                #ax.set_title('{0:.1f} - {1:.1f} GHz'.format(freqran[0],freqran[1]))
                ax.text(0.98,
                        0.01,
                        '{0:.1f} - {1:.1f} GHz'.format(freqran[0], freqran[1]),
                        color='w',
                        transform=ax.transAxes,
                        fontweight='bold',
                        ha='right')
                ax.set_title(' ')

                #ax.text(0.01,0.02, plttime.isot,transform=ax.transAxes,color='white')
                ax.set_xlabel('')
                ax.set_ylabel('')
                ax.set_xticklabels([''])
                ax.set_yticklabels([''])
        fig_tdt = plttime.to_datetime()
        if synoptic:
            fig_subdir = fig_tdt.strftime("%Y/")
            figname = 'eovsa_qlimg_' + plttime.iso[:10].replace('-',
                                                                '') + '.png'
        else:
            fig_subdir = fig_tdt.strftime("%Y/%m/%d/")
            figname = 'eovsa_qlimg_' + plttime.isot.replace(':', '').replace(
                '-', '')[:15] + '.png'
        figdir_ = figdir + fig_subdir
        if not os.path.exists(figdir_):
            os.makedirs(figdir_)
        if verbose:
            print 'Saving plot to :' + figdir_ + figname
        plt.savefig(figdir_ + figname)
    plt.close(fig)
Exemple #8
0
def imreg(vis=None, ephem=None, msinfo=None, reftime=None, imagefile=None, fitsfile=None, beamfile=None, \
          offsetfile=None, toTb=None, scl100=None, verbose=False, p_ang = False, overwrite = True, usephacenter=False):
    ia = iatool()
    if not imagefile:
        raise ValueError, 'Please specify input image'
    if not reftime:
        raise ValueError, 'Please specify reference time corresponding to the input image'
    if not fitsfile:
        fitsfile = [img + '.fits' for img in imagefile]
    if len(imagefile) != len(reftime):
        raise ValueError, 'Number of input images does not equal to number of helio coord headers!'
    if len(imagefile) != len(fitsfile):
        raise ValueError, 'Number of input images does not equal to number of output fits files!'
    nimg = len(imagefile)
    if verbose:
        print str(nimg) + ' images to process...'
    helio = ephem_to_helio(vis,
                           ephem=ephem,
                           msinfo=msinfo,
                           reftime=reftime,
                           usephacenter=usephacenter)
    for n, img in enumerate(imagefile):
        if verbose:
            print 'processing image #' + str(n)
        fitsf = fitsfile[n]
        hel = helio[n]
        if not os.path.exists(img):
            raise ValueError, 'Please specify input image'
        if os.path.exists(fitsf) and not overwrite:
            raise ValueError, 'Specified fits file already exists and overwrite is set to False. Aborting...'
        else:
            p0 = hel['p0']
            ia.open(img)
            imr = ia.rotate(pa=str(-p0) + 'deg')
            imr.tofits(fitsf, history=False, overwrite=overwrite)
            imr.close()
            sum = ia.summary()
            ia.close()
        # construct the standard fits header
        # RA and DEC of the reference pixel crpix1 and crpix2
        (imra, imdec) = (sum['refval'][0], sum['refval'][1])
        # find out the difference of the image center to the CASA phase center
        # RA and DEC difference in arcseconds
        ddec = degrees((imdec - hel['dec_fld'])) * 3600.
        dra = degrees((imra - hel['ra_fld']) * cos(hel['dec_fld'])) * 3600.
        # Convert into image heliocentric offsets
        prad = -radians(hel['p0'])
        dx = (-dra) * cos(prad) - ddec * sin(prad)
        dy = (-dra) * sin(prad) + ddec * cos(prad)
        if offsetfile:
            try:
                offset = np.load(offsetfile)
            except:
                raise ValueError, 'The specified offsetfile does not exist!'
            reftimes_d = offset['reftimes_d']
            xoffs = offset['xoffs']
            yoffs = offset['yoffs']
            timg_d = hel['reftime']
            ind = bisect.bisect_left(reftimes_d, timg_d)
            xoff = xoffs[ind - 1]
            yoff = yoffs[ind - 1]
        else:
            xoff = hel['refx']
            yoff = hel['refy']
        if verbose:
            print 'offset of image phase center to visibility phase center (arcsec): ', dx, dy
            print 'offset of visibility phase center to solar disk center (arcsec): ', xoff, yoff
        (crval1, crval2) = (xoff + dx, yoff + dy)
        # update the fits header to heliocentric coordinates

        hdu = pyfits.open(fitsf, mode='update')
        header = hdu[0].header
        (cdelt1,
         cdelt2) = (-header['cdelt1'] * 3600., header['cdelt2'] * 3600.
                    )  # Original CDELT1, 2 are for RA and DEC in degrees
        header['cdelt1'] = cdelt1
        header['cdelt2'] = cdelt2
        header['cunit1'] = 'arcsec'
        header['cunit2'] = 'arcsec'
        header['crval1'] = crval1
        header['crval2'] = crval2
        header['ctype1'] = 'HPLN-TAN'
        header['ctype2'] = 'HPLT-TAN'
        header['date-obs'] = hel['date-obs']  #begin time of the image
        if not p_ang:
            hel['p0'] = 0
        try:
            # this works for pyfits version of CASA 4.7.0 but not CASA 4.6.0
            header.update('exptime', hel['exptime'])
            header.update('p_angle', hel['p0'])
            header.update(
                'dsun_obs',
                sun.sunearth_distance(Time(hel['date-obs'])).to(u.meter).value)
            header.update(
                'rsun_obs',
                sun.solar_semidiameter_angular_size(Time(
                    hel['date-obs'])).value)
            header.update('rsun_ref', sun.constants.radius.value)
            header.update('hgln_obs', 0.)
            header.update(
                'hglt_obs',
                sun.heliographic_solar_center(Time(hel['date-obs']))[1].value)
        except:
            # this works for astropy.io.fits
            header.append(('exptime', hel['exptime']))
            header.append(('p_angle', hel['p0']))
            header.append(
                ('dsun_obs', sun.sunearth_distance(Time(hel['date-obs'])).to(
                    u.meter).value))
            header.append(('rsun_obs',
                           sun.solar_semidiameter_angular_size(
                               Time(hel['date-obs'])).value))
            header.append(('rsun_ref', sun.constants.radius.value))
            header.append(('hgln_obs', 0.))
            header.append(('hglt_obs',
                           sun.heliographic_solar_center(Time(
                               hel['date-obs']))[1].value))

        # header.update('comment', 'Fits header updated to heliocentric coordinates by Bin Chen')

        # update intensity units, i.e. to brightness temperature?
        if toTb:
            # get restoring beam info
            (bmajs, bmins, bpas, beamunits,
             bpaunits) = getbeam(imagefile=imagefile, beamfile=beamfile)
            bmaj = bmajs[n]
            bmin = bmins[n]
            beamunit = beamunits[n]
            data = hdu[
                0].data  # remember the data order is reversed due to the FITS convension
            dim = data.ndim
            sz = data.shape
            keys = header.keys()
            values = header.values()
            # which axis is frequency?
            faxis = keys[values.index('FREQ')][-1]
            faxis_ind = dim - int(faxis)
            if header['BUNIT'].lower() == 'jy/beam':
                header['BUNIT'] = 'K'
                for i in range(sz[faxis_ind]):
                    nu = header['CRVAL' + faxis] + header['CDELT' + faxis] * \
                                                   (i + 1 - header['CRPIX' + faxis])
                    if header['CUNIT' + faxis] == 'KHz':
                        nu *= 1e3
                    if header['CUNIT' + faxis] == 'MHz':
                        nu *= 1e6
                    if header['CUNIT' + faxis] == 'GHz':
                        nu *= 1e9
                    if len(bmaj) > 1:  # multiple (per-plane) beams
                        bmajtmp = bmaj[i]
                        bmintmp = bmin[i]
                    else:  # one single beam
                        bmajtmp = bmaj[0]
                        bmintmp = bmin[0]
                    if beamunit == 'arcsec':
                        bmaj0 = np.radians(bmajtmp / 3600.)
                        bmin0 = np.radians(bmajtmp / 3600.)
                    if beamunit == 'arcmin':
                        bmaj0 = np.radians(bmajtmp / 60.)
                        bmin0 = np.radians(bmintmp / 60.)
                    if beamunit == 'deg':
                        bmaj0 = np.radians(bmajtmp)
                        bmin0 = np.radians(bmintmp)
                    if beamunit == 'rad':
                        bmaj0 = bmajtmp
                        bmin0 = bmintmp
                    beam_area = bmaj0 * bmin0 * np.pi / (4. * log(2.))
                    k_b = qa.constants('k')['value']
                    c_l = qa.constants('c')['value']
                    factor = 2. * k_b * nu**2 / c_l**2  # SI unit
                    jy_to_si = 1e-26
                    # print nu/1e9, beam_area, factor
                    factor2 = 1.
                    if scl100:
                        factor2 = 100.
                    if faxis == '3':
                        data[:,
                             i, :, :] *= jy_to_si / beam_area / factor * factor2
                    if faxis == '4':
                        data[
                            i, :, :, :] *= jy_to_si / beam_area / factor * factor2

        hdu.flush()
        hdu.close()
Exemple #9
0
def make_sunpy(evtdata, hdr, norm_map=False):
    """ Make a sunpy map based on the NuSTAR data.
    
    Parameters
    ----------
    evtdata: FITS data structure
        This should be an hdu.data structure from a NuSTAR FITS file.

    hdr: FITS header containing the astrometric information

    Optional keywords

    norm_map: Normalise the map data by the exposure (live) time, so units 
    of DN/s. Defaults to "False" and DN
    
    Returns
    -------

    nustar_map:
        A sunpy map objecct
    
    """

    from sunpy.coordinates import get_sunearth_distance, get_sun_B0

    # Parse Header keywords
    for field in hdr.keys():
        if field.find('TYPE') != -1:
            if hdr[field] == 'X':
                print(hdr[field][5:8])
                xval = field[5:8]
            if hdr[field] == 'Y':
                print(hdr[field][5:8])
                yval = field[5:8]
        
    min_x= hdr['TLMIN'+xval]
    min_y= hdr['TLMIN'+yval]
    max_x= hdr['TLMAX'+xval]
    max_y= hdr['TLMAX'+yval]

    delx = abs(hdr['TCDLT'+xval])
    dely = abs(hdr['TCDLT'+yval])

    x = evtdata['X'][:]
    y = evtdata['Y'][:]
    met = evtdata['TIME'][:]*u.s
    mjdref=hdr['MJDREFI']
    mid_obs_time = astropy.time.Time(mjdref*u.d+met.mean(), format = 'mjd')

    # Add in the exposure time (or livetime), just a number not units of seconds 
    exp_time=hdr['EXPOSURE']

    # Use the native binning for now

    # Assume X and Y are the same size
    resample = 1.0
    scale = delx * resample
    bins = (max_x - min_x) / (resample)

    H, yedges, xedges = np.histogram2d(y, x, bins=bins, range = [[min_y,max_y], [min_x, max_x]])

    #Normalise the data with the exposure (or live) time?
    if norm_map is True:
    	H=H/exp_time
    	pixluname='DN/s'
    else:
    	pixluname='DN'


    dict_header = {
    "DATE-OBS": mid_obs_time.iso,
    "EXPTIME": exp_time,
    "CDELT1": scale,
    "NAXIS1": bins,
    "CRVAL1": 0.,
    "CRPIX1": bins*0.5,
    "CUNIT1": "arcsec",
    "CTYPE1": "HPLN-TAN",
    "CDELT2": scale,
    "NAXIS2": bins,
    "CRVAL2": 0.,
    "CRPIX2": bins*0.5 + 0.5,
    "CUNIT2": "arcsec",
    "CTYPE2": "HPLT-TAN",
    "PIXLUNIT": pixluname,
    "HGLT_OBS": get_sun_B0(mid_obs_time),
    "HGLN_OBS": 0,
    "RSUN_OBS": sun.solar_semidiameter_angular_size(mid_obs_time).value,
    "RSUN_REF": sun.constants.radius.value,
    # Assumes dsun_obs in m if don't specify the units, so give units
    "DSUN_OBS": get_sunearth_distance(mid_obs_time).value*u.astrophys.au
    }
    # For some reason the DSUN_OBS crashed the save...
    
#    header = sunpy.map.MapMeta(dict_header)
    header = sunpy.util.MetaDict(dict_header)

    nustar_map = sunpy.map.Map(H, header)
    
    return nustar_map
Exemple #10
0
def imreg(vis=None,
          ephem=None,
          msinfo=None,
          imagefile=None,
          timerange=None,
          reftime=None,
          fitsfile=None,
          beamfile=None,
          offsetfile=None,
          toTb=None,
          scl100=None,
          verbose=False,
          p_ang=False,
          overwrite=True,
          usephacenter=True,
          deletehistory=False):
    ''' 
    main routine to register CASA images
           Required Inputs:
               vis: STRING. CASA measurement set from which the image is derived
               imagefile: STRING or LIST. name of the input CASA image
               timerange: STRING or LIST. timerange used to generate the CASA image, must have the same length as the input images. 
                          Each element should be in CASA standard time format, e.g., '2012/03/03/12:00:00~2012/03/03/13:00:00'
           Optional Inputs:
               msinfo: DICTIONARY. CASA MS information, output from read_msinfo. If not provided, generate one from the supplied vis
               ephem: DICTIONARY. solar ephem, output from read_horizons. 
                      If not provided, query JPL Horizons based on time info of the vis (internet connection required)
               fitsfile: STRING or LIST. name of the output registered fits files
               reftime: STRING or LIST. Each element should be in CASA standard time format, e.g., '2012/03/03/12:00:00'
               offsetfile: optionally provide an offset with a series of solar x and y offsets with timestamps 
               toTb: Bool. Convert the default Jy/beam to brightness temperature?
               scl100: Bool. If True, scale the image values up by 100 (to compensate VLA 20 dB attenuator)
               verbose: Bool. Show more diagnostic info if True.
               usephacenter: Bool -- if True, correct for the RA and DEC in the ms file based on solar empheris.
                                     Otherwise assume the phasecenter is correctly pointed to the solar disk center
                                     (EOVSA case)
    '''
    ia = iatool()

    if deletehistory:
        msclearhistory(vis)
    if verbose:
        import time
        t0 = time.time()
        prtidx = 1
        print('point {}: {}'.format(prtidx, time.time() - t0))
        prtidx += 1

    if not imagefile:
        raise ValueError, 'Please specify input image'
    if not timerange:
        raise ValueError, 'Please specify timerange of the input image'
    if type(imagefile) == str:
        imagefile = [imagefile]
    if type(timerange) == str:
        timerange = [timerange]
    if not fitsfile:
        fitsfile = [img + '.fits' for img in imagefile]
    if type(fitsfile) == str:
        fitsfile = [fitsfile]
    nimg = len(imagefile)
    if len(timerange) != nimg:
        raise ValueError, 'Number of input images does not equal to number of timeranges!'
    if len(fitsfile) != nimg:
        raise ValueError, 'Number of input images does not equal to number of output fits files!'
    nimg = len(imagefile)
    if verbose:
        print str(nimg) + ' images to process...'

    if verbose:
        print('point {}: {}'.format(prtidx, time.time() - t0))
        prtidx += 1

    if reftime:  # use as reference time to find solar disk RA and DEC to register the image, but not the actual timerange associated with the image
        if type(reftime) == str:
            reftime = [reftime] * nimg
        if len(reftime) != nimg:
            raise ValueError, 'Number of reference times does not match that of input images!'
        helio = ephem_to_helio(vis,
                               ephem=ephem,
                               msinfo=msinfo,
                               reftime=reftime,
                               usephacenter=usephacenter)
    else:
        # use the supplied timerange to register the image
        helio = ephem_to_helio(vis,
                               ephem=ephem,
                               msinfo=msinfo,
                               reftime=timerange,
                               usephacenter=usephacenter)

    if verbose:
        print('point {}: {}'.format(prtidx, time.time() - t0))
        prtidx += 1

    for n, img in enumerate(imagefile):
        if verbose:
            print 'processing image #' + str(n)
        fitsf = fitsfile[n]
        timeran = timerange[n]
        # obtain duration of the image as FITS header exptime
        try:
            [tbg0, tend0] = timeran.split('~')
            tbg_d = qa.getvalue(qa.convert(qa.totime(tbg0), 'd'))[0]
            tend_d = qa.getvalue(qa.convert(qa.totime(tend0), 'd'))[0]
            tdur_s = (tend_d - tbg_d) * 3600. * 24.
            dateobs = qa.time(qa.quantity(tbg_d, 'd'), form='fits', prec=10)[0]
        except:
            print 'Error in converting the input timerange: ' + str(
                timeran) + '. Proceeding to the next image...'
            continue

        if verbose:
            print('point {}: {}'.format(prtidx, time.time() - t0))
            prtidx += 1

        hel = helio[n]
        if not os.path.exists(img):
            raise ValueError, 'Please specify input image'
        if os.path.exists(fitsf) and not overwrite:
            raise ValueError, 'Specified fits file already exists and overwrite is set to False. Aborting...'
        else:
            p0 = hel['p0']
            ia.open(img)
            imr = ia.rotate(pa=str(-p0) + 'deg')
            imr.tofits(fitsf, history=False, overwrite=overwrite)
            imr.close()
            imsum = ia.summary()
            ia.close()

        if verbose:
            print('point {}: {}'.format(prtidx, time.time() - t0))
            prtidx += 1

        # construct the standard fits header
        # RA and DEC of the reference pixel crpix1 and crpix2
        (imra, imdec) = (imsum['refval'][0], imsum['refval'][1])
        # find out the difference of the image center to the CASA phase center
        # RA and DEC difference in arcseconds
        ddec = degrees((imdec - hel['dec_fld'])) * 3600.
        dra = degrees((imra - hel['ra_fld']) * cos(hel['dec_fld'])) * 3600.
        # Convert into image heliocentric offsets
        prad = -radians(hel['p0'])
        dx = (-dra) * cos(prad) - ddec * sin(prad)
        dy = (-dra) * sin(prad) + ddec * cos(prad)
        if offsetfile:
            try:
                offset = np.load(offsetfile)
            except:
                raise ValueError, 'The specified offsetfile does not exist!'
            reftimes_d = offset['reftimes_d']
            xoffs = offset['xoffs']
            yoffs = offset['yoffs']
            timg_d = hel['reftime']
            ind = bisect.bisect_left(reftimes_d, timg_d)
            xoff = xoffs[ind - 1]
            yoff = yoffs[ind - 1]
        else:
            xoff = hel['refx']
            yoff = hel['refy']
        if verbose:
            print 'offset of image phase center to visibility phase center (arcsec): ', dx, dy
            print 'offset of visibility phase center to solar disk center (arcsec): ', xoff, yoff
        (crval1, crval2) = (xoff + dx, yoff + dy)
        # update the fits header to heliocentric coordinates

        if verbose:
            print('point {}: {}'.format(prtidx, time.time() - t0))
            prtidx += 1

        hdu = pyfits.open(fitsf, mode='update')

        if verbose:
            print('point {}: {}'.format(prtidx, time.time() - t0))
            prtidx += 1

        header = hdu[0].header
        (cdelt1,
         cdelt2) = (-header['cdelt1'] * 3600., header['cdelt2'] * 3600.
                    )  # Original CDELT1, 2 are for RA and DEC in degrees
        header['cdelt1'] = cdelt1
        header['cdelt2'] = cdelt2
        header['cunit1'] = 'arcsec'
        header['cunit2'] = 'arcsec'
        header['crval1'] = crval1
        header['crval2'] = crval2
        header['ctype1'] = 'HPLN-TAN'
        header['ctype2'] = 'HPLT-TAN'
        header['date-obs'] = dateobs  # begin time of the image
        if not p_ang:
            hel['p0'] = 0
        try:
            # this works for pyfits version of CASA 4.7.0 but not CASA 4.6.0
            if tdur_s:
                header.set('exptime', tdur_s)
            else:
                header.set('exptime', 1.)
            header.set('p_angle', hel['p0'])
            header.set('dsun_obs',
                       sun.sunearth_distance(Time(dateobs)).to(u.meter).value)
            header.set(
                'rsun_obs',
                sun.solar_semidiameter_angular_size(Time(dateobs)).value)
            header.set('rsun_ref', sun.constants.radius.value)
            header.set('hgln_obs', 0.)
            header.set('hglt_obs',
                       sun.heliographic_solar_center(Time(dateobs))[1].value)
        except:
            # this works for astropy.io.fits
            if tdur_s:
                header.append(('exptime', tdur_s))
            else:
                header.append(('exptime', 1.))
            header.append(('p_angle', hel['p0']))
            header.append(
                ('dsun_obs',
                 sun.sunearth_distance(Time(dateobs)).to(u.meter).value))
            header.append(
                ('rsun_obs',
                 sun.solar_semidiameter_angular_size(Time(dateobs)).value))
            header.append(('rsun_ref', sun.constants.radius.value))
            header.append(('hgln_obs', 0.))
            header.append(
                ('hglt_obs',
                 sun.heliographic_solar_center(Time(dateobs))[1].value))

        if verbose:
            print('point {}: {}'.format(prtidx, time.time() - t0))
            prtidx += 1

        # update intensity units, i.e. to brightness temperature?
        if toTb:
            # get restoring beam info
            (bmajs, bmins, bpas, beamunits,
             bpaunits) = getbeam(imagefile=imagefile, beamfile=beamfile)
            bmaj = bmajs[n]
            bmin = bmins[n]
            beamunit = beamunits[n]
            data = hdu[
                0].data  # remember the data order is reversed due to the FITS convension
            dim = data.ndim
            sz = data.shape
            keys = header.keys()
            values = header.values()
            # which axis is frequency?
            faxis = keys[values.index('FREQ')][-1]
            faxis_ind = dim - int(faxis)
            if header['BUNIT'].lower() == 'jy/beam':
                header['BUNIT'] = 'K'
                header['BTYPE'] = 'Brightness Temperature'
                for i in range(sz[faxis_ind]):
                    nu = header['CRVAL' + faxis] + header['CDELT' + faxis] * (
                        i + 1 - header['CRPIX' + faxis])
                    if header['CUNIT' + faxis] == 'KHz':
                        nu *= 1e3
                    if header['CUNIT' + faxis] == 'MHz':
                        nu *= 1e6
                    if header['CUNIT' + faxis] == 'GHz':
                        nu *= 1e9
                    if len(bmaj) > 1:  # multiple (per-plane) beams
                        bmajtmp = bmaj[i]
                        bmintmp = bmin[i]
                    else:  # one single beam
                        bmajtmp = bmaj[0]
                        bmintmp = bmin[0]
                    if beamunit == 'arcsec':
                        bmaj0 = np.radians(bmajtmp / 3600.)
                        bmin0 = np.radians(bmajtmp / 3600.)
                    if beamunit == 'arcmin':
                        bmaj0 = np.radians(bmajtmp / 60.)
                        bmin0 = np.radians(bmintmp / 60.)
                    if beamunit == 'deg':
                        bmaj0 = np.radians(bmajtmp)
                        bmin0 = np.radians(bmintmp)
                    if beamunit == 'rad':
                        bmaj0 = bmajtmp
                        bmin0 = bmintmp
                    beam_area = bmaj0 * bmin0 * np.pi / (4. * log(2.))
                    k_b = qa.constants('k')['value']
                    c_l = qa.constants('c')['value']
                    factor = 2. * k_b * nu**2 / c_l**2  # SI unit
                    jy_to_si = 1e-26
                    # print nu/1e9, beam_area, factor
                    factor2 = 1.
                    if scl100:
                        factor2 = 100.
                    if faxis == '3':
                        data[:,
                             i, :, :] *= jy_to_si / beam_area / factor * factor2
                    if faxis == '4':
                        data[
                            i, :, :, :] *= jy_to_si / beam_area / factor * factor2

        if verbose:
            print('point {}: {}'.format(prtidx, time.time() - t0))
            prtidx += 1

        hdu.flush()
        hdu.close()

        if verbose:
            print('point {}: {}'.format(prtidx, time.time() - t0))
            prtidx += 1
Exemple #11
0
def plt_qlook_image(imres, figdir=None, specdata=None, verbose=True, stokes='I,V', fov=None):
    from matplotlib import pyplot as plt
    from sunpy import map as smap
    from sunpy import sun
    import astropy.units as u
    if not figdir:
        figdir = './'

    observatory = 'EOVSA'
    polmap = {'RR': 0, 'LL': 1, 'I': 0, 'V': 1}
    pols = stokes.split(',')
    npols = len(pols)
    # SRL = set(['RR', 'LL'])
    # SXY = set(['XX', 'YY', 'XY', 'YX'])
    Spw = sorted(list(set(imres['Spw'])))
    nspw = len(Spw)
    # Freq = set(imres['Freq']) ## list is an unhashable type
    Freq = sorted(uniq(imres['Freq']))

    plttimes = list(set(imres['BeginTime']))
    ntime = len(plttimes)
    # sort the imres according to time
    images = np.array(imres['ImageName'])
    btimes = Time(imres['BeginTime'])
    etimes = Time(imres['EndTime'])
    spws = np.array(imres['Spw'])
    suc = np.array(imres['Succeeded'])
    inds = btimes.argsort()
    images_sort = images[inds].reshape(ntime, nspw)
    btimes_sort = btimes[inds].reshape(ntime, nspw)
    suc_sort = suc[inds].reshape(ntime, nspw)
    spws_sort = spws[inds].reshape(ntime, nspw)
    if verbose:
        print '{0:d} figures to plot'.format(ntime)
    plt.ioff()
    import matplotlib.gridspec as gridspec
    spec = specdata['spec']
    (npol, nbl, nfreq, ntim) = spec.shape
    tidx = range(ntim)
    fidx = range(nfreq)
    tim = specdata['tim']
    freq = specdata['freq']
    freqghz = freq / 1e9
    pol = ''.join(pols)
    spec_tim = Time(specdata['tim'] / 3600. / 24., format='mjd')
    timstrr = spec_tim.plot_date
    if npols == 1:
        if pol == 'RR':
            spec_plt = spec[0, 0, :, :]
        elif pol == 'LL':
            spec_plt = spec[1, 0, :, :]
        elif pol == 'I':
            spec_plt = (spec[0, 0, :, :] + spec[1, 0, :, :]) / 2.
        elif pol == 'V':
            spec_plt = (spec[0, 0, :, :] - spec[1, 0, :, :]) / 2.
        spec_plt = [spec_plt]
        print 'plot the dynamic spectrum in pol ' + pol  # ax1 = fig.add_subplot(211)

        hnspw = nspw / 2
        ncols = hnspw
        nrows = 2 + 2  # 1 image: 1x1, 1 dspec:2x4
        fig = plt.figure(figsize=(8, 8))
        gs = gridspec.GridSpec(nrows, ncols)
        axs = [plt.subplot(gs[0, 0])]
        for ll in range(1, nspw):
            axs.append(plt.subplot(gs[ll / hnspw, ll % hnspw], sharex=axs[0], sharey=axs[0]))
        for ll in range(nspw):
            axs.append(plt.subplot(gs[ll / hnspw + 2, ll % hnspw], sharex=axs[0], sharey=axs[0]))
        axs_dspec = [plt.subplot(gs[2:, :])]
        cmaps = ['jet']
    elif npols == 2:
        R_plot = np.absolute(spec[0, 0, :, :])
        L_plot = np.absolute(spec[1, 0, :, :])
        if pol == 'RRLL':
            spec_plt = [R_plot, L_plot]
            polstr = ['RR', 'LL']
            cmaps = ['jet'] * 2
        if pol == 'IV':
            I_plot = (R_plot + L_plot) / 2.
            V_plot = (R_plot - L_plot) / 2.
            spec_plt = [I_plot, V_plot]
            polstr = ['I', 'V']
            cmaps = ['jet', 'RdBu']
        print 'plot the dynamic spectrum in pol ' + pol

        hnspw = nspw / 2
        ncols = hnspw + 2  # 1 image: 1x1, 1 dspec:2x2
        nrows = 2 + 2
        fig = plt.figure(figsize=(12, 8))
        gs = gridspec.GridSpec(nrows, ncols)
        axs = [plt.subplot(gs[0, 0])]
        for ll in range(1, nspw):
            axs.append(plt.subplot(gs[ll / hnspw, ll % hnspw], sharex=axs[0], sharey=axs[0]))
        for ll in range(nspw):
            axs.append(plt.subplot(gs[ll / hnspw + 2, ll % hnspw], sharex=axs[0], sharey=axs[0]))
        axs_dspec = [plt.subplot(gs[:2, hnspw:])]
        axs_dspec.append(plt.subplot(gs[2:, hnspw:], sharex=axs_dspec[0], sharey=axs_dspec[0]))

    fig.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=0, hspace=0)
    timetext = fig.text(0.01, 0.98, '', color='w', fontweight='bold', fontsize=12, ha='left', va='top')
    for i in range(ntime):
        plt.ioff()
        # plt.clf()
        for ax in axs:
            ax.cla()
        plttime = btimes_sort[i, 0]
        # tofd = plttime.mjd - np.fix(plttime.mjd)
        suci = suc_sort[i]
        # if tofd < 16. / 24. or sum(
        #         suci) < nspw - 2:  # if time of the day is before 16 UT (and 24 UT), skip plotting (because the old antennas are not tracking)
        #     continue
        # fig=plt.figure(figsize=(9,6))
        # fig.suptitle('EOVSA @ '+plttime.iso[:19])
        timetext.set_text(plttime.iso[:19])
        if verbose:
            print 'Plotting image at: ', plttime.iso

        if i == 0:
            dspecvspans = []
            for pol in range(npols):
                ax = axs_dspec[pol]
                ax.pcolormesh(timstrr, freqghz, spec_plt[pol], cmap=cmaps[pol])
                ax.xaxis_date()
                ax.xaxis.set_major_formatter(DateFormatter("%H:%M:%S"))
                # plt.xticks(rotation=45)
                ax.set_xlim(timstrr[tidx[0]], timstrr[tidx[-1]])
                ax.set_ylim(freqghz[fidx[0]], freqghz[fidx[-1]])
                ax.set_xlabel('Time [UT]')
                ax.set_ylabel('Frequency [GHz]')
                for idx, freq in enumerate(Freq):
                    ax.axhspan(freq[0], freq[1], linestyle='dotted', edgecolor='w', alpha=0.7, facecolor='none')
                    xtext, ytext = ax.transAxes.inverted().transform(ax.transData.transform([timstrr[tidx[0]], np.mean(freq)]))
                    ax.text(xtext + 0.01, ytext, 'spw ' + Spw[idx], color='w', transform=ax.transAxes, fontweight='bold', ha='left', va='center',
                            fontsize=8, alpha=0.5)
                ax.text(0.01, 0.98, 'Stokes ' + pols[pol], color='w', transform=ax.transAxes, fontweight='bold', ha='left', va='top')
                dspecvspans.append(ax.axvspan(btimes[i].plot_date, etimes[i].plot_date, color='w', alpha=0.4))
                ax_pos = ax.get_position().extents
                x0, y0, x1, y1 = ax_pos
                h, v = x1 - x0, y1 - y0
                x0_new = x0 + 0.15 * h
                y0_new = y0 + 0.15 * v
                x1_new = x1 - 0.05 * h
                y1_new = y1 - 0.05 * v
                ax.set_position(mpl.transforms.Bbox([[x0_new, y0_new], [x1_new, y1_new]]))
        else:
            for pol in range(npols):
                xy = dspecvspans[pol].get_xy()
                xy[:, 0][np.array([0, 1, 4])] = btimes[i].plot_date
                xy[:, 0][np.array([2, 3])] = etimes[i].plot_date
                dspecvspans[pol].set_xy(xy)

        for n in range(nspw):
            image = images_sort[i, n]
            # fig.add_subplot(nspw/3, 3, n+1)
            # fig.add_subplot(2, nspw / 2, n + 1)
            for pol in range(npols):
                if suci[n]:
                    try:
                        eomap = smap.Map(image)
                    except:
                        continue
                    sz = eomap.data.shape
                    if len(sz) == 4:
                        eomap.data = eomap.data[min(polmap[pols[pol]], eomap.meta['naxis4'] - 1), 0, :, :].reshape((sz[2], sz[3]))
                    # resample the image for plotting
                    if fov is not None:
                        fov = [np.array(ll) for ll in fov]
                        pad = max(np.diff(fov[0])[0], np.diff(fov[1])[0])
                        eomap = eomap.submap((fov[0] + np.array([-1.0, 1.0]) * pad) * u.arcsec, (fov[1] + np.array([-1.0, 1.0]) * pad) * u.arcsec)
                    else:
                        dim = u.Quantity([256, 256], u.pixel)
                        eomap = eomap.resample(dim)
                    eomap.plot_settings['cmap'] = plt.get_cmap(cmaps[pol])
                    # import pdb
                    # pdb.set_trace()
                    eomap.plot(axes=axs[n + nspw * pol])
                    eomap.draw_limb()
                    eomap.draw_grid()
                    ax = plt.gca()
                    ax.set_autoscale_on(False)
                    if fov:
                        # pass
                        ax.set_xlim(fov[0])
                        ax.set_ylim(fov[1])
                    else:
                        ax.set_xlim([-1080, 1080])
                        ax.set_ylim([-1080, 1080])
                    spwran = spws_sort[i, n]
                    # freqran = [int(s) * 0.5 + 2.9 for s in spwran.split('~')]
                    # if len(freqran) == 1:
                    #     ax.text(0.98, 0.01, '{0:.1f} GHz'.format(freqran[0]), color='w',
                    #             transform=ax.transAxes, fontweight='bold', ha='right')
                    # else:
                    #     ax.text(0.98, 0.01, '{0:.1f} - {1:.1f} GHz'.format(freqran[0], freqran[1]), color='w',
                    #             transform=ax.transAxes, fontweight='bold', ha='right')
                    ax.text(0.98, 0.01, 'Stokes {1} @ {0:.3f} GHz'.format(eomap.meta['crval3'] / 1e9, pols[pol]), color='w', transform=ax.transAxes,
                            fontweight='bold', ha='right')
                    ax.set_title(' ')
                    # ax.set_title('spw '+spws_sort[i,n])
                    # ax.text(0.01,0.02, plttime.isot,transform=ax.transAxes,color='white')
                    ax.xaxis.set_visible(False)
                    ax.yaxis.set_visible(False)
                else:
                    # make an empty map
                    data = np.zeros((512, 512))
                    header = {"DATE-OBS": plttime.isot, "EXPTIME": 0., "CDELT1": 5., "NAXIS1": 512, "CRVAL1": 0., "CRPIX1": 257, "CUNIT1": "arcsec",
                              "CTYPE1": "HPLN-TAN", "CDELT2": 5., "NAXIS2": 512, "CRVAL2": 0., "CRPIX2": 257, "CUNIT2": "arcsec",
                              "CTYPE2": "HPLT-TAN", "HGLT_OBS": sun.heliographic_solar_center(plttime)[1].value, "HGLN_OBS": 0.,
                              "RSUN_OBS": sun.solar_semidiameter_angular_size(plttime).value, "RSUN_REF": sun.constants.radius.value,
                              "DSUN_OBS": sun.sunearth_distance(plttime).to(u.meter).value, }
                    eomap = smap.Map(data, header)
                    # resample the image for plotting
                    if fov:
                        fov = [np.array(ll) for ll in fov]
                        pad = max(np.diff(fov[0])[0], np.diff(fov[1])[0])
                        try:
                            eomap = eomap.submap((fov[0] + np.array([-1.0, 1.0]) * pad) * u.arcsec, (fov[1] + np.array([-1.0, 1.0]) * pad) * u.arcsec)
                        except:
                            x0, x1 = fov[0] + np.array([-1.0, 1.0]) * pad
                            y0, y1 = fov[1] + np.array([-1.0, 1.0]) * pad
                            bl = SkyCoord(x0 * u.arcsec, y0 * u.arcsec, frame=eomap.coordinate_frame)
                            tr = SkyCoord(x1 * u.arcsec, y1 * u.arcsec, frame=eomap.coordinate_frame)
                            eomap = eomap.submap(bl, tr)
                    else:
                        dim = u.Quantity([256, 256], u.pixel)
                        eomap = eomap.resample(dim)
                    eomap.plot_settings['cmap'] = plt.get_cmap(cmaps[pol])
                    eomap.plot(axes=axs[n + nspw * pol])
                    eomap.draw_limb()
                    eomap.draw_grid()
                    ax = plt.gca()
                    ax.set_autoscale_on(False)
                    if fov:
                        # pass
                        ax.set_xlim(fov[0])
                        ax.set_ylim(fov[1])
                    else:
                        ax.set_xlim([-1080, 1080])
                        ax.set_ylim([-1080, 1080])
                    # ax.set_title('spw '+spwran+'( )'))
                    spwran = spws_sort[i, n]
                    freqran = [int(s) * 0.5 + 2.9 for s in spwran.split('~')]
                    spwran = spws_sort[i, n]
                    # ax.set_title('{0:.1f} - {1:.1f} GHz'.format(freqran[0],freqran[1]))
                    # ax.text(0.98, 0.01, '{0:.1f} - {1:.1f} GHz'.format(freqran[0], freqran[1]), color='w',
                    #         transform=ax.transAxes, fontweight='bold', ha='right')
                    ax.text(0.98, 0.01, 'Stokes {1} @ {0:.3f} GHz'.format(0., pols[pol]), color='w', transform=ax.transAxes, fontweight='bold',
                            ha='right')
                    ax.set_title(' ')

                    # ax.text(0.01,0.02, plttime.isot,transform=ax.transAxes,color='white')
                    ax.xaxis.set_visible(False)
                    ax.yaxis.set_visible(False)
        figname = observatory + '_qlimg_' + plttime.isot.replace(':', '').replace('-', '')[:19] + '.png'
        fig_tdt = plttime.to_datetime()
        # fig_subdir = fig_tdt.strftime("%Y/%m/%d/")
        figdir_ = figdir  # + fig_subdir
        if not os.path.exists(figdir_):
            os.makedirs(figdir_)
        if verbose:
            print 'Saving plot to: ' + os.path.join(figdir_, figname)
        plt.savefig(os.path.join(figdir_, figname))
    plt.close(fig)
    DButil.img2html_movie(figdir_)

#track ID to plot
track_id = 12963
track_id = 12397
track_id = 14122
track_sp = 6840

fil = pd.read_pickle('filament_categories_hgs_mean_l.pic')

pfil = fil.loc[track_id, :]

#another track for the south pol
sfil = fil.loc[track_sp, :]

sr = sun.solar_semidiameter_angular_size()

r1 = plt.Circle((0, 0),
                radius=sr.value,
                color='lightgray',
                fill=True,
                linewidth=5,
                zorder=1)

fig, ax = plt.subplots(figsize=(10, 10), dpi=300)

#draw reference lines
draw_lines(sr, ax)

#plot all polygons
for j, i in enumerate(pfil['hpc_bbox'].values):
Exemple #13
0
    def plot_filament_track(self):
        """
        Function to create H alpha GONG plots with tracks overplotted

        plot_filament_tracks creates png files of GONG halpha data with all observed H alpha filament tracks visible on the sun at that time.
        The function can only be called after initialization of the halpha_plot object. 


        Parameters
        ----------
        self

        Returns
        -------
        H alpha with with tracks overplotted

        """

        #get start time of track for filename
        #        ofname = '{0}_track{1:6d}'.format(dat['event_starttime'][good[0]],i).replace(' ','0').replace(':','_')
        #replaced with named extension 2018/04/02 J. Prchlik
        self.ofile = self.ifile.split('/')[-1].replace('fits.fz', self.ext)
        try:
            sun = pyfits.open(self.ifile)
            # observed time of GONG halpha image
            self.stop = datetime.datetime.strptime(self.ofile[:-6],
                                                   '%Y%m%d%H%M%S')

            #Solar Halpha data
            sundat = sun[1].data
            #Set up image properties
            sc = self.dpi / 100.
            dpi = self.dpi
            #get image extent (i.e. physical coordinates)
            x0 = sun[1].header['CRVAL1'] - sun[1].header['CRPIX1']
            y0 = sun[1].header['CRVAL2'] - sun[1].header['CRPIX2']

            dx = 1.  #assumed approximate
            dy = 1.  #assumed approximate

            #Correct for Halpha images automatic scaling of solar radius to 900``
            #        try:
            #            asr = solar_semidiameter_angular_size(self.dat['event_starttime'].values[good[0]])
            #        except:
            #            asr = solar_semidiameter_angular_size(self.dat['event_starttime'].values[good])
            self.asr = solar_semidiameter_angular_size(
                self.stop.strftime('%Y/%m/%d %H:%M:%S'))

            #store the scale factor
            sf = self.asr.value / 900.

            sx, sy = np.shape(sundat)
            #get tracks visible on the surface using a given time frame
            good, = np.where((self.dat['total_event_start'] <= self.stop)
                             & (self.dat['total_event_end'] >= self.stop))

            #create figure and add sun
            self.fig, self.ax = plt.subplots(figsize=(sc * float(sx) / dpi,
                                                      sc * float(sy) / dpi),
                                             dpi=dpi)
            #set sun to fill entire range
            self.fig.subplots_adjust(left=0, bottom=0, right=1, top=1)
            #Turn off axis
            self.ax.set_axis_off()

            stat_max = 4300.
            stat_min = 75.
            self.ax.imshow(sundat,
                           cmap=plt.cm.gray,
                           extent=[
                               sf * x0, sf * (x0 + dx * sx), sf * y0,
                               sf * (y0 + dy * sy)
                           ],
                           origin='lower',
                           vmin=stat_min,
                           vmax=stat_max)
            #text offset
            poff = 0.01
            self.ax.text(sf * x0 + poff * sf * (dx * sx - x0),
                         sf * y0 + poff * sf * (dy * sy - y0),
                         sun[1].header['DATE-OBS'],
                         color='white',
                         fontsize=38,
                         fontweight='bold')
            #        rs = plt.Circle((0.,0.),radius=1000.,color='gray',fill=False,linewidth=5,zorder=0)
            #        ax.add_patch(rs)
            if self.lref: self.draw_lines()

            #remove identifying plot
            ########        #plot track polygons for given id
            ########            for j in good:
            ########                inc = 'red'
            ########                if self.dat['obs_observatory'].values[j] == 'HA2': inc='blue'
            ########                poly = plt.Polygon(loads(self.dat['hpc_bbox'].values[j]).exterior,color=inc,linewidth=0.5,fill=None)
            ########                self.ax.add_patch(poly)
            ########                xx, yy = self.calc_poly_values(self.dat['hpc_bbox'].values[j])
            ########                self.ax.text(np.mean(xx),np.max(yy),self.dat['track_id'].values[j],alpha=.5,color=inc)
            ########
            #list of track ids
            ltid = np.unique(self.dat['track_id'].values[good])

            #loop over track ids to find the closest rotational track
            for tid in ltid:
                #over plot rotation track
                idmatch, = np.where(self.dat['track_id'].values == tid)
                td = np.abs(self.dat['event_starttime_dt'][idmatch] -
                            self.stop)
                nearest, = np.where(td == td.min())
                roplot = idmatch[nearest]
                ####  if idmatch.size < -100:
                #####array of time differences between obs and filament track
                ####      td = np.abs(self.dat['event_starttime_dt'][idmatch]-self.stop)
                ####      nearest, = np.where(td == td.min())
                ####      roplot = idmatch[nearest]#[0] #nearest filament trace in time
                ####  else:
                ####      roplot = idmatch[0]

                roplot = roplot.tolist()
                #plot rotation of nearest filament placement
                #fix hpc_bbox to hpc_boundcc because columns used to be off in Dustin's file
                for k in roplot:
                    self.plot_rotation(self.dat['event_starttime_dt'][k],
                                       self.dat['hpc_boundcc'].values[k],
                                       color='teal',
                                       ids=self.dat['track_id'].values[k])

        #Setup plots

    #        ticks = [-1000.,-500.,0.,500.,1000.]
            lim = [sf * x0, sf * (x0 + sx * dx)]
            self.ax.set_xlim(lim)
            self.ax.set_ylim(lim)

            #Add AIA plot 2018/05/02 J. Prchlik
            if self.add_aia: self.add_aia_image()

            #remove axis labels just make an image
            #        self.ax.set_xticks(ticks)
            #        self.ax.set_yticks(ticks)
            #        self.ax.set_xlabel('Solar X [arcsec]')
            #        self.ax.set_ylabel('Solar Y [arcsec]')

            #save fig
            self.fig.savefig(self.pdir + self.ofile, bbox_inches=0, dpi=dpi)
            self.fig.clear()
            plt.close()

        except:
            print 'Unable to create image'
            print sys.exc_info()
Exemple #14
0
def plt_qlook_image(imres, figdir=None, verbose=True):
    from matplotlib import pyplot as plt
    from sunpy import map as smap
    from sunpy import sun
    import astropy.units as u
    if not figdir:
        figdir = './'
    nspw = len(set(imres['Spw']))
    plttimes = list(set(imres['BeginTime']))
    ntime = len(plttimes)
    # sort the imres according to time
    images = np.array(imres['ImageName'])
    btimes = Time(imres['BeginTime'])
    etimes = Time(imres['EndTime'])
    spws = np.array(imres['Spw'])
    suc = np.array(imres['Succeeded'])
    inds = btimes.argsort()
    images_sort = images[inds].reshape(ntime, nspw)
    btimes_sort = btimes[inds].reshape(ntime, nspw)
    suc_sort = suc[inds].reshape(ntime, nspw)
    spws_sort = spws[inds].reshape(ntime, nspw)
    if verbose:
        print '{0:d} figures to plot'.format(ntime)
    for i in range(ntime):
        #for i in range(1):
        plt.ioff()
        fig = plt.figure(figsize=(11, 6))
        plttime = btimes_sort[i, 0]
        fig.suptitle('EOVSA @ ' + plttime.iso[:19])
        if verbose:
            print 'Plotting image at: ', plttime.iso
            suci = suc_sort[i]
        for n in range(nspw):
            plt.ioff()
            image = images_sort[i, n]
            fig.add_subplot(nspw / 3, 3, n + 1)
            if suci[n]:
                try:
                    eomap = smap.Map(image)
                except:
                    continue
                sz = eomap.data.shape
                if len(sz) == 4:
                    eomap.data = eomap.data.reshape((sz[2], sz[3]))
                eomap.plot_settings['cmap'] = plt.get_cmap('jet')
                eomap.plot()
                eomap.draw_limb()
                eomap.draw_grid()
                ax = plt.gca()
                ax.set_xlim([-1050, 1050])
                ax.set_ylim([-1050, 1050])
                ax.set_title('spw ' + spws_sort[i, n])
                #ax.text(0.01,0.02, plttime.isot,transform=ax.transAxes,color='white')
                if n != nspw - 3:
                    ax.set_xlabel('')
                    ax.set_ylabel('')
                    ax.set_xticklabels([''])
                    ax.set_yticklabels([''])
            else:
                #make an empty map
                data = np.zeros((512, 512))
                header = {
                    "DATE-OBS": plttime.isot,
                    "EXPTIME": 0.,
                    "CDELT1": 5.,
                    "NAXIS1": 512,
                    "CRVAL1": 0.,
                    "CRPIX1": 257,
                    "CUNIT1": "arcsec",
                    "CTYPE1": "HPLN-TAN",
                    "CDELT2": 5.,
                    "NAXIS2": 512,
                    "CRVAL2": 0.,
                    "CRPIX2": 257,
                    "CUNIT2": "arcsec",
                    "CTYPE2": "HPLT-TAN",
                    "HGLT_OBS":
                    sun.heliographic_solar_center(plttime)[1].value,
                    "HGLN_OBS": 0.,
                    "RSUN_OBS":
                    sun.solar_semidiameter_angular_size(plttime).value,
                    "RSUN_REF": sun.constants.radius.value,
                    "DSUN_OBS":
                    sun.sunearth_distance(plttime).to(u.meter).value,
                }
                eomap = smap.Map(data, header)
                eomap.plot_settings['cmap'] = plt.get_cmap('jet')
                eomap.plot()
                eomap.draw_limb()
                eomap.draw_grid()
                ax = plt.gca()
                ax.set_xlim([-1050, 1050])
                ax.set_ylim([-1050, 1050])
                ax.set_title('spw ' + spws_sort[i, n])
                #ax.text(0.01,0.02, plttime.isot,transform=ax.transAxes,color='white')
                if n != 6:
                    ax.set_xlabel('')
                    ax.set_ylabel('')
                    ax.set_xticklabels([''])
                    ax.set_yticklabels([''])
        figname = 'eovsa_qlimg_' + plttime.isot.replace(':', '').replace(
            '-', '')[:15] + '.png'
        fig_tdt = plttime.to_datetime()
        fig_subdir = fig_tdt.strftime("%Y/%m/%d/")
        figdir_ = figdir + fig_subdir
        if not os.path.exists(figdir_):
            os.makedirs(figdir_)
        if verbose:
            print 'Saving plot to :' + figdir_ + figname
        plt.savefig(figdir_ + figname)
        plt.close(fig)
Exemple #15
0
#get where pandas dataframe equals track id
    track, = np.where(dat['track_id'].values == i)

    #which element to grab from track
    for k in track:

        t1str = dat['event_starttime_dt'].values[k]

        #grab data from first element in track
        t132b = datetime.utcfromtimestamp(t1str.tolist() / 1e9)
        t1posx, t1posy = calc_poly_values(dat['hpc_bbox'].values[k])
        t1meanx = dat['meanx'].values[k]
        t1meany = dat['meany'].values[k]

        maxr = solar_semidiameter_angular_size(
            t132b).value - 10.  #10 arcsec of the limb

        curr = np.sqrt(t1meanx**2. + t1meany**2.)
        p = 1

        #find when filament goes over the limb
        while curr < maxr:
            maxt = t132b + timedelta(minutes=20 * p)
            #remove deprecated fucntion J. Prchlik 2017/11/03
            #curx, cury =  solar_rotation.rot_hpc(t1meanx*u.arcsec,t1meany*u.arcsec,t132b,maxt,rot_type=rot_type) #current position
            curx, cury = rot_hpc(t1meanx * u.arcsec,
                                 t1meany * u.arcsec,
                                 t132b,
                                 maxt,
                                 rot_type=rot_type)  #current position