示例#1
0
    def UpdateColorbarPP(stuff):
        v_min = np.int(textbox_pp_min.text)
        v_max = np.int(textbox_pp_max.text)
        my_gamma = np.double(textbox_pp_g.text)

        print("\n v_min = ", v_min)
        print("v_max = ", v_max)
        print("gamma = ", my_gamma)

        pp_image.set_norm(colors.PowerNorm(gamma=my_gamma))
        pp_image.set_clim([v_min, v_max])

        cb_pp = Colorbar(ax=c_ax_pp,
                         mappable=pp_image,
                         orientation='horizontal',
                         ticklocation='top')
        cb_pp.locator = ticker.MaxNLocator(nbins=3)
        cb_pp.update_ticks()
示例#2
0
文件: maps.py 项目: rgrapenthin/obspy
def plot_cartopy(lons,
                 lats,
                 size,
                 color,
                 labels=None,
                 projection='global',
                 resolution='110m',
                 continent_fill_color='0.8',
                 water_fill_color='1.0',
                 colormap=None,
                 colorbar=None,
                 marker="o",
                 title=None,
                 colorbar_ticklabel_format=None,
                 show=True,
                 proj_kwargs=None,
                 **kwargs):  # @UnusedVariable
    """
    Creates a Cartopy plot with a data point scatter plot.

    :type lons: list/tuple of floats
    :param lons: Longitudes of the data points.
    :type lats: list/tuple of floats
    :param lats: Latitudes of the data points.
    :type size: float or list/tuple of floats
    :param size: Size of the individual points in the scatter plot.
    :type color: list/tuple of floats (or objects that can be
        converted to floats, like e.g.
        :class:`~obspy.core.utcdatetime.UTCDateTime`)
    :param color: Color information of the individual data points to be
        used in the specified color map (e.g. origin depths,
        origin times).
    :type labels: list/tuple of str
    :param labels: Annotations for the individual data points.
    :type projection: str, optional
    :param projection: The map projection.
        Currently supported are:

            * ``"global"`` (Will plot the whole world using
              :class:`~cartopy.crs.Mollweide`.)
            * ``"ortho"`` (Will center around the mean lat/long using
              :class:`~cartopy.crs.Orthographic`.)
            * ``"local"`` (Will plot around local events using
              :class:`~cartopy.crs.AlbersEqualArea`.)
            * Any other Cartopy :class:`~cartopy.crs.Projection`. An instance
              of this class will be created using the supplied ``proj_kwargs``.

        Defaults to "global"
    :type resolution: str, optional
    :param resolution: Resolution of the boundary database to use. Will be
        passed directly to the Cartopy module. Possible values are:

            * ``"110m"``
            * ``"50m"``
            * ``"10m"``

        Defaults to ``"110m"``. For compatibility, you may also specify any of
        the Basemap resolutions defined in :func:`plot_basemap`.
    :type continent_fill_color: Valid matplotlib color, optional
    :param continent_fill_color:  Color of the continents. Defaults to
        ``"0.9"`` which is a light gray.
    :type water_fill_color: Valid matplotlib color, optional
    :param water_fill_color: Color of all water bodies.
        Defaults to ``"white"``.
    :type colormap: str, any matplotlib colormap, optional
    :param colormap: The colormap for color-coding the events as provided
        in `color` kwarg.
        The event with the smallest `color` property will have the
        color of one end of the colormap and the event with the highest
        `color` property the color of the other end with all other events
        in between.
        Defaults to None which will use the default matplotlib colormap.
    :type colorbar: bool, optional
    :param colorbar: When left `None`, a colorbar is plotted if more than one
        object is plotted. Using `True`/`False` the colorbar can be forced
        on/off.
    :type title: str
    :param title: Title above plot.
    :type colorbar_ticklabel_format: str or function or
        subclass of :class:`matplotlib.ticker.Formatter`
    :param colorbar_ticklabel_format: Format string or Formatter used to format
        colorbar tick labels.
    :type show: bool
    :param show: Whether to show the figure after plotting or not. Can be used
        to do further customization of the plot before showing it.
    :type proj_kwargs: dict
    :param proj_kwargs: Keyword arguments to pass to the Cartopy
        :class:`~cartopy.ccrs.Projection`. In this dictionary, you may specify
        ``central_longitude='auto'`` or ``central_latitude='auto'`` to have
        this function calculate the latitude or longitude as it would for other
        projections. Some arguments may be ignored if you choose one of the
        built-in ``projection`` choices.
    """
    import matplotlib.pyplot as plt
    min_color = min(color)
    max_color = max(color)

    if isinstance(color[0], (datetime.datetime, UTCDateTime)):
        datetimeplot = True
        color = [date2num(getattr(t, 'datetime', t)) for t in color]
    else:
        datetimeplot = False

    scal_map = ScalarMappable(norm=Normalize(min_color, max_color),
                              cmap=colormap)
    scal_map.set_array(np.linspace(0, 1, 1))

    fig = plt.figure()

    # The colorbar should only be plotted if more then one event is
    # present.
    if colorbar is not None:
        show_colorbar = colorbar
    else:
        if len(lons) > 1 and hasattr(color, "__len__") and \
                not isinstance(color, (str, native_str)):
            show_colorbar = True
        else:
            show_colorbar = False

    if projection == "local":
        ax_x0, ax_width = 0.10, 0.80
    elif projection == "global":
        ax_x0, ax_width = 0.01, 0.98
    else:
        ax_x0, ax_width = 0.05, 0.90

    proj_kwargs = proj_kwargs or {}
    if projection == 'global':
        proj_kwargs['central_longitude'] = np.mean(lons)
        proj = ccrs.Mollweide(**proj_kwargs)
    elif projection == 'ortho':
        proj_kwargs['central_latitude'] = np.mean(lats)
        proj_kwargs['central_longitude'] = np.mean(lons)
        proj = ccrs.Orthographic(**proj_kwargs)
    elif projection == 'local':
        if min(lons) < -150 and max(lons) > 150:
            max_lons = max(np.array(lons) % 360)
            min_lons = min(np.array(lons) % 360)
        else:
            max_lons = max(lons)
            min_lons = min(lons)
        lat_0 = max(lats) / 2. + min(lats) / 2.
        lon_0 = max_lons / 2. + min_lons / 2.
        if lon_0 > 180:
            lon_0 -= 360
        deg2m_lat = 2 * np.pi * 6371 * 1000 / 360
        deg2m_lon = deg2m_lat * np.cos(lat_0 / 180 * np.pi)
        if len(lats) > 1:
            height = (max(lats) - min(lats)) * deg2m_lat
            width = (max_lons - min_lons) * deg2m_lon
            margin = 0.2 * (width + height)
            height += margin
            width += margin
        else:
            height = 2.0 * deg2m_lat
            width = 5.0 * deg2m_lon
        # Do intelligent aspect calculation for local projection
        # adjust to figure dimensions
        w, h = fig.get_size_inches()
        aspect = w / h
        if show_colorbar:
            aspect *= 1.2
        if width / height < aspect:
            width = height * aspect
        else:
            height = width / aspect

        proj_kwargs['central_latitude'] = lat_0
        proj_kwargs['central_longitude'] = lon_0
        proj = ccrs.AlbersEqualArea(**proj_kwargs)

    # User-supplied projection.
    elif isinstance(projection, type):
        if 'central_longitude' in proj_kwargs:
            if proj_kwargs['central_longitude'] == 'auto':
                proj_kwargs['central_longitude'] = np.mean(lons)
        if 'central_latitude' in proj_kwargs:
            if proj_kwargs['central_latitude'] == 'auto':
                proj_kwargs['central_latitude'] = np.mean(lats)
        if 'pole_longitude' in proj_kwargs:
            if proj_kwargs['pole_longitude'] == 'auto':
                proj_kwargs['pole_longitude'] = np.mean(lons)
        if 'pole_latitude' in proj_kwargs:
            if proj_kwargs['pole_latitude'] == 'auto':
                proj_kwargs['pole_latitude'] = np.mean(lats)

        proj = projection(**proj_kwargs)

    else:
        msg = "Projection '%s' not supported." % projection
        raise ValueError(msg)

    if show_colorbar:
        map_ax = fig.add_axes([ax_x0, 0.13, ax_width, 0.77], projection=proj)
        cm_ax = fig.add_axes([ax_x0, 0.05, ax_width, 0.05])
        plt.sca(map_ax)
    else:
        ax_y0, ax_height = 0.05, 0.85
        if projection == "local":
            ax_y0 += 0.05
            ax_height -= 0.05
        map_ax = fig.add_axes([ax_x0, ax_y0, ax_width, ax_height],
                              projection=proj)

    if projection == 'local':
        x0, y0 = proj.transform_point(lon_0, lat_0, proj.as_geodetic())
        map_ax.set_xlim(x0 - width / 2, x0 + width / 2)
        map_ax.set_ylim(y0 - height / 2, y0 + height / 2)
    else:
        map_ax.set_global()

    # Pick features at specified resolution.
    resolution = _CARTOPY_RESOLUTIONS[resolution]
    try:
        borders, land, ocean = _CARTOPY_FEATURES[resolution]
    except KeyError:
        borders = cfeature.NaturalEarthFeature(cfeature.BORDERS.category,
                                               cfeature.BORDERS.name,
                                               resolution,
                                               edgecolor='none',
                                               facecolor='none')
        land = cfeature.NaturalEarthFeature(cfeature.LAND.category,
                                            cfeature.LAND.name,
                                            resolution,
                                            edgecolor='face',
                                            facecolor='none')
        ocean = cfeature.NaturalEarthFeature(cfeature.OCEAN.category,
                                             cfeature.OCEAN.name,
                                             resolution,
                                             edgecolor='face',
                                             facecolor='none')
        _CARTOPY_FEATURES[resolution] = (borders, land, ocean)

    # Draw coast lines, country boundaries, fill continents.
    map_ax.set_axis_bgcolor(water_fill_color)
    map_ax.add_feature(ocean, facecolor=water_fill_color)
    map_ax.add_feature(land, facecolor=continent_fill_color)
    map_ax.add_feature(borders, edgecolor='0.75')
    map_ax.coastlines(resolution=resolution, color='0.4')

    # Draw grid lines - TODO: draw_labels=True doesn't work yet.
    if projection == 'local':
        map_ax.gridlines()
    else:
        # Draw lat/lon grid lines every 30 degrees.
        map_ax.gridlines(xlocs=range(-180, 181, 30), ylocs=range(-90, 91, 30))

    # Plot labels
    if labels and len(lons) > 0:
        with map_ax.hold_limits():
            for name, xpt, ypt, _colorpt in zip(labels, lons, lats, color):
                map_ax.text(xpt,
                            ypt,
                            name,
                            weight="heavy",
                            color="k",
                            zorder=100,
                            transform=ccrs.Geodetic(),
                            path_effects=[
                                PathEffects.withStroke(linewidth=3,
                                                       foreground="white")
                            ])

    scatter = map_ax.scatter(lons,
                             lats,
                             marker=marker,
                             s=size,
                             c=color,
                             zorder=10,
                             cmap=colormap,
                             transform=ccrs.Geodetic())

    if title:
        plt.suptitle(title)

    # Only show the colorbar for more than one event.
    if show_colorbar:
        if colorbar_ticklabel_format is not None:
            if isinstance(colorbar_ticklabel_format, (str, native_str)):
                formatter = FormatStrFormatter(colorbar_ticklabel_format)
            elif hasattr(colorbar_ticklabel_format, '__call__'):
                formatter = FuncFormatter(colorbar_ticklabel_format)
            elif isinstance(colorbar_ticklabel_format, Formatter):
                formatter = colorbar_ticklabel_format
            locator = MaxNLocator(5)
        else:
            if datetimeplot:
                locator = AutoDateLocator()
                formatter = AutoDateFormatter(locator)
                # Compat with old matplotlib versions.
                if hasattr(formatter, "scaled"):
                    formatter.scaled[1 / (24. * 60.)] = '%H:%M:%S'
            else:
                locator = None
                formatter = None
        cb = Colorbar(cm_ax,
                      scatter,
                      cmap=colormap,
                      orientation='horizontal',
                      ticks=locator,
                      format=formatter)
        # Compat with old matplotlib versions.
        if hasattr(cb, "update_ticks"):
            cb.update_ticks()

    if show:
        plt.show()

    return fig
