Exemple #1
0
    def moon_radec(self, mjd=None):
        """Return (ra, dec) in deg J2000 for Moon at MJD (days)

        Parameters:
        ----------

        mjd : np.float64
            Modified Julian Day (days)

        Returns:
        -------

        ra : np.float64
            right ascension, J2000 (deg)

        dec : np.float64
            declination, J2000 (deg)
        """
        jd = self._mjd2jd(mjd=self._arrayify(mjd))
        ra, dec, dist, geolon, geolat = pyasl.moonpos(jd)
        return (ra, dec)
def VisibilityPlot(date=None,
                   targets=None,
                   observatory=None,
                   plotLegend=True,
                   showMoonDist=True,
                   print2file=False,
                   remove_watermark=False):
    """
    Plot the visibility of target.

    Parameters
    ----------
    date: datetime
        The date for which to calculate the visibility.
    targets: list
        List of targets.
        Each target should be a dictionary with keys 'name' and 'coord'.
        The key 'name' is aa string, 'coord' is a SkyCoord object.
    observatory: string
        Name of the observatory that pyasl.observatory can resolve.
        Basically, any of pyasl.listObservatories().keys()
    plotLegend: boolean, optional
        If True (default), show a legend.
    showMoonDist : boolean, optional
        If True (default), the Moon distance will be shown.
  """

    from mpl_toolkits.axes_grid1 import host_subplot
    from matplotlib.ticker import MultipleLocator
    from matplotlib.font_manager import FontProperties
    from matplotlib import rcParams
    rcParams['xtick.major.pad'] = 12

    if isinstance(observatory, dict):
        obs = observatory
    else:
        obs = pyasl.observatory(observatory)

    # observer = ephem.Observer()
    # observer.pressure = 0
    # observer.horizon = '-0:34'
    # observer.lat, observer.lon = obs['latitude'], obs['longitude']
    # observer.date = date
    # print(observer.date)
    # print(observer.previous_rising(ephem.Sun()))
    # print(observer.next_setting(ephem.Sun()))
    # print(observer.previous_rising(ephem.Moon()))
    # print(observer.next_setting(ephem.Moon()))
    # observer.horizon = '-6'
    # noon = observer.next_transit(ephem.Sun())
    # print(noon)
    # print(observer.previous_rising(ephem.Sun(), start=noon, use_center=True))
    # print()

    fig = plt.figure(figsize=(15, 10))
    fig.subplots_adjust(left=0.07, right=0.8, bottom=0.15, top=0.88)

    # watermak
    if not remove_watermark:
        fig.text(0.99,
                 0.99,
                 'Created with\ngithub.com/iastro-pt/ObservationTools',
                 fontsize=10,
                 color='gray',
                 ha='right',
                 va='top',
                 alpha=0.5)

    ax = host_subplot(111)

    font0 = FontProperties()
    font1 = font0.copy()
    font0.set_family('sans-serif')
    font0.set_weight('light')
    font1.set_family('sans-serif')
    font1.set_weight('medium')

    for n, target in enumerate(targets):

        target_coord = target['coord']
        target_ra = target_coord.ra.deg
        target_dec = target_coord.dec.deg

        # JD array
        jdbinsize = 1.0 / 24. / 20.
        # jds = np.arange(allData[n]["Obs jd"][0], allData[n]["Obs jd"][2], jdbinsize)
        jd = pyasl.jdcnv(date)
        jd_start = pyasl.jdcnv(date) - 0.5
        jd_end = pyasl.jdcnv(date) + 0.5
        jds = np.arange(jd_start, jd_end, jdbinsize)
        # Get JD floating point
        jdsub = jds - np.floor(jds[0])
        # Get alt/az of object
        altaz = pyasl.eq2hor(jds, np.ones(jds.size)*target_ra, np.ones(jds.size)*target_dec, \
                            lon=obs['longitude'], lat=obs['latitude'], alt=obs['altitude'])
        # Get alt/az of Sun
        sun_position = pyasl.sunpos(jd)
        sun_ra, sun_dec = sun_position[1], sun_position[2]
        sunpos_altaz = pyasl.eq2hor(jds, np.ones(jds.size)*sun_ra, np.ones(jds.size)*sun_dec, \
                                    lon=obs['longitude'], lat=obs['latitude'], alt=obs['altitude'])

        # Define plot label
        plabel = "[{0:2d}]  {1!s}".format(n + 1, target['name'])

        # Find periods of: day, twilight, and night
        day = np.where(sunpos_altaz[0] >= 0.)[0]
        twi = np.where(
            np.logical_and(sunpos_altaz[0] > -18., sunpos_altaz[0] < 0.))[0]
        night = np.where(sunpos_altaz[0] <= -18.)[0]

        if (len(day) == 0) and (len(twi) == 0) and (len(night) == 0):
            print
            print("VisibilityPlot - no points to draw")
            print

        mpos = pyasl.moonpos(jds)
        # mpha = pyasl.moonphase(jds)
        # mpos_altaz = pyasl.eq2hor(jds, mpos[0], mpos[1],
        #                            lon=obs['longitude'], lat=obs['latitude'], alt=obs['altitude'])
        # moonind = np.where( mpos_altaz[0] > 0. )[0]

        if showMoonDist:
            mdist = pyasl.getAngDist(mpos[0], mpos[1], np.ones(jds.size)*target_ra, \
                                    np.ones(jds.size)*target_dec)
            bindist = int((2.0 / 24.) / jdbinsize)
            firstbin = np.random.randint(0, bindist)
            for mp in range(0, int(len(jds) / bindist)):
                bind = firstbin + mp * bindist
                if altaz[0][bind] - 1. < 5.: continue
                ax.text(jdsub[bind], altaz[0][bind]-1., str(int(mdist[bind]))+r"$^\circ$", ha="center", va="top", \
                        fontsize=8, stretch='ultra-condensed', fontproperties=font0, alpha=1.)

        if len(twi) > 1:
            # There are points in twilight
            linebreak = np.where(
                (jdsub[twi][1:] - jdsub[twi][:-1]) > 2.0 * jdbinsize)[0]
            if len(linebreak) > 0:
                plotrjd = np.insert(jdsub[twi], linebreak + 1, np.nan)
                plotdat = np.insert(altaz[0][twi], linebreak + 1, np.nan)
                ax.plot(plotrjd, plotdat, "-", color='#BEBEBE', linewidth=1.5)
            else:
                ax.plot(jdsub[twi],
                        altaz[0][twi],
                        "-",
                        color='#BEBEBE',
                        linewidth=1.5)

        ax.plot(jdsub[night], altaz[0][night], '.k', label=plabel)
        ax.plot(jdsub[day], altaz[0][day], '.', color='#FDB813')

        altmax = np.argmax(altaz[0])
        ax.text( jdsub[altmax], altaz[0][altmax], str(n+1), color="b", fontsize=14, \
                 fontproperties=font1, va="bottom", ha="center")

        if n + 1 == 29:
            ax.text( 1.1, 1.0-float(n+1)*0.04, "too many targets", ha="left", va="top", transform=ax.transAxes, \
                    fontsize=10, fontproperties=font0, color="r")
        else:
            ax.text( 1.1, 1.0-float(n+1)*0.04, plabel, ha="left", va="top", transform=ax.transAxes, \
                    fontsize=12, fontproperties=font0, color="b")

    ax.text( 1.1, 1.03, "List of targets", ha="left", va="top", transform=ax.transAxes, \
            fontsize=12, fontproperties=font0, color="b")

    axrange = ax.get_xlim()
    ax.set_xlabel("UT [hours]")

    if axrange[1] - axrange[0] <= 1.0:
        jdhours = np.arange(0, 3, 1.0 / 24.)
        utchours = (np.arange(0, 72, dtype=int) + 12) % 24
    else:
        jdhours = np.arange(0, 3, 1.0 / 12.)
        utchours = (np.arange(0, 72, 2, dtype=int) + 12) % 24
    ax.set_xticks(jdhours)
    ax.set_xlim(axrange)
    ax.set_xticklabels(utchours, fontsize=18)

    # Make ax2 responsible for "top" axis and "right" axis
    ax2 = ax.twin()
    # Set upper x ticks
    ax2.set_xticks(jdhours)
    ax2.set_xticklabels(utchours, fontsize=18)
    ax2.set_xlabel("UT [hours]")

    # Horizon angle for airmass
    airmass_ang = np.arange(5., 90., 5.)
    geo_airmass = pyasl.airmass.airmassPP(90. - airmass_ang)
    ax2.set_yticks(airmass_ang)
    airmassformat = []
    for t in range(geo_airmass.size):
        airmassformat.append("{0:2.2f}".format(geo_airmass[t]))
    ax2.set_yticklabels(airmassformat, rotation=90)
    ax2.set_ylabel("Relative airmass", labelpad=32)
    ax2.tick_params(axis="y", pad=10, labelsize=10)
    plt.text(1.015,-0.04, "Plane-parallel", transform=ax.transAxes, ha='left', \
             va='top', fontsize=10, rotation=90)

    ax22 = ax.twin()
    ax22.set_xticklabels([])
    ax22.set_frame_on(True)
    ax22.patch.set_visible(False)
    ax22.yaxis.set_ticks_position('right')
    ax22.yaxis.set_label_position('right')
    ax22.spines['right'].set_position(('outward', 25))
    ax22.spines['right'].set_color('k')
    ax22.spines['right'].set_visible(True)
    airmass2 = list(
        map(
            lambda ang: pyasl.airmass.airmassSpherical(90. - ang, obs[
                'altitude']), airmass_ang))
    ax22.set_yticks(airmass_ang)
    airmassformat = []
    for t in airmass2:
        airmassformat.append("{0:2.2f}".format(t))
    ax22.set_yticklabels(airmassformat, rotation=90)
    ax22.tick_params(axis="y", pad=10, labelsize=10)
    plt.text(1.045,-0.04, "Spherical+Alt", transform=ax.transAxes, ha='left', va='top', \
             fontsize=10, rotation=90)

    ax3 = ax.twiny()
    ax3.set_frame_on(True)
    ax3.patch.set_visible(False)
    ax3.xaxis.set_ticks_position('bottom')
    ax3.xaxis.set_label_position('bottom')
    ax3.spines['bottom'].set_position(('outward', 50))
    ax3.spines['bottom'].set_color('k')
    ax3.spines['bottom'].set_visible(True)

    ltime, ldiff = pyasl.localtime.localTime(
        utchours, np.repeat(obs['longitude'], len(utchours)))
    jdltime = jdhours - ldiff / 24.
    ax3.set_xticks(jdltime)
    ax3.set_xticklabels(utchours)
    ax3.set_xlim([axrange[0], axrange[1]])
    ax3.set_xlabel("Local time [hours]")

    ax.set_ylim([0, 91])
    ax.yaxis.set_major_locator(MultipleLocator(15))
    ax.yaxis.set_minor_locator(MultipleLocator(5))
    yticks = ax.get_yticks()
    ytickformat = []
    for t in range(yticks.size):
        ytickformat.append(str(int(yticks[t])) + r"$^\circ$")
    ax.set_yticklabels(ytickformat, fontsize=16)
    ax.set_ylabel("Altitude", fontsize=18)
    yticksminor = ax.get_yticks(minor=True)
    ymind = np.where(yticksminor % 15. != 0.)[0]
    yticksminor = yticksminor[ymind]
    ax.set_yticks(yticksminor, minor=True)
    m_ytickformat = []
    for t in range(yticksminor.size):
        m_ytickformat.append(str(int(yticksminor[t])) + r"$^\circ$")
    ax.set_yticklabels(m_ytickformat, minor=True)
    ax.set_ylim([0, 91])

    ax.yaxis.grid(color='gray', linestyle='dashed')
    ax.yaxis.grid(color='gray', which="minor", linestyle='dotted')
    ax2.xaxis.grid(color='gray', linestyle='dotted')

    plt.text(0.5,0.95,"Visibility on {0!s}".format(date.date()), \
             transform=fig.transFigure, ha='center', va='bottom', fontsize=20)

    if plotLegend:
        line1 = matplotlib.lines.Line2D((0, 0), (1, 1),
                                        color='#FDB813',
                                        linestyle="-",
                                        linewidth=2)
        line2 = matplotlib.lines.Line2D((0, 0), (1, 1),
                                        color='#BEBEBE',
                                        linestyle="-",
                                        linewidth=2)
        line3 = matplotlib.lines.Line2D((0, 0), (1, 1),
                                        color='k',
                                        linestyle="-",
                                        linewidth=2)

        lgd2 = plt.legend((line1,line2,line3),("day","twilight","night",), \
                            bbox_to_anchor=(0.88, 0.13), loc='best', borderaxespad=0.,prop={'size':12}, fancybox=True)
        lgd2.get_frame().set_alpha(.5)

    obsco = "Obs coord.: {0:8.4f}$^\circ$, {1:8.4f}$^\circ$, {2:4f} m".format(
        obs['longitude'], obs['latitude'], obs['altitude'])

    plt.text(0.01,
             0.97,
             obsco,
             transform=fig.transFigure,
             ha='left',
             va='center',
             fontsize=10)
    plt.text(0.01,
             0.95,
             obs['name'],
             transform=fig.transFigure,
             ha='left',
             va='center',
             fontsize=10)

    return fig