示例#3
0
class ColorbarWidget(QWidget):
    colorbarChanged = Signal() # The parent should simply redraw their canvas

    def __init__(self, parent=None):
        super(ColorbarWidget, self).__init__(parent)

        self.setWindowTitle("Colorbar")
        self.setMaximumWidth(200)

        self.cmap = QComboBox()
        self.cmap.addItems(sorted(cm.cmap_d.keys()))
        self.cmap.currentIndexChanged.connect(self.cmap_index_changed)

        self.cmin = QLineEdit()
        self.cmin_value = 0
        self.cmin.setMaximumWidth(100)
        self.cmin.editingFinished.connect(self.clim_changed)
        self.cmin_layout = QHBoxLayout()
        self.cmin_layout.addStretch()
        self.cmin_layout.addWidget(self.cmin)
        self.cmin_layout.addStretch()

        self.cmax = QLineEdit()
        self.cmax_value = 1
        self.cmax.setMaximumWidth(100)
        self.cmax.editingFinished.connect(self.clim_changed)
        self.cmin.setValidator(QDoubleValidator())
        self.cmax.setValidator(QDoubleValidator())
        self.cmax_layout = QHBoxLayout()
        self.cmax_layout.addStretch()
        self.cmax_layout.addWidget(self.cmax)
        self.cmax_layout.addStretch()

        self.norm_layout = QHBoxLayout()
        self.norm = QComboBox()
        self.norm.addItems(NORM_OPTS)
        self.norm.currentIndexChanged.connect(self.norm_changed)

        self.powerscale = QLineEdit()
        self.powerscale_value = 2
        self.powerscale.setText("2")
        self.powerscale.setValidator(QDoubleValidator(0.001,100,3))
        self.powerscale.setMaximumWidth(50)
        self.powerscale.editingFinished.connect(self.norm_changed)
        self.powerscale.hide()
        self.powerscale_label = QLabel("n=")
        self.powerscale_label.hide()

        self.norm_layout.addStretch()
        self.norm_layout.addWidget(self.norm)
        self.norm_layout.addStretch()
        self.norm_layout.addWidget(self.powerscale_label)
        self.norm_layout.addWidget(self.powerscale)

        self.autoscale = QCheckBox("Autoscaling")
        self.autoscale.setChecked(True)
        self.autoscale.stateChanged.connect(self.update_clim)

        self.canvas = FigureCanvas(Figure())
        if parent:
            # Set facecolor to match parent
            self.canvas.figure.set_facecolor(parent.palette().window().color().getRgbF())
        self.ax = self.canvas.figure.add_axes([0.4,0.05,0.2,0.9])

        # layout
        self.layout = QVBoxLayout(self)
        self.layout.addWidget(self.cmap)
        self.layout.addLayout(self.cmax_layout)
        self.layout.addWidget(self.canvas, stretch=1)
        self.layout.addLayout(self.cmin_layout)
        self.layout.addLayout(self.norm_layout)
        self.layout.addWidget(self.autoscale)

    def set_mappable(self, mappable):
        """
        When a new plot is created this method should be called with the new mappable
        """
        self.ax.clear()
        try: # Use current cmap
            cmap = self.colorbar.get_cmap()
        except AttributeError:
            try: # else use viridis
                cmap = cm.viridis
            except AttributeError: # else default
                cmap = None
        self.colorbar = Colorbar(ax=self.ax, mappable=mappable)
        self.cmin_value, self.cmax_value = self.colorbar.get_clim()
        self.update_clim_text()
        self.cmap_changed(cmap)
        self.cmap.setCurrentIndex(sorted(cm.cmap_d.keys()).index(self.colorbar.get_cmap().name))
        self.redraw()

    def cmap_index_changed(self):
        self.cmap_changed(self.cmap.currentText())

    def cmap_changed(self, name):
        self.colorbar.set_cmap(name)
        self.colorbar.mappable.set_cmap(name)
        self.redraw()

    def norm_changed(self):
        """
        Called when a different normalization is selected
        """
        idx = self.norm.currentIndex()
        if NORM_OPTS[idx] == 'Power':
            self.powerscale.show()
            self.powerscale_label.show()
        else:
            self.powerscale.hide()
            self.powerscale_label.hide()
        self.colorbar.mappable.set_norm(self.get_norm())
        self.set_mappable(self.colorbar.mappable)

    def get_norm(self):
        """
        This will create a matplotlib.colors.Normalize from selected idx, limits and powerscale
        """
        idx = self.norm.currentIndex()
        if self.autoscale.isChecked():
            cmin = cmax = None
        else:
            cmin = self.cmin_value
            cmax = self.cmax_value
        if NORM_OPTS[idx] == 'Power':
            if self.powerscale.hasAcceptableInput():
                self.powerscale_value = float(self.powerscale.text())
            return PowerNorm(gamma=self.powerscale_value, vmin=cmin, vmax=cmax)
        elif NORM_OPTS[idx] == "SymmetricLog10":
            return SymLogNorm(1e-8 if cmin is None else max(1e-8, abs(cmin)*1e-3),
                              vmin=cmin, vmax=cmax)
        else:
            return Normalize(vmin=cmin, vmax=cmax)

    def clim_changed(self):
        """
        Called when either the min or max is changed. Will unset the autoscale.
        """
        self.autoscale.blockSignals(True)
        self.autoscale.setChecked(False)
        self.autoscale.blockSignals(False)
        self.update_clim()

    def update_clim(self):
        """
        This will update the clim of the plot based on min, max, and autoscale
        """
        if self.autoscale.isChecked():
            data = self.colorbar.mappable.get_array()
            try:
                try:
                    self.cmin_value = data[~data.mask].min()
                    self.cmax_value = data[~data.mask].max()
                except AttributeError:
                    self.cmin_value = np.nanmin(data)
                    self.cmax_value = np.nanmax(data)
            except (ValueError, RuntimeWarning):
                # all values mask
                pass
            self.update_clim_text()
        else:
            if self.cmin.hasAcceptableInput():
                cmin = float(self.cmin.text())
                if cmin < self.cmax_value:
                    self.cmin_value = cmin
                else: # reset values back
                    self.update_clim_text()
            if self.cmax.hasAcceptableInput():
                cmax = float(self.cmax.text())
                if cmax > self.cmin_value:
                    self.cmax_value = cmax
                else: #reset values back
                    self.update_clim_text()
        self.colorbar.set_clim(self.cmin_value, self.cmax_value)
        self.redraw()

    def update_clim_text(self):
        """
        Update displayed limit values based on stored ones
        """
        self.cmin.setText("{:.4}".format(self.cmin_value))
        self.cmax.setText("{:.4}".format(self.cmax_value))

    def redraw(self):
        """
        Redraws the colobar and emits signal to cause the parent to redraw
        """
        self.colorbar.update_ticks()
        self.colorbar.draw_all()
        self.canvas.draw_idle()
        self.colorbarChanged.emit()
示例#4
0
class ColorbarWidget(QWidget):
    colorbarChanged = Signal() # The parent should simply redraw their canvas

    def __init__(self, parent=None):
        super(ColorbarWidget, self).__init__(parent)

        self.setWindowTitle("Colorbar")
        self.setMaximumWidth(200)

        self.dval = QDoubleValidator()

        self.cmin = QLineEdit()
        self.cmin_value = 0
        self.cmin.setMaximumWidth(100)
        self.cmin.editingFinished.connect(self.clim_changed)
        self.cmin_layout = QHBoxLayout()
        self.cmin_layout.addStretch()
        self.cmin_layout.addWidget(self.cmin)
        self.cmin_layout.addStretch()

        self.cmax = QLineEdit()
        self.cmax_value = 1
        self.cmax.setMaximumWidth(100)
        self.cmax.editingFinished.connect(self.clim_changed)
        self.cmin.setValidator(self.dval)
        self.cmax.setValidator(self.dval)
        self.cmax_layout = QHBoxLayout()
        self.cmax_layout.addStretch()
        self.cmax_layout.addWidget(self.cmax)
        self.cmax_layout.addStretch()

        self.norm_layout = QHBoxLayout()
        self.norm = QComboBox()
        self.norm.addItems(NORM_OPTS)
        self.norm.currentIndexChanged.connect(self.norm_changed)

        self.powerscale = QLineEdit()
        self.powerscale_value = 2
        self.powerscale.setText("2")
        self.powerscale.setValidator(QDoubleValidator(0.001,100,3))
        self.powerscale.setMaximumWidth(50)
        self.powerscale.editingFinished.connect(self.norm_changed)
        self.powerscale.hide()
        self.powerscale_label = QLabel("n=")
        self.powerscale_label.hide()

        self.norm_layout.addStretch()
        self.norm_layout.addWidget(self.norm)
        self.norm_layout.addStretch()
        self.norm_layout.addWidget(self.powerscale_label)
        self.norm_layout.addWidget(self.powerscale)

        self.autoscale = QCheckBox("Autoscaling")
        self.autoscale.setChecked(True)
        self.autoscale.stateChanged.connect(self.update_clim)

        self.canvas = FigureCanvas(Figure())
        if parent:
            # Set facecolor to match parent
            self.canvas.figure.set_facecolor(parent.palette().window().color().getRgbF())
        self.ax = self.canvas.figure.add_axes([0.4,0.05,0.2,0.9])

        # layout
        self.layout = QVBoxLayout(self)
        self.layout.addLayout(self.cmax_layout)
        self.layout.addWidget(self.canvas, stretch=1)
        self.layout.addLayout(self.cmin_layout)
        self.layout.addLayout(self.norm_layout)
        self.layout.addWidget(self.autoscale)

    def set_mappable(self, mappable):
        """
        When a new plot is created this method should be called with the new mappable
        """
        self.ax.clear()
        self.colorbar = Colorbar(ax=self.ax, mappable=mappable)
        self.cmin_value, self.cmax_value = self.colorbar.get_clim()
        self.update_clim_text()
        self.redraw()

    def norm_changed(self):
        """
        Called when a different normalization is selected
        """
        idx = self.norm.currentIndex()
        if NORM_OPTS[idx] == 'Power':
            self.powerscale.show()
            self.powerscale_label.show()
        else:
            self.powerscale.hide()
            self.powerscale_label.hide()
        self.colorbar.mappable.set_norm(self.get_norm())
        self.colorbarChanged.emit()

    def get_norm(self):
        """
        This will create a matplotlib.colors.Normalize from selected idx, limits and powerscale
        """
        idx = self.norm.currentIndex()
        if self.autoscale.isChecked():
            cmin = cmax = None
        else:
            cmin = self.cmin_value
            cmax = self.cmax_value
        if NORM_OPTS[idx] == 'Power':
            if self.powerscale.hasAcceptableInput():
                self.powerscale_value = float(self.powerscale.text())
            return PowerNorm(gamma=self.powerscale_value, vmin=cmin, vmax=cmax)
        elif NORM_OPTS[idx] == "SymmetricLog10":
            return SymLogNorm(1e-8 if cmin is None else max(1e-8, abs(cmin)*1e-3),
                              vmin=cmin, vmax=cmax)
        else:
            return Normalize(vmin=cmin, vmax=cmax)

    def clim_changed(self):
        """
        Called when either the min or max is changed. Will unset the autoscale.
        """
        self.autoscale.blockSignals(True)
        self.autoscale.setChecked(False)
        self.autoscale.blockSignals(False)
        self.update_clim()

    def update_clim(self):
        """
        This will update the clim of the plot based on min, max, and autoscale
        """
        if self.autoscale.isChecked():
            data = self.colorbar.mappable.get_array()
            try:
                try:
                    self.cmin_value = data[~data.mask].min()
                    self.cmax_value = data[~data.mask].max()
                except AttributeError:
                    self.cmin_value = np.nanmin(data)
                    self.cmax_value = np.nanmax(data)
            except (ValueError, RuntimeWarning):
                # all values mask
                pass
            self.update_clim_text()
        else:
            if self.cmin.hasAcceptableInput():
                self.cmin_value = float(self.cmin.text())
            if self.cmax.hasAcceptableInput():
                self.cmax_value = float(self.cmax.text())
        self.colorbar.set_clim(self.cmin_value, self.cmax_value)
        self.redraw()

    def update_clim_text(self):
        """
        Update displayed limit values based on stored ones
        """
        self.cmin.setText("{:.4}".format(self.cmin_value))
        self.cmax.setText("{:.4}".format(self.cmax_value))

    def redraw(self):
        """
        Redraws the colobar and emits signal to cause the parent to redraw
        """
        self.colorbar.update_ticks()
        self.colorbar.draw_all()
        self.canvas.draw_idle()
        self.colorbarChanged.emit()