Exemple #3
0
def moonphase2(jd):
    """
    Computes the illuminated fraction of the Moon at given Julian date(s).
    
    Parameters
    ----------
    jd : float or array
         The Julian date.
         
    Returns
    -------
    Fraction : float or array
        The illuminated fraction [0 - 1] of the Moon.
        Has the same size as `jd`.

    Notes
    -----
    
    .. note:: This function was ported from the IDL Astronomy User's Library.

    :IDL - Documentation:  
    
    NAME:
          MPHASE
    PURPOSE:
          Return the illuminated fraction of the Moon at given Julian date(s) 
    
    CALLING SEQUENCE:
          MPHASE, jd, k
    INPUT:
          JD - Julian date, scalar or vector, double precision recommended
    OUTPUT:
          k - illuminated fraction of Moon's disk (0.0 < k < 1.0), same number
              of elements as jd.   k = 0 indicates a new moon, while k = 1 for
              a full moon.
    EXAMPLE:
          Plot the illuminated fraction of the moon for every day in July 
          1996 at 0 TD (~Greenwich noon).
    
          IDL> jdcnv, 1996, 7, 1, 0, jd         ;Get Julian date of July 1
          IDL> mphase, jd+dindgen(31), k        ;Moon phase for all 31 days
          IDL> plot, indgen(31),k               ;Plot phase vs. July day number
  """

    jd = np.array(jd, ndmin=1)

    # Earth-Sun distance (1 AU)
    edist = 1.49598e8

    mpos = moonpos(jd)
    ram = mpos[0] * np.pi / 180.
    decm = mpos[1] * np.pi / 180.
    dism = mpos[2]

    spos = sunpos2(jd)
    ras = spos[1] * np.pi / 180.
    decs = spos[2] * np.pi / 180.

    phi = np.arccos(
        np.sin(decs) * np.sin(decm) +
        np.cos(decs) * np.cos(decm) * np.cos(ras - ram))
    inc = np.arctan2(edist * np.sin(phi), dism - edist * np.cos(phi))
    k = (1 + np.cos(inc)) / 2.

    return np.ravel(k)
def VisibilityPlot(date=None, targets=None, observatory=None, plotLegend=True, 
                   showMoonDist=True, print2file=False, remove_watermark=False):
  """
    Plot the visibility of target.

    Parameters
    ----------
    date: datetime
        The date for which to calculate the visibility.
    targets: list
        List of targets.
        Each target should be a dictionary with keys 'name' and 'coord'.
        The key 'name' is aa string, 'coord' is a SkyCoord object.
    observatory: string
        Name of the observatory that pyasl.observatory can resolve.
        Basically, any of pyasl.listObservatories().keys()
    plotLegend: boolean, optional
        If True (default), show a legend.
    showMoonDist : boolean, optional
        If True (default), the Moon distance will be shown.
  """

  from mpl_toolkits.axes_grid1 import host_subplot
  from matplotlib.ticker import MultipleLocator
  from matplotlib.font_manager import FontProperties
  from matplotlib import rcParams
  rcParams['xtick.major.pad'] = 12


  if isinstance(observatory, dict):
    obs = observatory
  else:
    obs = pyasl.observatory(observatory)

  # observer = ephem.Observer()
  # observer.pressure = 0
  # observer.horizon = '-0:34'
  # observer.lat, observer.lon = obs['latitude'], obs['longitude']
  # observer.date = date
  # print(observer.date)
  # print(observer.previous_rising(ephem.Sun()))
  # print(observer.next_setting(ephem.Sun()))
  # print(observer.previous_rising(ephem.Moon()))
  # print(observer.next_setting(ephem.Moon()))
  # observer.horizon = '-6'
  # noon = observer.next_transit(ephem.Sun())
  # print(noon)
  # print(observer.previous_rising(ephem.Sun(), start=noon, use_center=True))
  # print()


  fig = plt.figure(figsize=(15,10))
  fig.subplots_adjust(left=0.07, right=0.8, bottom=0.15, top=0.88)

  # watermak
  if not remove_watermark:
    fig.text(0.99, 0.99, 'Created with\ngithub.com/iastro-pt/ObservationTools',
            fontsize=10, color='gray',
            ha='right', va='top', alpha=0.5)

  ax = host_subplot(111)

  font0 = FontProperties()
  font1 = font0.copy()
  font0.set_family('sans-serif')
  font0.set_weight('light')
  font1.set_family('sans-serif')
  font1.set_weight('medium')


  for n, target in enumerate(targets):

    target_coord = target['coord']
    target_ra = target_coord.ra.deg
    target_dec = target_coord.dec.deg

    # JD array
    jdbinsize = 1.0/24./20.
    # jds = np.arange(allData[n]["Obs jd"][0], allData[n]["Obs jd"][2], jdbinsize)
    jd = pyasl.jdcnv(date)
    jd_start = pyasl.jdcnv(date)-0.5
    jd_end = pyasl.jdcnv(date)+0.5
    jds = np.arange(jd_start, jd_end, jdbinsize)
    # Get JD floating point
    jdsub = jds - np.floor(jds[0])
    # Get alt/az of object
    altaz = pyasl.eq2hor(jds, np.ones(jds.size)*target_ra, np.ones(jds.size)*target_dec, \
                        lon=obs['longitude'], lat=obs['latitude'], alt=obs['altitude'])
    # Get alt/az of Sun
    sun_position = pyasl.sunpos(jd)
    sun_ra, sun_dec = sun_position[1], sun_position[2]
    sunpos_altaz = pyasl.eq2hor(jds, np.ones(jds.size)*sun_ra, np.ones(jds.size)*sun_dec, \
                                lon=obs['longitude'], lat=obs['latitude'], alt=obs['altitude'])

    # Define plot label
    plabel = "[{0:2d}]  {1!s}".format(n+1, target['name'])

    # Find periods of: day, twilight, and night
    day = np.where( sunpos_altaz[0] >= 0. )[0]
    twi = np.where( np.logical_and(sunpos_altaz[0] > -18., sunpos_altaz[0] < 0.) )[0]
    night = np.where( sunpos_altaz[0] <= -18. )[0]

    if (len(day) == 0) and (len(twi) == 0) and (len(night) == 0):
      print
      print("VisibilityPlot - no points to draw")
      print

    mpos = pyasl.moonpos(jds)
    # mpha = pyasl.moonphase(jds)
    # mpos_altaz = pyasl.eq2hor(jds, mpos[0], mpos[1],
    #                            lon=obs['longitude'], lat=obs['latitude'], alt=obs['altitude'])
    # moonind = np.where( mpos_altaz[0] > 0. )[0]

    if showMoonDist:
      mdist = pyasl.getAngDist(mpos[0], mpos[1], np.ones(jds.size)*target_ra, \
                              np.ones(jds.size)*target_dec)
      bindist = int((2.0/24.)/jdbinsize)
      firstbin = np.random.randint(0,bindist)
      for mp in range(0, int(len(jds)/bindist)):
        bind = firstbin+mp*bindist
        if altaz[0][bind]-1. < 5.: continue
        ax.text(jdsub[bind], altaz[0][bind]-1., str(int(mdist[bind]))+r"$^\circ$", ha="center", va="top", \
                fontsize=8, stretch='ultra-condensed', fontproperties=font0, alpha=1.)


    if len(twi) > 1:
      # There are points in twilight
      linebreak = np.where( (jdsub[twi][1:]-jdsub[twi][:-1]) > 2.0*jdbinsize)[0]
      if len(linebreak) > 0:
        plotrjd = np.insert(jdsub[twi], linebreak+1, np.nan)
        plotdat = np.insert(altaz[0][twi], linebreak+1, np.nan)
        ax.plot( plotrjd, plotdat, "-", color='#BEBEBE', linewidth=1.5)
      else:
        ax.plot( jdsub[twi], altaz[0][twi], "-", color='#BEBEBE', linewidth=1.5)

    ax.plot( jdsub[night], altaz[0][night], '.k', label=plabel)
    ax.plot( jdsub[day], altaz[0][day], '.', color='#FDB813')

    altmax = np.argmax(altaz[0])
    ax.text( jdsub[altmax], altaz[0][altmax], str(n+1), color="b", fontsize=14, \
             fontproperties=font1, va="bottom", ha="center")

    if n+1 == 29:
      ax.text( 1.1, 1.0-float(n+1)*0.04, "too many targets", ha="left", va="top", transform=ax.transAxes, \
              fontsize=10, fontproperties=font0, color="r")
    else:
      ax.text( 1.1, 1.0-float(n+1)*0.04, plabel, ha="left", va="top", transform=ax.transAxes, \
              fontsize=12, fontproperties=font0, color="b")

  ax.text( 1.1, 1.03, "List of targets", ha="left", va="top", transform=ax.transAxes, \
          fontsize=12, fontproperties=font0, color="b")

  axrange = ax.get_xlim()
  ax.set_xlabel("UT [hours]")

  if axrange[1]-axrange[0] <= 1.0:
    jdhours = np.arange(0,3,1.0/24.)
    utchours = (np.arange(0,72,dtype=int)+12)%24
  else:
    jdhours = np.arange(0,3,1.0/12.)
    utchours = (np.arange(0,72, 2, dtype=int)+12)%24
  ax.set_xticks(jdhours)
  ax.set_xlim(axrange)
  ax.set_xticklabels(utchours, fontsize=18)

  # Make ax2 responsible for "top" axis and "right" axis
  ax2 = ax.twin()
  # Set upper x ticks
  ax2.set_xticks(jdhours)
  ax2.set_xticklabels(utchours, fontsize=18)
  ax2.set_xlabel("UT [hours]")

  # Horizon angle for airmass
  airmass_ang = np.arange(5.,90.,5.)
  geo_airmass = pyasl.airmass.airmassPP(90.-airmass_ang)
  ax2.set_yticks(airmass_ang)
  airmassformat = []
  for t in range(geo_airmass.size):
    airmassformat.append("{0:2.2f}".format(geo_airmass[t]))
  ax2.set_yticklabels(airmassformat, rotation=90)
  ax2.set_ylabel("Relative airmass", labelpad=32)
  ax2.tick_params(axis="y", pad=10, labelsize=10)
  plt.text(1.015,-0.04, "Plane-parallel", transform=ax.transAxes, ha='left', \
           va='top', fontsize=10, rotation=90)

  ax22 = ax.twin()
  ax22.set_xticklabels([])
  ax22.set_frame_on(True)
  ax22.patch.set_visible(False)
  ax22.yaxis.set_ticks_position('right')
  ax22.yaxis.set_label_position('right')
  ax22.spines['right'].set_position(('outward', 25))
  ax22.spines['right'].set_color('k')
  ax22.spines['right'].set_visible(True)
  airmass2 = list(map(lambda ang: pyasl.airmass.airmassSpherical(90. - ang, obs['altitude']), airmass_ang))
  ax22.set_yticks(airmass_ang)
  airmassformat = []
  for t in airmass2:
      airmassformat.append("{0:2.2f}".format(t))
  ax22.set_yticklabels(airmassformat, rotation=90)
  ax22.tick_params(axis="y", pad=10, labelsize=10)
  plt.text(1.045,-0.04, "Spherical+Alt", transform=ax.transAxes, ha='left', va='top', \
           fontsize=10, rotation=90)

  ax3 = ax.twiny()
  ax3.set_frame_on(True)
  ax3.patch.set_visible(False)
  ax3.xaxis.set_ticks_position('bottom')
  ax3.xaxis.set_label_position('bottom')
  ax3.spines['bottom'].set_position(('outward', 50))
  ax3.spines['bottom'].set_color('k')
  ax3.spines['bottom'].set_visible(True)

  ltime, ldiff = pyasl.localtime.localTime(utchours, np.repeat(obs['longitude'], len(utchours)))
  jdltime = jdhours - ldiff/24.
  ax3.set_xticks(jdltime)
  ax3.set_xticklabels(utchours)
  ax3.set_xlim([axrange[0],axrange[1]])
  ax3.set_xlabel("Local time [hours]")

  ax.set_ylim([0, 91])
  ax.yaxis.set_major_locator(MultipleLocator(15))
  ax.yaxis.set_minor_locator(MultipleLocator(5))
  yticks = ax.get_yticks()
  ytickformat = []
  for t in range(yticks.size): ytickformat.append(str(int(yticks[t]))+r"$^\circ$")
  ax.set_yticklabels(ytickformat, fontsize=16)
  ax.set_ylabel("Altitude", fontsize=18)
  yticksminor = ax.get_yticks(minor=True)
  ymind = np.where( yticksminor % 15. != 0. )[0]
  yticksminor = yticksminor[ymind]
  ax.set_yticks(yticksminor, minor=True)
  m_ytickformat = []
  for t in range(yticksminor.size): m_ytickformat.append(str(int(yticksminor[t]))+r"$^\circ$")
  ax.set_yticklabels(m_ytickformat, minor=True)
  ax.set_ylim([0, 91])

  ax.yaxis.grid(color='gray', linestyle='dashed')
  ax.yaxis.grid(color='gray', which="minor", linestyle='dotted')
  ax2.xaxis.grid(color='gray', linestyle='dotted')

  plt.text(0.5,0.95,"Visibility on {0!s}".format(date.date()), \
           transform=fig.transFigure, ha='center', va='bottom', fontsize=20)

  if plotLegend:
    line1 = matplotlib.lines.Line2D((0,0),(1,1), color='#FDB813', linestyle="-", linewidth=2)
    line2 = matplotlib.lines.Line2D((0,0),(1,1), color='#BEBEBE', linestyle="-", linewidth=2)
    line3 = matplotlib.lines.Line2D((0,0),(1,1), color='k', linestyle="-", linewidth=2)

    lgd2 = plt.legend((line1,line2,line3),("day","twilight","night",), \
                        bbox_to_anchor=(0.88, 0.13), loc='best', borderaxespad=0.,prop={'size':12}, fancybox=True)
    lgd2.get_frame().set_alpha(.5)

  obsco = "Obs coord.: {0:8.4f}$^\circ$, {1:8.4f}$^\circ$, {2:4f} m".format(obs['longitude'], obs['latitude'], obs['altitude'])

  plt.text(0.01,0.97, obsco, transform=fig.transFigure, ha='left', va='center', fontsize=10)
  plt.text(0.01,0.95, obs['name'], transform=fig.transFigure, ha='left', va='center', fontsize=10)

  return fig