示例#5
0
文件: maps.py 项目: Brtle/obspy
def plot_cartopy(lons, lats, size, color, labels=None, projection='global',
                 resolution='110m', continent_fill_color='0.8',
                 water_fill_color='1.0', colormap=None, colorbar=None,
                 marker="o", title=None, colorbar_ticklabel_format=None,
                 show=True, proj_kwargs=None, **kwargs):  # @UnusedVariable
    """
    Creates a Cartopy plot with a data point scatter plot.

    :type lons: list/tuple of floats
    :param lons: Longitudes of the data points.
    :type lats: list/tuple of floats
    :param lats: Latitudes of the data points.
    :type size: float or list/tuple of floats
    :param size: Size of the individual points in the scatter plot.
    :type color: list/tuple of floats (or objects that can be
        converted to floats, like e.g.
        :class:`~obspy.core.utcdatetime.UTCDateTime`)
    :param color: Color information of the individual data points to be
        used in the specified color map (e.g. origin depths,
        origin times).
    :type labels: list/tuple of str
    :param labels: Annotations for the individual data points.
    :type projection: str, optional
    :param projection: The map projection.
        Currently supported are:

            * ``"global"`` (Will plot the whole world using
              :class:`~cartopy.crs.Mollweide`.)
            * ``"ortho"`` (Will center around the mean lat/long using
              :class:`~cartopy.crs.Orthographic`.)
            * ``"local"`` (Will plot around local events using
              :class:`~cartopy.crs.AlbersEqualArea`.)
            * Any other Cartopy :class:`~cartopy.crs.Projection`. An instance
              of this class will be created using the supplied ``proj_kwargs``.

        Defaults to "global"
    :type resolution: str, optional
    :param resolution: Resolution of the boundary database to use. Will be
        passed directly to the Cartopy module. Possible values are:

            * ``"110m"``
            * ``"50m"``
            * ``"10m"``

        Defaults to ``"110m"``. For compatibility, you may also specify any of
        the Basemap resolutions defined in :func:`plot_basemap`.
    :type continent_fill_color: Valid matplotlib color, optional
    :param continent_fill_color:  Color of the continents. Defaults to
        ``"0.9"`` which is a light gray.
    :type water_fill_color: Valid matplotlib color, optional
    :param water_fill_color: Color of all water bodies.
        Defaults to ``"white"``.
    :type colormap: str, any matplotlib colormap, optional
    :param colormap: The colormap for color-coding the events as provided
        in `color` kwarg.
        The event with the smallest `color` property will have the
        color of one end of the colormap and the event with the highest
        `color` property the color of the other end with all other events
        in between.
        Defaults to None which will use the default matplotlib colormap.
    :type colorbar: bool, optional
    :param colorbar: When left `None`, a colorbar is plotted if more than one
        object is plotted. Using `True`/`False` the colorbar can be forced
        on/off.
    :type title: str
    :param title: Title above plot.
    :type colorbar_ticklabel_format: str or function or
        subclass of :class:`matplotlib.ticker.Formatter`
    :param colorbar_ticklabel_format: Format string or Formatter used to format
        colorbar tick labels.
    :type show: bool
    :param show: Whether to show the figure after plotting or not. Can be used
        to do further customization of the plot before showing it.
    :type proj_kwargs: dict
    :param proj_kwargs: Keyword arguments to pass to the Cartopy
        :class:`~cartopy.ccrs.Projection`. In this dictionary, you may specify
        ``central_longitude='auto'`` or ``central_latitude='auto'`` to have
        this function calculate the latitude or longitude as it would for other
        projections. Some arguments may be ignored if you choose one of the
        built-in ``projection`` choices.
    """
    import matplotlib.pyplot as plt

    if isinstance(color[0], (datetime.datetime, UTCDateTime)):
        datetimeplot = True
        color = [date2num(getattr(t, 'datetime', t)) for t in color]
    else:
        datetimeplot = False

    fig = plt.figure()

    # The colorbar should only be plotted if more then one event is
    # present.
    if colorbar is not None:
        show_colorbar = colorbar
    else:
        if len(lons) > 1 and hasattr(color, "__len__") and \
                not isinstance(color, (str, native_str)):
            show_colorbar = True
        else:
            show_colorbar = False

    if projection == "local":
        ax_x0, ax_width = 0.10, 0.80
    elif projection == "global":
        ax_x0, ax_width = 0.01, 0.98
    else:
        ax_x0, ax_width = 0.05, 0.90

    proj_kwargs = proj_kwargs or {}
    if projection == 'global':
        proj_kwargs['central_longitude'] = np.mean(lons)
        proj = ccrs.Mollweide(**proj_kwargs)
    elif projection == 'ortho':
        proj_kwargs['central_latitude'] = np.mean(lats)
        proj_kwargs['central_longitude'] = mean_longitude(lons)
        proj = ccrs.Orthographic(**proj_kwargs)
    elif projection == 'local':
        if min(lons) < -150 and max(lons) > 150:
            max_lons = max(np.array(lons) % 360)
            min_lons = min(np.array(lons) % 360)
        else:
            max_lons = max(lons)
            min_lons = min(lons)
        lat_0 = max(lats) / 2. + min(lats) / 2.
        lon_0 = max_lons / 2. + min_lons / 2.
        if lon_0 > 180:
            lon_0 -= 360
        deg2m_lat = 2 * np.pi * 6371 * 1000 / 360
        deg2m_lon = deg2m_lat * np.cos(lat_0 / 180 * np.pi)
        if len(lats) > 1:
            height = (max(lats) - min(lats)) * deg2m_lat
            width = (max_lons - min_lons) * deg2m_lon
            margin = 0.2 * (width + height)
            height += margin
            width += margin
        else:
            height = 2.0 * deg2m_lat
            width = 5.0 * deg2m_lon
        # Do intelligent aspect calculation for local projection
        # adjust to figure dimensions
        w, h = fig.get_size_inches()
        aspect = w / h
        if show_colorbar:
            aspect *= 1.2
        if width / height < aspect:
            width = height * aspect
        else:
            height = width / aspect

        proj_kwargs['central_latitude'] = lat_0
        proj_kwargs['central_longitude'] = lon_0
        proj_kwargs['standard_parallels'] = [lat_0, lat_0]
        proj = ccrs.AlbersEqualArea(**proj_kwargs)

    # User-supplied projection.
    elif isinstance(projection, type):
        if 'central_longitude' in proj_kwargs:
            if proj_kwargs['central_longitude'] == 'auto':
                proj_kwargs['central_longitude'] = mean_longitude(lons)
        if 'central_latitude' in proj_kwargs:
            if proj_kwargs['central_latitude'] == 'auto':
                proj_kwargs['central_latitude'] = np.mean(lats)
        if 'pole_longitude' in proj_kwargs:
            if proj_kwargs['pole_longitude'] == 'auto':
                proj_kwargs['pole_longitude'] = np.mean(lons)
        if 'pole_latitude' in proj_kwargs:
            if proj_kwargs['pole_latitude'] == 'auto':
                proj_kwargs['pole_latitude'] = np.mean(lats)

        proj = projection(**proj_kwargs)

    else:
        msg = "Projection '%s' not supported." % projection
        raise ValueError(msg)

    if show_colorbar:
        map_ax = fig.add_axes([ax_x0, 0.13, ax_width, 0.77], projection=proj)
        cm_ax = fig.add_axes([ax_x0, 0.05, ax_width, 0.05])
        plt.sca(map_ax)
    else:
        ax_y0, ax_height = 0.05, 0.85
        if projection == "local":
            ax_y0 += 0.05
            ax_height -= 0.05
        map_ax = fig.add_axes([ax_x0, ax_y0, ax_width, ax_height],
                              projection=proj)

    if projection == 'local':
        x0, y0 = proj.transform_point(lon_0, lat_0, proj.as_geodetic())
        map_ax.set_xlim(x0 - width / 2, x0 + width / 2)
        map_ax.set_ylim(y0 - height / 2, y0 + height / 2)
    else:
        map_ax.set_global()

    # Pick features at specified resolution.
    resolution = _CARTOPY_RESOLUTIONS[resolution]
    try:
        borders, land, ocean = _CARTOPY_FEATURES[resolution]
    except KeyError:
        borders = cfeature.NaturalEarthFeature(cfeature.BORDERS.category,
                                               cfeature.BORDERS.name,
                                               resolution,
                                               edgecolor='none',
                                               facecolor='none')
        land = cfeature.NaturalEarthFeature(cfeature.LAND.category,
                                            cfeature.LAND.name, resolution,
                                            edgecolor='face', facecolor='none')
        ocean = cfeature.NaturalEarthFeature(cfeature.OCEAN.category,
                                             cfeature.OCEAN.name, resolution,
                                             edgecolor='face',
                                             facecolor='none')
        _CARTOPY_FEATURES[resolution] = (borders, land, ocean)

    # Draw coast lines, country boundaries, fill continents.
    if MATPLOTLIB_VERSION >= [2, 0, 0]:
        map_ax.set_facecolor(water_fill_color)
    else:
        map_ax.set_axis_bgcolor(water_fill_color)
    map_ax.add_feature(ocean, facecolor=water_fill_color)
    map_ax.add_feature(land, facecolor=continent_fill_color)
    map_ax.add_feature(borders, edgecolor='0.75')
    map_ax.coastlines(resolution=resolution, color='0.4')

    # Draw grid lines - TODO: draw_labels=True doesn't work yet.
    if projection == 'local':
        map_ax.gridlines()
    else:
        # Draw lat/lon grid lines every 30 degrees.
        map_ax.gridlines(xlocs=range(-180, 181, 30), ylocs=range(-90, 91, 30))

    # Plot labels
    if labels and len(lons) > 0:
        with map_ax.hold_limits():
            for name, xpt, ypt, _colorpt in zip(labels, lons, lats, color):
                map_ax.text(xpt, ypt, name, weight="heavy", color="k",
                            zorder=100, transform=ccrs.Geodetic(),
                            path_effects=[
                                PathEffects.withStroke(linewidth=3,
                                                       foreground="white")])

    scatter = map_ax.scatter(lons, lats, marker=marker, s=size, c=color,
                             zorder=10, cmap=colormap,
                             transform=ccrs.Geodetic())

    if title:
        plt.suptitle(title)

    # Only show the colorbar for more than one event.
    if show_colorbar:
        if colorbar_ticklabel_format is not None:
            if isinstance(colorbar_ticklabel_format, (str, native_str)):
                formatter = FormatStrFormatter(colorbar_ticklabel_format)
            elif hasattr(colorbar_ticklabel_format, '__call__'):
                formatter = FuncFormatter(colorbar_ticklabel_format)
            elif isinstance(colorbar_ticklabel_format, Formatter):
                formatter = colorbar_ticklabel_format
            locator = MaxNLocator(5)
        else:
            if datetimeplot:
                locator = AutoDateLocator()
                formatter = AutoDateFormatter(locator)
                # Compat with old matplotlib versions.
                if hasattr(formatter, "scaled"):
                    formatter.scaled[1 / (24. * 60.)] = '%H:%M:%S'
            else:
                locator = None
                formatter = None
        cb = Colorbar(cm_ax, scatter, cmap=colormap,
                      orientation='horizontal',
                      ticks=locator,
                      format=formatter)
        # Compat with old matplotlib versions.
        if hasattr(cb, "update_ticks"):
            cb.update_ticks()

    if show:
        plt.show()

    return fig
示例#6
0
def add_ortho(lats, lons, colors, CClim,
              central_longitude, central_latitude,
              text=None, size=50, marker=['o', 'd'],
              colormap='viridis', fig=None,
              rect=[0.0, 0.0, 1.0, 1.0]):
    if not fig:
        fig = plt.figure()

    proj = ccrs.Orthographic(central_longitude=central_longitude,
                             central_latitude=central_latitude)

    # left, bottom, width, height
    ax = fig.add_axes([rect[0],
                       rect[1] + rect[3] * 0.12,
                       rect[2],
                       rect[3] * 0.85],
                      projection=proj)
    cm_ax = fig.add_axes([rect[0],
                          rect[1],
                          rect[2],
                          rect[3] * 0.08])
    plt.sca(ax)

    # make the map global rather than have it zoom in to
    # the extents of any plotted data
    ax.set_global()

    ax.stock_img()
    ax.coastlines()
    ax.gridlines()

    lats_mark1 = []
    lons_mark1 = []
    colors_mark1 = []
    lats_mark2 = []
    lons_mark2 = []
    colors_mark2 = []

    cmap = get_cmap(colormap)
    cmap.set_under('grey')

    for lon, lat, color in zip(lons, lats, colors):
        if color > CClim:
            lats_mark1.append(lat)
            lons_mark1.append(lon)
            colors_mark1.append(color)
        else:
            lats_mark2.append(lat)
            lons_mark2.append(lon)
            colors_mark2.append(color)

    if len(lons_mark1) > 0:
        scatter = ax.scatter(lons_mark1, lats_mark1, s=size, c=colors_mark1,
                             marker=marker[0],
                             cmap=cmap, vmin=CClim, vmax=1, zorder=10,
                             transform=ccrs.Geodetic())

    if len(lons_mark2) > 0:
        scatter = ax.scatter(lons_mark2, lats_mark2, s=size, c=colors_mark2,
                             marker=marker[1],
                             cmap=cmap, vmin=CClim, vmax=1, zorder=10,
                             transform=ccrs.Geodetic())

    locator = MaxNLocator(5)

    cb = Colorbar(cm_ax, scatter, cmap=cmap,
                  orientation='horizontal',
                  ticks=locator,
                  extend='min')
    cb.set_label('CC')
    # Compat with old matplotlib versions.
    if hasattr(cb, "update_ticks"):
        cb.update_ticks()

    ax.plot(central_longitude, central_latitude, color='red', marker='*',
            markersize=np.sqrt(size))

    if (text):
        for lat, lon, text in zip(lats, lons, text):
            # Avoid plotting invisible texts. They clutter at the origin
            # otherwise
            dist = locations2degrees(lat, lon,
                                     central_latitude, central_longitude)
            if (dist < 90):
                plt.text(lon, lat, text, weight="heavy",
                         transform=ccrs.Geodetic(),
                         color="k", zorder=100,
                         path_effects=[
                             PathEffects.withStroke(linewidth=3,
                                                    foreground="white")])

    return ax
示例#7
0
文件: maps.py 项目: 3rdcycle/obspy
def plot_basemap(lons, lats, size, color, labels=None, projection='global',
                 resolution='l', continent_fill_color='0.8',
                 water_fill_color='1.0', colormap=None, colorbar=None,
                 marker="o", title=None, colorbar_ticklabel_format=None,
                 show=True, **kwargs):  # @UnusedVariable
    """
    Creates a basemap plot with a data point scatter plot.

    :type lons: list/tuple of floats
    :param lons: Longitudes of the data points.
    :type lats: list/tuple of floats
    :param lats: Latitudes of the data points.
    :type size: float or list/tuple of floats
    :param size: Size of the individual points in the scatter plot.
    :type color: list/tuple of floats (or objects that can be
        converted to floats, like e.g.
        :class:`~obspy.core.utcdatetime.UTCDateTime`)
    :param color: Color information of the individual data points to be
        used in the specified color map (e.g. origin depths,
        origin times).
    :type labels: list/tuple of str
    :param labels: Annotations for the individual data points.
    :type projection: str, optional
    :param projection: The map projection. Currently supported are
        * ``"global"`` (Will plot the whole world.)
        * ``"ortho"`` (Will center around the mean lat/long.)
        * ``"local"`` (Will plot around local events)
        Defaults to "global"
    :type resolution: str, optional
    :param resolution: Resolution of the boundary database to use. Will be
        based directly to the basemap module. Possible values are
        * ``"c"`` (crude)
        * ``"l"`` (low)
        * ``"i"`` (intermediate)
        * ``"h"`` (high)
        * ``"f"`` (full)
        Defaults to ``"l"``. For compatibility, you may also specify any of the
        Cartopy resolutions defined in :func:`plot_cartopy`.
    :type continent_fill_color: Valid matplotlib color, optional
    :param continent_fill_color:  Color of the continents. Defaults to
        ``"0.9"`` which is a light gray.
    :type water_fill_color: Valid matplotlib color, optional
    :param water_fill_color: Color of all water bodies.
        Defaults to ``"white"``.
    :type colormap: str, any matplotlib colormap, optional
    :param colormap: The colormap for color-coding the events as provided
        in `color` kwarg.
        The event with the smallest `color` property will have the
        color of one end of the colormap and the event with the highest
        `color` property the color of the other end with all other events
        in between.
        Defaults to None which will use the default matplotlib colormap.
    :type colorbar: bool, optional
    :param colorbar: When left `None`, a colorbar is plotted if more than one
        object is plotted. Using `True`/`False` the colorbar can be forced
        on/off.
    :type title: str
    :param title: Title above plot.
    :type colorbar_ticklabel_format: str or function or
        subclass of :class:`matplotlib.ticker.Formatter`
    :param colorbar_ticklabel_format: Format string or Formatter used to format
        colorbar tick labels.
    :type show: bool
    :param show: Whether to show the figure after plotting or not. Can be used
        to do further customization of the plot before showing it.
    """
    min_color = min(color)
    max_color = max(color)

    if any([isinstance(c, (datetime.datetime, UTCDateTime)) for c in color]):
        datetimeplot = True
        color = [np.isfinite(float(t)) and date2num(t) or np.nan
                 for t in color]
    else:
        datetimeplot = False

    scal_map = ScalarMappable(norm=Normalize(min_color, max_color),
                              cmap=colormap)
    scal_map.set_array(np.linspace(0, 1, 1))

    fig = plt.figure()

    # The colorbar should only be plotted if more then one event is
    # present.
    if colorbar is not None:
        show_colorbar = colorbar
    else:
        if len(lons) > 1 and hasattr(color, "__len__") and \
                not isinstance(color, (str, native_str)):
            show_colorbar = True
        else:
            show_colorbar = False

    if projection == "local":
        ax_x0, ax_width = 0.10, 0.80
    elif projection == "global":
        ax_x0, ax_width = 0.01, 0.98
    else:
        ax_x0, ax_width = 0.05, 0.90

    if show_colorbar:
        map_ax = fig.add_axes([ax_x0, 0.13, ax_width, 0.77])
        cm_ax = fig.add_axes([ax_x0, 0.05, ax_width, 0.05])
    else:
        ax_y0, ax_height = 0.05, 0.85
        if projection == "local":
            ax_y0 += 0.05
            ax_height -= 0.05
        map_ax = fig.add_axes([ax_x0, ax_y0, ax_width, ax_height])

    if projection == 'global':
        bmap = Basemap(projection='moll', lon_0=round(np.mean(lons), 4),
                       resolution=_BASEMAP_RESOLUTIONS[resolution], ax=map_ax)
    elif projection == 'ortho':
        bmap = Basemap(projection='ortho',
                       resolution=_BASEMAP_RESOLUTIONS[resolution],
                       area_thresh=1000.0, lat_0=round(np.mean(lats), 4),
                       lon_0=round(np.mean(lons), 4), ax=map_ax)
    elif projection == 'local':
        if min(lons) < -150 and max(lons) > 150:
            max_lons = max(np.array(lons) % 360)
            min_lons = min(np.array(lons) % 360)
        else:
            max_lons = max(lons)
            min_lons = min(lons)
        lat_0 = max(lats) / 2. + min(lats) / 2.
        lon_0 = max_lons / 2. + min_lons / 2.
        if lon_0 > 180:
            lon_0 -= 360
        deg2m_lat = 2 * np.pi * 6371 * 1000 / 360
        deg2m_lon = deg2m_lat * np.cos(lat_0 / 180 * np.pi)
        if len(lats) > 1:
            height = (max(lats) - min(lats)) * deg2m_lat
            width = (max_lons - min_lons) * deg2m_lon
            margin = 0.2 * (width + height)
            height += margin
            width += margin
        else:
            height = 2.0 * deg2m_lat
            width = 5.0 * deg2m_lon
        # do intelligent aspect calculation for local projection
        # adjust to figure dimensions
        w, h = fig.get_size_inches()
        aspect = w / h
        if show_colorbar:
            aspect *= 1.2
        if width / height < aspect:
            width = height * aspect
        else:
            height = width / aspect

        bmap = Basemap(projection='aea',
                       resolution=_BASEMAP_RESOLUTIONS[resolution],
                       area_thresh=1000.0, lat_0=round(lat_0, 4),
                       lon_0=round(lon_0, 4),
                       width=width, height=height, ax=map_ax)
        # not most elegant way to calculate some round lats/lons

        def linspace2(val1, val2, N):
            """
            returns around N 'nice' values between val1 and val2
            """
            dval = val2 - val1
            round_pos = int(round(-np.log10(1. * dval / N)))
            # Fake negative rounding as not supported by future as of now.
            if round_pos < 0:
                factor = 10 ** (abs(round_pos))
                delta = round(2. * dval / N / factor) * factor / 2
            else:
                delta = round(2. * dval / N, round_pos) / 2
            new_val1 = np.ceil(val1 / delta) * delta
            new_val2 = np.floor(val2 / delta) * delta
            N = (new_val2 - new_val1) / delta + 1
            return np.linspace(new_val1, new_val2, N)

        N1 = int(np.ceil(height / max(width, height) * 8))
        N2 = int(np.ceil(width / max(width, height) * 8))
        parallels = linspace2(lat_0 - height / 2 / deg2m_lat,
                              lat_0 + height / 2 / deg2m_lat, N1)

        # Old basemap versions have problems with non-integer parallels.
        try:
            bmap.drawparallels(parallels, labels=[0, 1, 1, 0])
        except KeyError:
            parallels = sorted(list(set(map(int, parallels))))
            bmap.drawparallels(parallels, labels=[0, 1, 1, 0])

        if min(lons) < -150 and max(lons) > 150:
            lon_0 %= 360
        meridians = linspace2(lon_0 - width / 2 / deg2m_lon,
                              lon_0 + width / 2 / deg2m_lon, N2)
        meridians[meridians > 180] -= 360
        bmap.drawmeridians(meridians, labels=[1, 0, 0, 1])
    else:
        msg = "Projection '%s' not supported." % projection
        raise ValueError(msg)

    # draw coast lines, country boundaries, fill continents.
    map_ax.set_axis_bgcolor(water_fill_color)
    bmap.drawcoastlines(color="0.4")
    bmap.drawcountries(color="0.75")
    bmap.fillcontinents(color=continent_fill_color,
                        lake_color=water_fill_color)
    # draw the edge of the bmap projection region (the projection limb)
    bmap.drawmapboundary(fill_color=water_fill_color)
    # draw lat/lon grid lines every 30 degrees.
    bmap.drawmeridians(np.arange(-180, 180, 30))
    bmap.drawparallels(np.arange(-90, 90, 30))

    # compute the native bmap projection coordinates for events.
    x, y = bmap(lons, lats)
    # plot labels
    if labels:
        if 100 > len(lons) > 1:
            for name, xpt, ypt, _colorpt in zip(labels, x, y, color):
                # Check if the point can actually be seen with the current bmap
                # projection. The bmap object will set the coordinates to very
                # large values if it cannot project a point.
                if xpt > 1e25:
                    continue
                map_ax.text(xpt, ypt, name, weight="heavy",
                            color="k", zorder=100,
                            path_effects=[
                                PathEffects.withStroke(linewidth=3,
                                                       foreground="white")])
        elif len(lons) == 1:
            map_ax.text(x[0], y[0], labels[0], weight="heavy", color="k",
                        path_effects=[
                            PathEffects.withStroke(linewidth=3,
                                                   foreground="white")])

    # scatter plot is removing valid x/y points with invalid color value,
    # so we plot those points separately.
    try:
        nan_points = np.isnan(np.array(color, dtype=np.float))
    except ValueError:
        # `color' was not a list of values, but a list of colors.
        pass
    else:
        if nan_points.any():
            x_ = np.array(x)[nan_points]
            y_ = np.array(y)[nan_points]
            size_ = np.array(size)[nan_points]
            scatter = bmap.scatter(x_, y_, marker=marker, s=size_, c="0.3",
                                   zorder=10, cmap=None)
    scatter = bmap.scatter(x, y, marker=marker, s=size, c=color,
                           zorder=10, cmap=colormap)

    if title:
        plt.suptitle(title)

    # Only show the colorbar for more than one event.
    if show_colorbar:
        if colorbar_ticklabel_format is not None:
            if isinstance(colorbar_ticklabel_format, (str, native_str)):
                formatter = FormatStrFormatter(colorbar_ticklabel_format)
            elif hasattr(colorbar_ticklabel_format, '__call__'):
                formatter = FuncFormatter(colorbar_ticklabel_format)
            elif isinstance(colorbar_ticklabel_format, Formatter):
                formatter = colorbar_ticklabel_format
            locator = MaxNLocator(5)
        else:
            if datetimeplot:
                locator = AutoDateLocator()
                formatter = AutoDateFormatter(locator)
                # Compat with old matplotlib versions.
                if hasattr(formatter, "scaled"):
                    formatter.scaled[1 / (24. * 60.)] = '%H:%M:%S'
            else:
                locator = None
                formatter = None
        cb = Colorbar(cm_ax, scatter, cmap=colormap,
                      orientation='horizontal',
                      ticks=locator,
                      format=formatter)
        # Compat with old matplotlib versions.
        if hasattr(cb, "update_ticks"):
            cb.update_ticks()

    if show:
        plt.show()

    return fig
示例#8
0
class ColorbarWidget(QWidget):
    colorbarChanged = Signal()  # The parent should simply redraw their canvas
    scaleNormChanged = Signal()
    # register additional color maps from file
    register_customized_colormaps()
    # create the list
    cmap_list = sorted(
        [cmap for cmap in cm.cmap_d.keys() if not cmap.endswith('_r')])

    def __init__(self, parent=None, default_norm_scale=None):
        """
        :param default_scale: None uses linear, else either a string or tuple(string, other arguments), e.g. tuple('Power', exponent)
        """

        super(ColorbarWidget, self).__init__(parent)

        self.setWindowTitle("Colorbar")
        self.setMaximumWidth(100)

        self.cmap = QComboBox()
        self.cmap.addItems(self.cmap_list)
        self.cmap.currentIndexChanged.connect(self.cmap_index_changed)
        self.crev = QCheckBox('Reverse')
        self.crev.stateChanged.connect(self.crev_checked_changed)

        self.cmin = QLineEdit()
        self.cmin_value = 0
        self.cmin.setMaximumWidth(100)
        self.cmin.editingFinished.connect(self.clim_changed)
        self.cmin_layout = QHBoxLayout()
        self.cmin_layout.addStretch()
        self.cmin_layout.addWidget(self.cmin)
        self.cmin_layout.addStretch()

        self.linear_validator = QDoubleValidator(parent=self)
        self.log_validator = QDoubleValidator(MIN_LOG_VALUE,
                                              sys.float_info.max, 3, self)
        self.cmax = QLineEdit()
        self.cmax_value = 1
        self.cmax.setMaximumWidth(100)
        self.cmax.editingFinished.connect(self.clim_changed)
        self.cmax_layout = QHBoxLayout()
        self.cmax_layout.addStretch()
        self.cmax_layout.addWidget(self.cmax)
        self.cmax_layout.addStretch()

        norm_scale = 'Linear'
        powerscale_value = 2
        if default_norm_scale in NORM_OPTS:
            norm_scale = default_norm_scale
        if isinstance(default_norm_scale,
                      tuple) and default_norm_scale[0] in NORM_OPTS:
            norm_scale = default_norm_scale[0]
            if norm_scale == 'Power':
                powerscale_value = float(default_norm_scale[1])

        self.norm_layout = QHBoxLayout()
        self.norm = QComboBox()
        self.norm.addItems(NORM_OPTS)
        self.norm.setCurrentText(norm_scale)
        self.norm.currentIndexChanged.connect(self.norm_changed)
        self.update_clim_validator()

        self.powerscale = QLineEdit()
        self.powerscale_value = powerscale_value
        self.powerscale.setText(str(powerscale_value))
        self.powerscale.setValidator(QDoubleValidator(0.001, 100, 3))
        self.powerscale.setMaximumWidth(50)
        self.powerscale.editingFinished.connect(self.norm_changed)
        self.powerscale_label = QLabel("n=")
        if norm_scale != 'Power':
            self.powerscale.hide()
            self.powerscale_label.hide()

        self.norm_layout.addStretch()
        self.norm_layout.addWidget(self.norm)
        self.norm_layout.addStretch()
        self.norm_layout.addWidget(self.powerscale_label)
        self.norm_layout.addWidget(self.powerscale)

        self.autoscale = QCheckBox("Autoscaling")
        self.autoscale.setChecked(True)
        self.autoscale.stateChanged.connect(self.update_clim)

        self.canvas = FigureCanvas(Figure())
        if parent:
            # Set facecolor to match parent
            self.canvas.figure.set_facecolor(
                parent.palette().window().color().getRgbF())
        self.ax = self.canvas.figure.add_axes([0.0, 0.02, 0.2, 0.97])

        # layout
        self.layout = QVBoxLayout(self)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setSpacing(2)
        self.layout.addWidget(self.cmap)
        self.layout.addWidget(self.crev)
        self.layout.addLayout(self.cmax_layout)
        self.layout.addWidget(self.canvas, stretch=1)
        self.layout.addLayout(self.cmin_layout)
        self.layout.addLayout(self.norm_layout)
        self.layout.addWidget(self.autoscale)

    def set_mappable(self, mappable):
        """
        When a new plot is created this method should be called with the new mappable
        """
        # sanity check the mappable
        mappable = self._validate_mappable(mappable)
        self.ax.clear()
        try:  # Use current cmap
            cmap = get_current_cmap(self.colorbar)
        except AttributeError:
            # else use default
            cmap = ConfigService.getString("plots.images.Colormap")
        self.colorbar = Colorbar(ax=self.ax, mappable=mappable)
        self.cmin_value, self.cmax_value = mappable.get_clim()
        self.update_clim_text()
        self.cmap_changed(cmap, False)

        mappable_cmap = get_current_cmap(mappable)

        if mappable_cmap.name.endswith('_r'):
            self.crev.setChecked(True)
        else:
            self.crev.setChecked(False)
        self.cmap.setCurrentIndex(
            self.cmap_list.index(mappable_cmap.name.replace('_r', '')))

        self.redraw()

    def cmap_index_changed(self):
        self.cmap_changed(self.cmap.currentText(), self.crev.isChecked())

    def crev_checked_changed(self):
        self.cmap_changed(self.cmap.currentText(), self.crev.isChecked())

    def cmap_changed(self, name, rev):
        if rev:
            name += '_r'
        self.colorbar.mappable.set_cmap(name)
        if mpl_version_info() >= (3, 1):
            self.colorbar.update_normal(self.colorbar.mappable)
        else:
            self.colorbar.set_cmap(name)
        self.redraw()

    def mappable_changed(self):
        """
        Updates the colormap and min/max values of the colorbar
        when the plot changes via settings.
        """
        mappable_cmap = get_current_cmap(self.colorbar.mappable)
        low, high = self.colorbar.mappable.get_clim()
        self.cmin_value = low
        self.cmax_value = high
        self.update_clim_text()
        self.cmap.setCurrentIndex(
            sorted(cm.cmap_d.keys()).index(mappable_cmap.name))
        self.redraw()

    def norm_changed(self):
        """
        Called when a different normalization is selected
        """
        idx = self.norm.currentIndex()
        if NORM_OPTS[idx] == 'Power':
            self.powerscale.show()
            self.powerscale_label.show()
        else:
            self.powerscale.hide()
            self.powerscale_label.hide()
        self.colorbar.mappable.set_norm(self.get_norm())
        self.set_mappable(self.colorbar.mappable)
        self.update_clim_validator()
        self.scaleNormChanged.emit()

    def get_norm(self):
        """
        This will create a matplotlib.colors.Normalize from selected idx, limits and powerscale
        """
        idx = self.norm.currentIndex()
        if self.autoscale.isChecked():
            cmin = cmax = None
        else:
            cmin = self.cmin_value
            cmax = self.cmax_value
        if NORM_OPTS[idx] == 'Power':
            if self.powerscale.hasAcceptableInput():
                self.powerscale_value = float(self.powerscale.text())
            return PowerNorm(gamma=self.powerscale_value, vmin=cmin, vmax=cmax)
        elif NORM_OPTS[idx] == "SymmetricLog10":
            return SymLogNorm(
                1e-8 if cmin is None else max(1e-8,
                                              abs(cmin) * 1e-3),
                vmin=cmin,
                vmax=cmax)
        elif NORM_OPTS[idx] == "Log":
            cmin = MIN_LOG_VALUE if cmin is not None and cmin <= 0 else cmin
            return LogNorm(vmin=cmin, vmax=cmax)
        else:
            return Normalize(vmin=cmin, vmax=cmax)

    def get_colorbar_scale(self):
        norm = self.colorbar.norm
        scale = 'linear'
        kwargs = {}
        if isinstance(norm, SymLogNorm):
            scale = 'symlog'
        elif isinstance(norm, LogNorm):
            scale = 'log'
        elif isinstance(norm, PowerNorm):
            scale = 'function'
            kwargs = {
                'functions': (lambda x: np.power(x, norm.gamma),
                              lambda x: np.power(x, 1 / norm.gamma))
            }
        return scale, kwargs

    def clim_changed(self):
        """
        Called when either the min or max is changed. Will unset the autoscale.
        """
        self.autoscale.blockSignals(True)
        self.autoscale.setChecked(False)
        self.autoscale.blockSignals(False)
        self.update_clim()

    def update_clim(self):
        """
        This will update the clim of the plot based on min, max, and autoscale
        """
        if self.autoscale.isChecked():
            self._autoscale_clim()
        else:
            self._manual_clim()

        self.colorbar.mappable.set_clim(self.cmin_value, self.cmax_value)
        self.redraw()

    def update_clim_text(self):
        """
        Update displayed limit values based on stored ones
        """
        self.cmin.setText("{:.4}".format(self.cmin_value))
        self.cmax.setText("{:.4}".format(self.cmax_value))

    def redraw(self):
        """
        Redraws the colobar and emits signal to cause the parent to redraw
        """
        self.colorbar.update_ticks()
        self.colorbar.draw_all()
        self.canvas.draw_idle()
        self.colorbarChanged.emit()

    def update_clim_validator(self):
        if NORM_OPTS[self.norm.currentIndex()] == "Log":
            self.cmin.setValidator(self.log_validator)
            self.cmax.setValidator(self.log_validator)
        else:
            self.cmin.setValidator(self.linear_validator)
            self.cmax.setValidator(self.linear_validator)

    def _autoscale_clim(self):
        """Update stored colorbar limits
        The new limits are found from the colobar data """
        data = self.colorbar.mappable.get_array()
        norm = NORM_OPTS[self.norm.currentIndex()]
        try:
            try:
                masked_data = data[~data.mask]
                # use the smallest positive value as vmin when using log scale,
                # matplotlib will take care of the data skipping part.
                masked_data = masked_data[
                    data > 0] if norm == "Log" else masked_data
                self.cmin_value = masked_data.min()
                self.cmax_value = masked_data.max()
            except (AttributeError, IndexError):
                data = data[np.nonzero(data)] if norm == "Log" else data
                self.cmin_value = np.nanmin(data)
                self.cmax_value = np.nanmax(data)
        except (ValueError, RuntimeWarning):
            # all values mask
            pass
        self.update_clim_text()

    def _manual_clim(self):
        """Update stored colorbar limits
        The new limits are found from user input"""
        if self.cmin.hasAcceptableInput():
            cmin = float(self.cmin.text())
            if cmin < self.cmax_value:
                self.cmin_value = cmin
            else:  # reset values back
                self.update_clim_text()
        if self.cmax.hasAcceptableInput():
            cmax = float(self.cmax.text())
            if cmax > self.cmin_value:
                self.cmax_value = cmax
            else:  # reset values back
                self.update_clim_text()

    def _create_linear_normalize_object(self):
        if self.autoscale.isChecked():
            cmin = cmax = None
        else:
            cmin = self.cmin_value
            cmax = self.cmax_value
        return Normalize(vmin=cmin, vmax=cmax)

    def _validate_mappable(self, mappable):
        """Disable the Log option if no positive value can be found from given data (image)"""
        index = NORM_OPTS.index("Log")
        if mappable.get_array() is not None:
            if np.all(mappable.get_array() <= 0):
                self.norm.model().item(index, 0).setEnabled(False)
                self.norm.setItemData(
                    index, "Log scale is disabled for non-positive data",
                    Qt.ToolTipRole)
                if isinstance(mappable.norm, LogNorm):
                    mappable.norm = self._create_linear_normalize_object()
                    self.norm.blockSignals(True)
                    self.norm.setCurrentIndex(0)
                    self.norm.blockSignals(False)
            else:
                if not self.norm.model().item(index, 0).isEnabled():
                    self.norm.model().item(index, 0).setEnabled(True)
                    self.norm.setItemData(index, "", Qt.ToolTipRole)

        return mappable
示例#9
0
文件: maps.py 项目: johjam/obspy
def plot_basemap(
    lons,
    lats,
    size,
    color,
    labels=None,
    projection="cyl",
    resolution="l",
    continent_fill_color="0.8",
    water_fill_color="1.0",
    colormap=None,
    marker="o",
    title=None,
    colorbar_ticklabel_format=None,
    show=True,
    **kwargs
):  # @UnusedVariable
    """
    Creates a basemap plot with a data point scatter plot.

    :type lons: list/tuple of floats
    :param lons: Longitudes of the data points.
    :type lats: list/tuple of floats
    :param lats: Latitudes of the data points.
    :type size: list/tuple of floats (or a single float)
    :param size: Size of the individual points in the scatter plot.
    :type color: list/tuple of
        floats/:class:`~obspy.core.utcdatetime.UTCDateTime` (or a single float)
    :param color: Color information of the individual data points. Can be
    :type labels: list/tuple of str
    :param labels: Annotations for the individual data points.
    :type projection: str, optional
    :param projection: The map projection. Currently supported are
        * ``"cyl"`` (Will plot the whole world.)
        * ``"ortho"`` (Will center around the mean lat/long.)
        * ``"local"`` (Will plot around local events)
        Defaults to "cyl"
    :type resolution: str, optional
    :param resolution: Resolution of the boundary database to use. Will be
        based directly to the basemap module. Possible values are
        * ``"c"`` (crude)
        * ``"l"`` (low)
        * ``"i"`` (intermediate)
        * ``"h"`` (high)
        * ``"f"`` (full)
        Defaults to ``"l"``
    :type continent_fill_color: Valid matplotlib color, optional
    :param continent_fill_color:  Color of the continents. Defaults to
        ``"0.9"`` which is a light gray.
    :type water_fill_color: Valid matplotlib color, optional
    :param water_fill_color: Color of all water bodies.
        Defaults to ``"white"``.
    :type colormap: str, optional, any matplotlib colormap
    :param colormap: The colormap for color-coding the events.
        The event with the smallest property will have the
        color of one end of the colormap and the event with the biggest
        property the color of the other end with all other events in
        between.
        Defaults to None which will use the default colormap for the date
        encoding and a colormap going from green over yellow to red for the
        depth encoding.
    :type title: str
    :param title: Title above plot.
    :type colorbar_ticklabel_format: str or func or
        subclass of :matplotlib:`matplotlib.ticker.Formatter`
    :param colorbar_ticklabel_format: Format string or Formatter used to format
        colorbar tick labels.
    :type show: bool
    :param show: Whether to show the figure after plotting or not. Can be used
        to do further customization of the plot before showing it.
    """
    min_color = min(color)
    max_color = max(color)

    if isinstance(color[0], (datetime.datetime, UTCDateTime)):
        datetimeplot = True
        color = [date2num(t) for t in color]
    else:
        datetimeplot = False

    scal_map = ScalarMappable(norm=Normalize(min_color, max_color), cmap=colormap)
    scal_map.set_array(np.linspace(0, 1, 1))

    fig = plt.figure()
    # The colorbar should only be plotted if more then one event is
    # present.

    if len(lons) > 1 and hasattr(color, "__len__") and not isinstance(color, (str, native_str)):
        show_colorbar = True
    else:
        show_colorbar = False

    if projection == "local":
        ax_x0, ax_width = 0.10, 0.80
    else:
        ax_x0, ax_width = 0.05, 0.90

    if show_colorbar:
        map_ax = fig.add_axes([ax_x0, 0.13, ax_width, 0.77])
        cm_ax = fig.add_axes([ax_x0, 0.05, ax_width, 0.05])
        plt.sca(map_ax)
    else:
        map_ax = fig.add_axes([ax_x0, 0.05, ax_width, 0.85])

    if projection == "cyl":
        bmap = Basemap(resolution=resolution)
    elif projection == "ortho":
        bmap = Basemap(
            projection="ortho", resolution=resolution, area_thresh=1000.0, lat_0=np.mean(lats), lon_0=np.mean(lons)
        )
    elif projection == "local":
        if min(lons) < -150 and max(lons) > 150:
            max_lons = max(np.array(lons) % 360)
            min_lons = min(np.array(lons) % 360)
        else:
            max_lons = max(lons)
            min_lons = min(lons)
        lat_0 = (max(lats) + min(lats)) / 2.0
        lon_0 = (max_lons + min_lons) / 2.0
        if lon_0 > 180:
            lon_0 -= 360
        deg2m_lat = 2 * np.pi * 6371 * 1000 / 360
        deg2m_lon = deg2m_lat * np.cos(lat_0 / 180 * np.pi)
        if len(lats) > 1:
            height = (max(lats) - min(lats)) * deg2m_lat
            width = (max_lons - min_lons) * deg2m_lon
            margin = 0.2 * (width + height)
            height += margin
            width += margin
        else:
            height = 2.0 * deg2m_lat
            width = 5.0 * deg2m_lon

        bmap = Basemap(
            projection="aeqd",
            resolution=resolution,
            area_thresh=1000.0,
            lat_0=lat_0,
            lon_0=lon_0,
            width=width,
            height=height,
        )
        # not most elegant way to calculate some round lats/lons

        def linspace2(val1, val2, N):
            """
            returns around N 'nice' values between val1 and val2
            """
            dval = val2 - val1
            round_pos = int(round(-np.log10(1.0 * dval / N)))
            delta = round(2.0 * dval / N, round_pos) / 2
            new_val1 = np.ceil(val1 / delta) * delta
            new_val2 = np.floor(val2 / delta) * delta
            N = (new_val2 - new_val1) / delta + 1
            return np.linspace(new_val1, new_val2, N)

        N1 = int(np.ceil(height / max(width, height) * 8))
        N2 = int(np.ceil(width / max(width, height) * 8))
        bmap.drawparallels(
            linspace2(lat_0 - height / 2 / deg2m_lat, lat_0 + height / 2 / deg2m_lat, N1), labels=[0, 1, 1, 0]
        )
        if min(lons) < -150 and max(lons) > 150:
            lon_0 %= 360
        meridians = linspace2(lon_0 - width / 2 / deg2m_lon, lon_0 + width / 2 / deg2m_lon, N2)
        meridians[meridians > 180] -= 360
        bmap.drawmeridians(meridians, labels=[1, 0, 0, 1])
    else:
        msg = "Projection '%s' not supported." % projection
        raise ValueError(msg)

    # draw coast lines, country boundaries, fill continents.
    plt.gca().set_axis_bgcolor(water_fill_color)
    bmap.drawcoastlines(color="0.4")
    bmap.drawcountries(color="0.75")
    bmap.fillcontinents(color=continent_fill_color, lake_color=water_fill_color)
    # draw the edge of the bmap projection region (the projection limb)
    bmap.drawmapboundary(fill_color=water_fill_color)
    # draw lat/lon grid lines every 30 degrees.
    bmap.drawmeridians(np.arange(-180, 180, 30))
    bmap.drawparallels(np.arange(-90, 90, 30))

    # compute the native bmap projection coordinates for events.
    x, y = bmap(lons, lats)
    # plot labels
    if labels:
        if 100 > len(lons) > 1:
            for name, xpt, ypt, colorpt in zip(labels, x, y, color):
                # Check if the point can actually be seen with the current bmap
                # projection. The bmap object will set the coordinates to very
                # large values if it cannot project a point.
                if xpt > 1e25:
                    continue
                plt.text(
                    xpt,
                    ypt,
                    name,
                    weight="heavy",
                    color="k",
                    zorder=100,
                    path_effects=[PathEffects.withStroke(linewidth=3, foreground="white")],
                )
        elif len(lons) == 1:
            plt.text(
                x[0],
                y[0],
                labels[0],
                weight="heavy",
                color="k",
                path_effects=[PathEffects.withStroke(linewidth=3, foreground="white")],
            )

    scatter = bmap.scatter(x, y, marker=marker, s=size, c=color, zorder=10, cmap=colormap)

    if title:
        plt.suptitle(title)

    # Only show the colorbar for more than one event.
    if show_colorbar:
        if colorbar_ticklabel_format is not None:
            if isinstance(colorbar_ticklabel_format, (str, native_str)):
                formatter = FormatStrFormatter(colorbar_ticklabel_format)
            elif hasattr(colorbar_ticklabel_format, "__call__"):
                formatter = FuncFormatter(colorbar_ticklabel_format)
            elif isinstance(colorbar_ticklabel_format, Formatter):
                formatter = colorbar_ticklabel_format
            locator = MaxNLocator(5)
        else:
            if datetimeplot:
                locator = AutoDateLocator()
                formatter = AutoDateFormatter(locator)
                formatter.scaled[1 / (24.0 * 60.0)] = "%H:%M:%S"
            else:
                locator = None
                formatter = None
        cb = Colorbar(cm_ax, scatter, cmap=colormap, orientation="horizontal", ticks=locator, format=formatter)
        # format=formatter)
        # ticks=mpl.ticker.MaxNLocator(4))
        cb.update_ticks()

    if show:
        plt.show()

    return fig
示例#10
0
def AnimateDiameterAndRawData_Big2(rawframes, static_background, rawframes_pre,
                                   sizes_df_lin, traj, ParameterJsonFile):
    from matplotlib.gridspec import GridSpec

    settings = nd.handle_data.ReadJson(ParameterJsonFile)

    fps = settings["Exp"]["fps"]

    my_gamma = settings["Animation"]["gamma"]
    microns_per_pixel = settings["Exp"]["Microns_per_pixel"]
    frames_tot = settings["Animation"]["frames_tot"]
    num_points_pdf = 100

    # Diameter plot
    histogramm_min = settings["Plot"]["Histogramm_min"]
    histogramm_max = settings["Plot"]["Histogramm_max"]

    diam_grid = np.linspace(histogramm_min, histogramm_max, 1000)
    diam_grid_inv = 1 / diam_grid

    # here comes the font sizes
    global my_font_size
    my_font_size = 16
    my_font_size_title = 22

    global prob_inv_diam_sum
    prob_inv_diam_sum = np.zeros(num_points_pdf)

    # get min and max particle id
    part_id_min = np.min(traj.particle)
    part_id_max = np.max(traj.particle)

    # get min and max diameter
    diam_max = np.round(np.max(sizes_df_lin.diameter) + 5, -1)
    diam_min = np.round(np.min(sizes_df_lin.diameter) - 5, -1)

    # get particle id of TRAJECTORIES in the roi
    #    particle_id_traj = traj[(traj.x > 800) & (traj.x < 1800)].particle.unique()
    particle_id_traj = traj.particle.unique()

    #get traj in ROI
    traj_roi = traj[np.isin(traj.particle, particle_id_traj)]

    frame = 0
    # get trajectory of particles in current frame
    traj_roi_history = GetTrajHistory(frame, traj_roi)

    # get position and diameter of evaluated particles
    pos_roi, sizes_df_lin_frame = GetPosEvaluated(frame, traj_roi,
                                                  sizes_df_lin)

    # design the subplot
    fig = plt.figure(figsize=[25, 13], constrained_layout=True)

    #    gs = GridSpec(6, 3, figure=fig, width_ratios = [0.5,0.5,0.2])
    gs = GridSpec(12,
                  5,
                  figure=fig,
                  width_ratios=[1] * 2 + [0.15] * 3,
                  height_ratios=[1 / 2] * (2 * 3) + [1] * 2 + [1.5] +
                  [0.5] * 3)

    ax_raw = fig.add_subplot(gs[0:2, 0:2], aspect="equal")  # raw image
    ax_bg = fig.add_subplot(gs[2:4, 0:2],
                            aspect="equal",
                            sharex=ax_raw,
                            sharey=ax_raw)  # background
    ax_pp = fig.add_subplot(gs[4:6, 0:2],
                            aspect="equal",
                            sharex=ax_raw,
                            sharey=ax_raw)  # post-processed image
    ax_traj = fig.add_subplot(gs[6, 0:2],
                              aspect="equal",
                              sharex=ax_raw,
                              sharey=ax_raw)  # trajectories
    ax_eval = fig.add_subplot(gs[7, 0:2],
                              aspect="equal",
                              sharex=ax_raw,
                              sharey=ax_raw)  # particles colour in diameter

    ax_hist = fig.add_subplot(gs[8, 0])  # histogram of current frame
    ax_hist_cum = fig.add_subplot(gs[8, 1], sharex=ax_hist,
                                  sharey=ax_hist)  # summed histogram

    # axis for the colorbars / legends
    c_ax_raw = plt.subplot(gs[0, 2:5])
    c_ax_bg = plt.subplot(gs[2, 2:5])
    c_ax_pp = plt.subplot(gs[4, 2:5])
    c_ax_traj = plt.subplot(gs[6, 2:5])
    c_ax_eval = plt.subplot(gs[7, 2:5])

    # axis for min, max and gamma values
    ax_raw_min = plt.subplot(gs[1, 2])
    ax_raw_max = plt.subplot(gs[1, 3])
    ax_raw_g = plt.subplot(gs[1, 4])

    ax_bg_min = plt.subplot(gs[3, 2])
    ax_bg_max = plt.subplot(gs[3, 3])
    ax_bg_g = plt.subplot(gs[3, 4])

    ax_pp_min = plt.subplot(gs[5, 2])
    ax_pp_max = plt.subplot(gs[5, 3])
    ax_pp_g = plt.subplot(gs[5, 4])

    #here come the sliders
    slider_frame_ax = plt.subplot(gs[9, 0:2])
    slider_x_min_ax = plt.subplot(gs[10, 0])
    slider_x_max_ax = plt.subplot(gs[11, 0])
    slider_y_min_ax = plt.subplot(gs[10, 1])
    slider_y_max_ax = plt.subplot(gs[11, 1])

    # plot the stuff
    import matplotlib.colors as colors
    raw_image = ax_raw.imshow(rawframes[0, :, :],
                              cmap='gray',
                              norm=colors.PowerNorm(gamma=my_gamma),
                              animated=True,
                              vmin=0,
                              vmax=np.max(rawframes))

    bg_image = ax_bg.imshow(static_background,
                            cmap='gray',
                            norm=colors.PowerNorm(gamma=my_gamma),
                            animated=True,
                            vmin=0,
                            vmax=np.max(static_background))

    pp_image = ax_pp.imshow(rawframes_pre[0, :, :],
                            cmap='gray',
                            norm=colors.PowerNorm(gamma=my_gamma),
                            animated=True,
                            vmin=np.min(rawframes_pre),
                            vmax=np.max(rawframes_pre))

    ax_scatter_traj = ax_traj.scatter(traj_roi_history.x,
                                      traj_roi_history.y,
                                      s=3,
                                      c=traj_roi_history.particle,
                                      cmap='gist_ncar',
                                      alpha=1,
                                      vmin=0,
                                      vmax=part_id_max)

    #    ax_scatter_traj = ax_traj.scatter(traj_roi_history.x, traj_roi_history.y, s = 3, c = traj_roi_history.particle, cmap = 'gist_ncar', alpha = 1, vmin=part_id_min, vmax=part_id_max)

    ax_scatter_diam = ax_eval.scatter(pos_roi.x,
                                      pos_roi.y,
                                      c=sizes_df_lin_frame.diameter,
                                      cmap='gist_ncar',
                                      vmin=diam_min,
                                      vmax=diam_max)

    # add titles and labels
    ax_raw.set_title('raw-data', fontsize=my_font_size_title)
    ax_raw.set_ylabel('y-Position [px]', fontsize=my_font_size)

    ax_bg.set_title('Background and stationary particles',
                    fontsize=my_font_size_title)
    ax_bg.set_ylabel('y-Position [px]', fontsize=my_font_size)

    ax_pp.set_title('Processed image', fontsize=my_font_size_title)
    ax_pp.set_ylabel('y-Position [px]', fontsize=my_font_size)

    ax_traj.set_title('trajectory', fontsize=my_font_size_title)
    ax_traj.set_ylabel('y-Position [px]', fontsize=my_font_size)

    ax_eval.set_title('Diameter of each particle', fontsize=my_font_size_title)
    ax_eval.set_ylabel('y-Position [px]', fontsize=my_font_size)
    ax_eval.set_xlabel('x-Position [px]', fontsize=my_font_size)

    # COLORBARS
    from matplotlib.colorbar import Colorbar

    cb_raw = Colorbar(ax=c_ax_raw,
                      mappable=raw_image,
                      orientation='horizontal',
                      ticklocation='top')
    cb_raw.set_label("Brightness", fontsize=my_font_size)

    cb_bg = Colorbar(ax=c_ax_bg,
                     mappable=bg_image,
                     orientation='horizontal',
                     ticklocation='top')
    cb_bg.set_label("Brightness", fontsize=my_font_size)

    cb_pp = Colorbar(ax=c_ax_pp,
                     mappable=pp_image,
                     orientation='horizontal',
                     ticklocation='top')
    cb_pp.set_label("Brightness", fontsize=my_font_size)

    cb_traj = Colorbar(ax=c_ax_traj,
                       mappable=ax_scatter_traj,
                       orientation='horizontal',
                       ticklocation='top')
    cb_traj.set_label("Particle ID", fontsize=my_font_size)

    cb_eval = Colorbar(ax=c_ax_eval,
                       mappable=ax_scatter_diam,
                       orientation='horizontal',
                       ticklocation='top')
    cb_eval.set_label("Diameter [nm]", fontsize=my_font_size)

    from matplotlib import ticker
    cb_raw.locator = ticker.MaxNLocator(nbins=3)
    cb_raw.update_ticks()

    cb_bg.locator = ticker.MaxNLocator(nbins=3)
    cb_bg.update_ticks()

    cb_pp.locator = ticker.MaxNLocator(nbins=3)
    cb_pp.update_ticks()

    cb_traj.locator = ticker.MaxNLocator(nbins=5)
    cb_traj.update_ticks()

    cb_eval.locator = ticker.MaxNLocator(nbins=5)
    cb_eval.update_ticks()

    # Here come the two histograms
    line_diam_frame, = ax_hist.plot(diam_grid, np.zeros_like(diam_grid))
    line_diam_sum, = ax_hist_cum.plot(diam_grid, np.zeros_like(diam_grid))

    # label and title
    ax_hist.set_xlabel('Diameter [nm]', fontsize=my_font_size)
    ax_hist.set_ylabel('Occurance', fontsize=my_font_size)
    ax_hist.set_title("Live Histogram", fontsize=my_font_size_title)

    ax_hist_cum.set_xlabel('Diameter [nm]', fontsize=my_font_size)
    ax_hist_cum.set_ylabel('Occurance', fontsize=my_font_size)
    ax_hist_cum.set_title("Cummulated Histogram", fontsize=my_font_size_title)

    # limits
    ax_hist.set_xlim([histogramm_min, histogramm_max])
    ax_hist.set_ylim([0, 1.1])
    ax_hist.set_yticks([])
    ax_hist.tick_params(direction='out')

    # Global PDF
    inv_diam, inv_diam_std = nd.CalcDiameter.InvDiameter(
        sizes_df_lin, settings)

    prob_inv_diam = np.zeros_like(diam_grid_inv)

    for index, (loop_mean, loop_std, weight) in enumerate(
            zip(inv_diam, inv_diam_std, sizes_df_lin["traj length"])):
        #loop through all evaluated partices in that roi and frame

        #calc probability density function (PDF)
        my_pdf = scipy.stats.norm(loop_mean, loop_std).pdf(diam_grid_inv)

        # normalized nad weight
        my_pdf = my_pdf / np.sum(my_pdf) * weight

        #add up all PDFs
        prob_inv_diam = prob_inv_diam + my_pdf

    #normalized to 1
    prob_inv_diam_show = prob_inv_diam / np.max(prob_inv_diam)

    line_diam_sum.set_ydata(prob_inv_diam_show)

    def animate(frame, x_min, x_max, y_min, y_max, UpdateFrame):
        global ColorbarDone
        print("\nframe", frame)
        print("x_min", x_min)
        print("x_max", x_max)
        print("y_min", y_min)
        print("y_max", y_max)
        print("Update Frame", UpdateFrame)

        # select new frame if required
        if UpdateFrame == True:
            rawframes_frame = rawframes[frame, :, :]
            rawframes_pp_frame = rawframes_pre[frame, :, :]

            raw_image.set_data(rawframes_frame)
            bg_image.set_data(static_background)
            pp_image.set_data(rawframes_pp_frame)

        # SET AXES
        ax_raw.set_xlim([x_min, x_max])
        ax_raw.set_ylim([y_min, y_max])

        ax_raw.tick_params(direction='out')

        # make the labels in um
        num_x_ticks = 5
        num_y_ticks = 3

        x_ticks_px = np.round(
            np.linspace(x_min, x_max, num_x_ticks, dtype='int'), -2)
        y_ticks_px = np.round(
            np.linspace(y_min, y_max, num_y_ticks, dtype='int'), -1)

        ax_raw.set_xticks(x_ticks_px)
        ax_raw.set_xticklabels(x_ticks_px)

        ax_raw.set_yticks(y_ticks_px)
        ax_raw.set_yticklabels(y_ticks_px)

        # get particle id of TRAJECTORIES in the roi
        particle_id_traj = traj[(traj.x > x_min)
                                & (traj.x < x_max)].particle.unique()

        #get traj in ROI
        traj_roi = traj[traj.particle.isin(particle_id_traj)]

        # get trajectory of particles in current frame
        traj_roi_history = GetTrajHistory(frame, traj_roi)

        # get position and diameter of evaluated particles
        pos_roi, sizes_df_lin_roi_frame = GetPosEvaluated(
            frame, traj_roi, sizes_df_lin)

        #update figure
        time_ms = frame * (1 / fps) * 1000
        time_ms = np.round(time_ms, 1)

        fig.suptitle('frame: ' + str(frame) + '; time: ' + str(time_ms) +
                     ' ms',
                     fontsize=my_font_size_title)

        ax_scatter_traj.set_offsets(
            np.transpose(
                np.asarray(
                    [traj_roi_history.x.values, traj_roi_history.y.values])))
        ax_scatter_traj.set_array(traj_roi_history.particle)

        ax_scatter_diam.set_offsets(
            np.transpose(np.asarray([pos_roi.x.values, pos_roi.y.values])))
        ax_scatter_diam.set_array(sizes_df_lin_roi_frame.diameter)

        ## DIAMETER PDF FROM PREVIOUS POINTS
        sizes_df_lin_roi_frame = sizes_df_lin_roi_frame.sort_index()

        # get inverse diameter which is normal distributed (proportional to the diffusion)
        inv_diam, inv_diam_std = nd.CalcDiameter.InvDiameter(
            sizes_df_lin_roi_frame, settings)

        # probability of inverse diameter
        prob_inv_diam = np.zeros_like(diam_grid_inv)

        for index, (loop_mean,
                    loop_std) in enumerate(zip(inv_diam, inv_diam_std)):
            #loop through all evaluated partices in that roi and frame

            #calc probability density function (PDF)
            my_pdf = scipy.stats.norm(loop_mean, loop_std).pdf(diam_grid_inv)

            # normalized
            my_pdf = my_pdf / np.sum(my_pdf)

            #add up all PDFs
            prob_inv_diam = prob_inv_diam + my_pdf

        #normalized to 1
        if np.max(prob_inv_diam) > 0:
            prob_inv_diam_show = prob_inv_diam / np.max(prob_inv_diam)
        else:
            prob_inv_diam_show = prob_inv_diam

        line_diam_frame.set_ydata(prob_inv_diam_show)

        #
        #
        #
        #        ## ACCUMULATED DIAMETER PDF
        #        #normalized to 1
        #        prob_inv_diam_sum_show = prob_inv_diam_sum / np.max(prob_inv_diam_sum)
        #
        #        line_diam_sum.set_ydata(prob_inv_diam_sum_show)

        print("Animation updated")

        return raw_image

    # Functions for Update the ROI and brightness
    def UpdateFrame(val):
        UpdateFrame = True
        UpdateAnimation(UpdateFrame, val)

    def UpdateROI(val):
        UpdateFrame = False
        UpdateAnimation(UpdateFrame, val)

    def UpdateAnimation(UpdateROI, val):
        frame = int(slider_frame.val)
        x_min = int(slider_x_min.val)
        x_max = int(slider_x_max.val)
        y_min = int(slider_y_min.val)
        y_max = int(slider_y_max.val)

        animate(frame, x_min, x_max, y_min, y_max, UpdateROI)
        plt.draw()

    def UpdateColorbarRawimage(stuff):
        v_min = np.int(textbox_raw_min.text)
        v_max = np.int(textbox_raw_max.text)
        my_gamma = np.double(textbox_raw_g.text)

        print("\n v_min = ", v_min)
        print("v_max = ", v_max)
        print("gamma = ", my_gamma)

        raw_image.set_norm(colors.PowerNorm(gamma=my_gamma))
        raw_image.set_clim([v_min, v_max])

        cb_raw = Colorbar(ax=c_ax_raw,
                          mappable=raw_image,
                          orientation='horizontal',
                          ticklocation='top')
        cb_raw.locator = ticker.MaxNLocator(nbins=3)
        cb_raw.update_ticks()

    def UpdateColorbarBg(stuff):
        v_min = np.int(textbox_bg_min.text)
        v_max = np.int(textbox_bg_max.text)
        my_gamma = np.double(textbox_bg_g.text)

        print("\n v_min = ", v_min)
        print("v_max = ", v_max)
        print("gamma = ", my_gamma)

        bg_image.set_norm(colors.PowerNorm(gamma=my_gamma))
        bg_image.set_clim([v_min, v_max])

        cb_bg = Colorbar(ax=c_ax_bg,
                         mappable=bg_image,
                         orientation='horizontal',
                         ticklocation='top')
        cb_bg.locator = ticker.MaxNLocator(nbins=3)
        cb_bg.update_ticks()

    def UpdateColorbarPP(stuff):
        v_min = np.int(textbox_pp_min.text)
        v_max = np.int(textbox_pp_max.text)
        my_gamma = np.double(textbox_pp_g.text)

        print("\n v_min = ", v_min)
        print("v_max = ", v_max)
        print("gamma = ", my_gamma)

        pp_image.set_norm(colors.PowerNorm(gamma=my_gamma))
        pp_image.set_clim([v_min, v_max])

        cb_pp = Colorbar(ax=c_ax_pp,
                         mappable=pp_image,
                         orientation='horizontal',
                         ticklocation='top')
        cb_pp.locator = ticker.MaxNLocator(nbins=3)
        cb_pp.update_ticks()


#    anim = animation.FuncAnimation(fig, animate, init_func=init, frames = 100, interval=100, blit=True, repeat=False)

#    anim = animation.FuncAnimation(fig, animate, frames = 1000, interval = 10, repeat = False)

    min_frame = int(traj_roi.frame.min())
    max_frame = int(traj_roi.frame.max())
    show_frames = np.linspace(min_frame, max_frame, frames_tot, dtype='int')

    Do_Save = True

    # HERE COME THE TEXTBOXES AND SLIDERS
    from matplotlib.widgets import Slider, Button, TextBox
    #raw image
    textbox_raw_min = TextBox(ax_raw_min,
                              "min: ",
                              initial=str(np.min(rawframes[0, :, :])),
                              hovercolor="y")
    textbox_raw_min.on_submit(UpdateColorbarRawimage)

    textbox_raw_max = TextBox(ax_raw_max,
                              "max: ",
                              initial=str(np.max(rawframes[0, :, :])),
                              hovercolor="y")
    textbox_raw_max.on_submit(UpdateColorbarRawimage)

    textbox_raw_g = TextBox(ax_raw_g,
                            "gamma: ",
                            initial=str(my_gamma),
                            hovercolor="y")
    textbox_raw_g.on_submit(UpdateColorbarRawimage)

    #bg
    textbox_bg_min = TextBox(ax_bg_min,
                             "min: ",
                             initial=str(np.int(np.min(static_background))),
                             hovercolor="y")
    textbox_bg_min.on_submit(UpdateColorbarBg)

    textbox_bg_max = TextBox(ax_bg_max,
                             "max: ",
                             initial=str(np.int(np.max(static_background))),
                             hovercolor="y")
    textbox_bg_max.on_submit(UpdateColorbarBg)

    textbox_bg_g = TextBox(ax_bg_g,
                           "gamma: ",
                           initial=str(my_gamma),
                           hovercolor="y")
    textbox_bg_g.on_submit(UpdateColorbarBg)

    #preproccesd (pp)
    textbox_pp_min = TextBox(ax_pp_min,
                             "min: ",
                             initial=str(np.int(np.min(
                                 rawframes_pre[0, :, :]))),
                             hovercolor="y")
    textbox_pp_min.on_submit(UpdateColorbarPP)

    textbox_pp_max = TextBox(ax_pp_max,
                             "max: ",
                             initial=str(np.int(np.max(
                                 rawframes_pre[0, :, :]))),
                             hovercolor="y")
    textbox_pp_max.on_submit(UpdateColorbarPP)

    textbox_pp_g = TextBox(ax_pp_g,
                           "gamma: ",
                           initial=str(my_gamma),
                           hovercolor="y")
    textbox_pp_g.on_submit(UpdateColorbarPP)

    # sliders
    frame_max = rawframes.shape[0] - 1
    x_max_max = rawframes.shape[2] - 1
    y_max_max = rawframes.shape[1] - 1

    slider_frame = Slider(slider_frame_ax,
                          "Frame: ",
                          valmin=0,
                          valmax=frame_max,
                          valinit=0,
                          valstep=1)
    slider_x_min = Slider(slider_x_min_ax,
                          "x_min: ",
                          valmin=0,
                          valmax=x_max_max,
                          valinit=0,
                          valstep=1)
    slider_x_max = Slider(slider_x_max_ax,
                          "x_max: ",
                          valmin=0,
                          valmax=x_max_max,
                          valinit=x_max_max,
                          valstep=1,
                          slidermin=slider_x_min)
    slider_y_min = Slider(slider_y_min_ax,
                          "y_min: ",
                          valmin=0,
                          valmax=y_max_max,
                          valinit=0,
                          valstep=1)
    slider_y_max = Slider(slider_y_max_ax,
                          "y_max: ",
                          valmin=0,
                          valmax=y_max_max,
                          valinit=y_max_max,
                          valstep=1,
                          slidermin=slider_y_min)

    slider_frame.on_changed(UpdateFrame)
    slider_x_min.on_changed(UpdateROI)
    slider_x_max.on_changed(UpdateROI)
    slider_y_min.on_changed(UpdateROI)
    slider_y_max.on_changed(UpdateROI)

    plt.show()

    #    if Do_Save == True:
    #        anim = animation.FuncAnimation(fig, animate, frames = show_frames, init_func=init, interval = 0, repeat = False)
    #        anim.save('200204_2.html', writer = 'html', fps=1)
    #
    #    else:
    #        anim = animation.FuncAnimation(fig, animate, frames = show_frames, init_func=init, interval = 5, repeat = True)

    #    return anim

    return
示例#11
0
def add_ortho(lats,
              lons,
              colors,
              CClim,
              central_longitude,
              central_latitude,
              text=None,
              size=50,
              marker=['o', 'd'],
              colormap='viridis',
              fig=None,
              rect=[0.0, 0.0, 1.0, 1.0]):
    if not fig:
        fig = plt.figure()

    proj = ccrs.Orthographic(central_longitude=central_longitude,
                             central_latitude=central_latitude)

    # left, bottom, width, height
    ax = fig.add_axes(
        [rect[0], rect[1] + rect[3] * 0.12, rect[2], rect[3] * 0.85],
        projection=proj)
    cm_ax = fig.add_axes([rect[0], rect[1], rect[2], rect[3] * 0.08])
    plt.sca(ax)

    # make the map global rather than have it zoom in to
    # the extents of any plotted data
    ax.set_global()

    ax.stock_img()
    ax.coastlines()
    ax.gridlines()

    lats_mark1 = []
    lons_mark1 = []
    colors_mark1 = []
    lats_mark2 = []
    lons_mark2 = []
    colors_mark2 = []

    cmap = get_cmap(colormap)
    cmap.set_under('grey')

    for lon, lat, color in zip(lons, lats, colors):
        if color > CClim:
            lats_mark1.append(lat)
            lons_mark1.append(lon)
            colors_mark1.append(color)
        else:
            lats_mark2.append(lat)
            lons_mark2.append(lon)
            colors_mark2.append(color)

    if len(lons_mark1) > 0:
        scatter = ax.scatter(lons_mark1,
                             lats_mark1,
                             s=size,
                             c=colors_mark1,
                             marker=marker[0],
                             cmap=cmap,
                             vmin=CClim,
                             vmax=1,
                             zorder=10,
                             transform=ccrs.Geodetic())

    if len(lons_mark2) > 0:
        scatter = ax.scatter(lons_mark2,
                             lats_mark2,
                             s=size,
                             c=colors_mark2,
                             marker=marker[1],
                             cmap=cmap,
                             vmin=CClim,
                             vmax=1,
                             zorder=10,
                             transform=ccrs.Geodetic())

    locator = MaxNLocator(5)

    cb = Colorbar(cm_ax,
                  scatter,
                  cmap=cmap,
                  orientation='horizontal',
                  ticks=locator,
                  extend='min')
    cb.set_label('CC')
    # Compat with old matplotlib versions.
    if hasattr(cb, "update_ticks"):
        cb.update_ticks()

    ax.plot(central_longitude,
            central_latitude,
            color='red',
            marker='*',
            markersize=np.sqrt(size))

    if (text):
        for lat, lon, text in zip(lats, lons, text):
            # Avoid plotting invisible texts. They clutter at the origin
            # otherwise
            dist = locations2degrees(lat, lon, central_latitude,
                                     central_longitude)
            if (dist < 90):
                plt.text(lon,
                         lat,
                         text,
                         weight="heavy",
                         transform=ccrs.Geodetic(),
                         color="k",
                         zorder=100,
                         path_effects=[
                             PathEffects.withStroke(linewidth=3,
                                                    foreground="white")
                         ])

    return ax
示例#12
0
文件: maps.py 项目: kjdavidson/obspy
def plot_basemap(lons,
                 lats,
                 size,
                 color,
                 labels=None,
                 projection='cyl',
                 resolution='l',
                 continent_fill_color='0.8',
                 water_fill_color='1.0',
                 colormap=None,
                 colorbar=None,
                 marker="o",
                 title=None,
                 colorbar_ticklabel_format=None,
                 show=True,
                 **kwargs):  # @UnusedVariable
    """
    Creates a basemap plot with a data point scatter plot.

    :type lons: list/tuple of floats
    :param lons: Longitudes of the data points.
    :type lats: list/tuple of floats
    :param lats: Latitudes of the data points.
    :type size: float or list/tuple of floats
    :param size: Size of the individual points in the scatter plot.
    :type color: list/tuple of floats (or objects that can be
        converted to floats, like e.g.
        :class:`~obspy.core.utcdatetime.UTCDateTime`)
    :param color: Color information of the individual data points to be
        used in the specified color map (e.g. origin depths,
        origin times).
    :type labels: list/tuple of str
    :param labels: Annotations for the individual data points.
    :type projection: str, optional
    :param projection: The map projection. Currently supported are
        * ``"cyl"`` (Will plot the whole world.)
        * ``"ortho"`` (Will center around the mean lat/long.)
        * ``"local"`` (Will plot around local events)
        Defaults to "cyl"
    :type resolution: str, optional
    :param resolution: Resolution of the boundary database to use. Will be
        based directly to the basemap module. Possible values are
        * ``"c"`` (crude)
        * ``"l"`` (low)
        * ``"i"`` (intermediate)
        * ``"h"`` (high)
        * ``"f"`` (full)
        Defaults to ``"l"``
    :type continent_fill_color: Valid matplotlib color, optional
    :param continent_fill_color:  Color of the continents. Defaults to
        ``"0.9"`` which is a light gray.
    :type water_fill_color: Valid matplotlib color, optional
    :param water_fill_color: Color of all water bodies.
        Defaults to ``"white"``.
    :type colormap: str, any matplotlib colormap, optional
    :param colormap: The colormap for color-coding the events as provided
        in `color` kwarg.
        The event with the smallest `color` property will have the
        color of one end of the colormap and the event with the highest
        `color` property the color of the other end with all other events
        in between.
        Defaults to None which will use the default matplotlib colormap.
    :type colorbar: bool, optional
    :param colorbar: When left `None`, a colorbar is plotted if more than one
        object is plotted. Using `True`/`False` the colorbar can be forced
        on/off.
    :type title: str
    :param title: Title above plot.
    :type colorbar_ticklabel_format: str or function or
        subclass of :class:`matplotlib.ticker.Formatter`
    :param colorbar_ticklabel_format: Format string or Formatter used to format
        colorbar tick labels.
    :type show: bool
    :param show: Whether to show the figure after plotting or not. Can be used
        to do further customization of the plot before showing it.
    """
    min_color = min(color)
    max_color = max(color)

    if isinstance(color[0], (datetime.datetime, UTCDateTime)):
        datetimeplot = True
        color = [date2num(t) for t in color]
    else:
        datetimeplot = False

    scal_map = ScalarMappable(norm=Normalize(min_color, max_color),
                              cmap=colormap)
    scal_map.set_array(np.linspace(0, 1, 1))

    fig = plt.figure()
    # The colorbar should only be plotted if more then one event is
    # present.

    if colorbar is not None:
        show_colorbar = colorbar
    else:
        if len(lons) > 1 and hasattr(color, "__len__") and \
                not isinstance(color, (str, native_str)):
            show_colorbar = True
        else:
            show_colorbar = False

    if projection == "local":
        ax_x0, ax_width = 0.10, 0.80
    else:
        ax_x0, ax_width = 0.05, 0.90

    if show_colorbar:
        map_ax = fig.add_axes([ax_x0, 0.13, ax_width, 0.77])
        cm_ax = fig.add_axes([ax_x0, 0.05, ax_width, 0.05])
        plt.sca(map_ax)
    else:
        ax_y0, ax_height = 0.05, 0.85
        if projection == "local":
            ax_y0 += 0.05
            ax_height -= 0.05
        map_ax = fig.add_axes([ax_x0, ax_y0, ax_width, ax_height])

    if projection == 'cyl':
        bmap = Basemap(resolution=resolution)
    elif projection == 'ortho':
        bmap = Basemap(projection='ortho',
                       resolution=resolution,
                       area_thresh=1000.0,
                       lat_0=np.mean(lats),
                       lon_0=np.mean(lons))
    elif projection == 'local':
        if min(lons) < -150 and max(lons) > 150:
            max_lons = max(np.array(lons) % 360)
            min_lons = min(np.array(lons) % 360)
        else:
            max_lons = max(lons)
            min_lons = min(lons)
        lat_0 = max(lats) / 2. + min(lats) / 2.
        lon_0 = max_lons / 2. + min_lons / 2.
        if lon_0 > 180:
            lon_0 -= 360
        deg2m_lat = 2 * np.pi * 6371 * 1000 / 360
        deg2m_lon = deg2m_lat * np.cos(lat_0 / 180 * np.pi)
        if len(lats) > 1:
            height = (max(lats) - min(lats)) * deg2m_lat
            width = (max_lons - min_lons) * deg2m_lon
            margin = 0.2 * (width + height)
            height += margin
            width += margin
        else:
            height = 2.0 * deg2m_lat
            width = 5.0 * deg2m_lon
        # do intelligent aspect calculation for local projection
        # adjust to figure dimensions
        w, h = fig.get_size_inches()
        aspect = w / h
        if show_colorbar:
            aspect *= 1.2
        if width / height < aspect:
            width = height * aspect
        else:
            height = width / aspect

        bmap = Basemap(projection='aeqd',
                       resolution=resolution,
                       area_thresh=1000.0,
                       lat_0=lat_0,
                       lon_0=lon_0,
                       width=width,
                       height=height)

        # not most elegant way to calculate some round lats/lons

        def linspace2(val1, val2, N):
            """
            returns around N 'nice' values between val1 and val2
            """
            dval = val2 - val1
            round_pos = int(round(-np.log10(1. * dval / N)))
            # Fake negative rounding as not supported by future as of now.
            if round_pos < 0:
                factor = 10**(abs(round_pos))
                delta = round(2. * dval / N / factor) * factor / 2
            else:
                delta = round(2. * dval / N, round_pos) / 2
            new_val1 = np.ceil(val1 / delta) * delta
            new_val2 = np.floor(val2 / delta) * delta
            N = (new_val2 - new_val1) / delta + 1
            return np.linspace(new_val1, new_val2, N)

        N1 = int(np.ceil(height / max(width, height) * 8))
        N2 = int(np.ceil(width / max(width, height) * 8))
        bmap.drawparallels(linspace2(lat_0 - height / 2 / deg2m_lat,
                                     lat_0 + height / 2 / deg2m_lat, N1),
                           labels=[0, 1, 1, 0])
        if min(lons) < -150 and max(lons) > 150:
            lon_0 %= 360
        meridians = linspace2(lon_0 - width / 2 / deg2m_lon,
                              lon_0 + width / 2 / deg2m_lon, N2)
        meridians[meridians > 180] -= 360
        bmap.drawmeridians(meridians, labels=[1, 0, 0, 1])
    else:
        msg = "Projection '%s' not supported." % projection
        raise ValueError(msg)

    # draw coast lines, country boundaries, fill continents.
    map_ax.set_axis_bgcolor(water_fill_color)
    bmap.drawcoastlines(color="0.4")
    bmap.drawcountries(color="0.75")
    bmap.fillcontinents(color=continent_fill_color,
                        lake_color=water_fill_color)
    # draw the edge of the bmap projection region (the projection limb)
    bmap.drawmapboundary(fill_color=water_fill_color)
    # draw lat/lon grid lines every 30 degrees.
    bmap.drawmeridians(np.arange(-180, 180, 30))
    bmap.drawparallels(np.arange(-90, 90, 30))

    # compute the native bmap projection coordinates for events.
    x, y = bmap(lons, lats)
    # plot labels
    if labels:
        if 100 > len(lons) > 1:
            for name, xpt, ypt, _colorpt in zip(labels, x, y, color):
                # Check if the point can actually be seen with the current bmap
                # projection. The bmap object will set the coordinates to very
                # large values if it cannot project a point.
                if xpt > 1e25:
                    continue
                plt.text(xpt,
                         ypt,
                         name,
                         weight="heavy",
                         color="k",
                         zorder=100,
                         **path_effect_kwargs)
        elif len(lons) == 1:
            plt.text(x[0],
                     y[0],
                     labels[0],
                     weight="heavy",
                     color="k",
                     **path_effect_kwargs)

    scatter = bmap.scatter(x,
                           y,
                           marker=marker,
                           s=size,
                           c=color,
                           zorder=10,
                           cmap=colormap)

    if title:
        plt.suptitle(title)

    # Only show the colorbar for more than one event.
    if show_colorbar:
        if colorbar_ticklabel_format is not None:
            if isinstance(colorbar_ticklabel_format, (str, native_str)):
                formatter = FormatStrFormatter(colorbar_ticklabel_format)
            elif hasattr(colorbar_ticklabel_format, '__call__'):
                formatter = FuncFormatter(colorbar_ticklabel_format)
            elif isinstance(colorbar_ticklabel_format, Formatter):
                formatter = colorbar_ticklabel_format
            locator = MaxNLocator(5)
        else:
            if datetimeplot:
                locator = AutoDateLocator()
                formatter = AutoDateFormatter(locator)
                formatter.scaled[1 / (24. * 60.)] = '%H:%M:%S'
            else:
                locator = None
                formatter = None
        cb = Colorbar(cm_ax,
                      scatter,
                      cmap=colormap,
                      orientation='horizontal',
                      ticks=locator,
                      format=formatter)
        #              format=formatter)
        #              ticks=mpl.ticker.MaxNLocator(4))
        cb.update_ticks()

    if show:
        plt.show()

    return fig