geemap/geemap.py
def add_time_slider(
        self,
        ee_object,
        vis_params={},
        region=None,
        layer_name="Time series",
        labels=None,
        time_interval=1,
        position="bottomright",
        slider_length="150px",
        date_format="YYYY-MM-dd",
        opacity=1.0,
        **kwargs,
    ):
        """Adds a time slider to the map.

        Args:
            ee_object (ee.Image | ee.ImageCollection): The Image or ImageCollection to visualize.
            vis_params (dict, optional): Visualization parameters to use for visualizing image. Defaults to {}.
            region (ee.Geometry | ee.FeatureCollection): The region to visualize.
            layer_name (str, optional): The layer name to be used. Defaults to "Time series".
            labels (list, optional): The list of labels to be used for the time series. Defaults to None.
            time_interval (int, optional): Time interval in seconds. Defaults to 1.
            position (str, optional): Position to place the time slider, can be any of ['topleft', 'topright', 'bottomleft', 'bottomright']. Defaults to "bottomright".
            slider_length (str, optional): Length of the time slider. Defaults to "150px".
            date_format (str, optional): The date format to use. Defaults to 'YYYY-MM-dd'.
            opacity (float, optional): The opacity of layers. Defaults to 1.0.

        Raises:
            TypeError: If the ee_object is not ee.Image | ee.ImageCollection.
        """
        import threading

        if isinstance(ee_object, ee.Image):
            if region is not None:
                if isinstance(region, ee.Geometry):
                    ee_object = ee_object.clip(region)
                elif isinstance(region, ee.FeatureCollection):
                    ee_object = ee_object.clipToCollection(region)
            if layer_name not in self.ee_raster_layer_names:
                self.addLayer(ee_object, {}, layer_name, False, opacity)
            band_names = ee_object.bandNames()
            ee_object = ee.ImageCollection(
                ee_object.bandNames().map(lambda b: ee_object.select([b]))
            )

            if labels is not None:
                if len(labels) != int(ee_object.size().getInfo()):
                    raise ValueError(
                        "The length of labels must be equal to the number of bands in the image."
                    )
            else:
                labels = band_names.getInfo()

        elif isinstance(ee_object, ee.ImageCollection):
            if region is not None:
                if isinstance(region, ee.Geometry):
                    ee_object = ee_object.map(lambda img: img.clip(region))
                elif isinstance(region, ee.FeatureCollection):
                    ee_object = ee_object.map(lambda img: img.clipToCollection(region))

            if labels is not None:
                if len(labels) != int(ee_object.size().getInfo()):
                    raise ValueError(
                        "The length of labels must be equal to the number of images in the ImageCollection."
                    )
            else:
                labels = (
                    ee_object.aggregate_array("system:time_start")
                    .map(lambda d: ee.Date(d).format(date_format))
                    .getInfo()
                )
        else:
            raise TypeError("The ee_object must be an ee.Image or ee.ImageCollection")

        # if labels is not None:
        #     size = len(labels)
        # else:
        #     size = ee_object.size().getInfo()
        #     labels = [str(i) for i in range(1, size + 1)]

        first = ee.Image(ee_object.first())

        if layer_name not in self.ee_raster_layer_names:
            self.addLayer(ee_object.toBands(), {}, layer_name, False, opacity)
        self.addLayer(first, vis_params, "Image X", True, opacity)

        slider = widgets.IntSlider(
            min=1,
            max=len(labels),
            readout=False,
            continuous_update=False,
            layout=widgets.Layout(width=slider_length),
        )
        label = widgets.Label(
            value=labels[0], layout=widgets.Layout(padding="0px 5px 0px 5px")
        )

        play_btn = widgets.Button(
            icon="play",
            tooltip="Play the time slider",
            button_style="primary",
            layout=widgets.Layout(width="32px"),
        )

        pause_btn = widgets.Button(
            icon="pause",
            tooltip="Pause the time slider",
            button_style="primary",
            layout=widgets.Layout(width="32px"),
        )

        close_btn = widgets.Button(
            icon="times",
            tooltip="Close the time slider",
            button_style="primary",
            layout=widgets.Layout(width="32px"),
        )

        play_chk = widgets.Checkbox(value=False)

        slider_widget = widgets.HBox([slider, label, play_btn, pause_btn, close_btn])

        def play_click(b):

            play_chk.value = True

            def work(slider):
                while play_chk.value:
                    if slider.value < len(labels):
                        slider.value += 1
                    else:
                        slider.value = 1
                    time.sleep(time_interval)

            thread = threading.Thread(target=work, args=(slider,))
            thread.start()

        def pause_click(b):
            play_chk.value = False

        play_btn.on_click(play_click)
        pause_btn.on_click(pause_click)

        def slider_changed(change):
            self.default_style = {"cursor": "wait"}
            index = slider.value - 1
            label.value = labels[index]
            image = ee.Image(ee_object.toList(ee_object.size()).get(index))
            if layer_name not in self.ee_raster_layer_names:
                self.addLayer(ee_object.toBands(), {}, layer_name, False, opacity)
            self.addLayer(image, vis_params, "Image X", True, opacity)
            self.default_style = {"cursor": "default"}

        slider.observe(slider_changed, "value")

        def close_click(b):
            play_chk.value = False
            self.toolbar_reset()
            self.remove_ee_layer("Image X")
            self.remove_ee_layer(layer_name)

            if self.slider_ctrl is not None and self.slider_ctrl in self.controls:
                self.remove_control(self.slider_ctrl)
            slider_widget.close()

        close_btn.on_click(close_click)

        slider_ctrl = ipyleaflet.WidgetControl(widget=slider_widget, position=position)
        self.add_control(slider_ctrl)
        self.slider_ctrl = slider_ctrl
Adds a time slider to the map.

        Args:
            ee_object (ee.Image | ee.ImageCollection): The Image or ImageCollection to visualize.
            vis_params (dict, optional): Visualization parameters to use for visualizing image. Defaults to {}.
            region (ee.Geometry | ee.FeatureCollection): The region to visualize.
            layer_name (str, optional): The layer name to be used. Defaults to "Time series".
            labels (list, optional): The list of labels to be used for the time series. Defaults to None.
            time_interval (int, optional): Time interval in seconds. Defaults to 1.
            position (str, optional): Position to place the time slider, can be any of ['topleft', 'topright', 'bottomleft', 'bottomright']. Defaults to "bottomright".
            slider_length (str, optional): Length of the time slider. Defaults to "150px".
            date_format (str, optional): The date format to use. Defaults to 'YYYY-MM-dd'.
            opacity (float, optional): The opacity of layers. Defaults to 1.0.

        Raises:
            TypeError: If the ee_object is not ee.Image | ee.ImageCollection.
        
Adds a time slider to the map.
Adds a time slider to the map .
def add_time_slider(
        self,
        ee_object,
        vis_params={},
        region=None,
        layer_name="Time series",
        labels=None,
        time_interval=1,
        position="bottomright",
        slider_length="150px",
        date_format="YYYY-MM-dd",
        opacity=1.0,
        **kwargs,
    ):
        import threading
        if isinstance(ee_object, ee.Image):
            if region is not None:
                if isinstance(region, ee.Geometry):
                    ee_object = ee_object.clip(region)
                elif isinstance(region, ee.FeatureCollection):
                    ee_object = ee_object.clipToCollection(region)
            if layer_name not in self.ee_raster_layer_names:
                self.addLayer(ee_object, {}, layer_name, False, opacity)
            band_names = ee_object.bandNames()
            ee_object = ee.ImageCollection(
                ee_object.bandNames().map(lambda b: ee_object.select([b]))
            )
            if labels is not None:
                if len(labels) != int(ee_object.size().getInfo()):
                    raise ValueError(
                        "The length of labels must be equal to the number of bands in the image."
                    )
            else:
                labels = band_names.getInfo()
        elif isinstance(ee_object, ee.ImageCollection):
            if region is not None:
                if isinstance(region, ee.Geometry):
                    ee_object = ee_object.map(lambda img: img.clip(region))
                elif isinstance(region, ee.FeatureCollection):
                    ee_object = ee_object.map(lambda img: img.clipToCollection(region))
            if labels is not None:
                if len(labels) != int(ee_object.size().getInfo()):
                    raise ValueError(
                        "The length of labels must be equal to the number of images in the ImageCollection."
                    )
            else:
                labels = (
                    ee_object.aggregate_array("system:time_start")
                    .map(lambda d: ee.Date(d).format(date_format))
                    .getInfo()
                )
        else:
            raise TypeError("The ee_object must be an ee.Image or ee.ImageCollection")
        first = ee.Image(ee_object.first())
        if layer_name not in self.ee_raster_layer_names:
            self.addLayer(ee_object.toBands(), {}, layer_name, False, opacity)
        self.addLayer(first, vis_params, "Image X", True, opacity)
        slider = widgets.IntSlider(
            min=1,
            max=len(labels),
            readout=False,
            continuous_update=False,
            layout=widgets.Layout(width=slider_length),
        )
        label = widgets.Label(
            value=labels[0], layout=widgets.Layout(padding="0px 5px 0px 5px")
        )
        play_btn = widgets.Button(
            icon="play",
            tooltip="Play the time slider",
            button_style="primary",
            layout=widgets.Layout(width="32px"),
        )
        pause_btn = widgets.Button(
            icon="pause",
            tooltip="Pause the time slider",
            button_style="primary",
            layout=widgets.Layout(width="32px"),
        )
        close_btn = widgets.Button(
            icon="times",
            tooltip="Close the time slider",
            button_style="primary",
            layout=widgets.Layout(width="32px"),
        )
        play_chk = widgets.Checkbox(value=False)
        slider_widget = widgets.HBox([slider, label, play_btn, pause_btn, close_btn])
        def play_click(b):
            play_chk.value = True
            def work(slider):
                while play_chk.value:
                    if slider.value < len(labels):
                        slider.value += 1
                    else:
                        slider.value = 1
                    time.sleep(time_interval)
            thread = threading.Thread(target=work, args=(slider,))
            thread.start()
        def pause_click(b):
            play_chk.value = False
        play_btn.on_click(play_click)
        pause_btn.on_click(pause_click)
        def slider_changed(change):
            self.default_style = {"cursor": "wait"}
            index = slider.value - 1
            label.value = labels[index]
            image = ee.Image(ee_object.toList(ee_object.size()).get(index))
            if layer_name not in self.ee_raster_layer_names:
                self.addLayer(ee_object.toBands(), {}, layer_name, False, opacity)
            self.addLayer(image, vis_params, "Image X", True, opacity)
            self.default_style = {"cursor": "default"}
        slider.observe(slider_changed, "value")
        def close_click(b):
            play_chk.value = False
            self.toolbar_reset()
            self.remove_ee_layer("Image X")
            self.remove_ee_layer(layer_name)
            if self.slider_ctrl is not None and self.slider_ctrl in self.controls:
                self.remove_control(self.slider_ctrl)
            slider_widget.close()
        close_btn.on_click(close_click)
        slider_ctrl = ipyleaflet.WidgetControl(widget=slider_widget, position=position)
        self.add_control(slider_ctrl)
        self.slider_ctrl = slider_ctrl
def add_time_slider ( self , ee_object , vis_params = { } , region = None , layer_name = "Time series" , labels = None , time_interval = 1 , position = "bottomright" , slider_length = "150px" , date_format = "YYYY-MM-dd" , opacity = 1.0 , ** kwargs , ) : import threading if isinstance ( ee_object , ee . Image ) : if region is not None : if isinstance ( region , ee . Geometry ) : ee_object = ee_object . clip ( region ) elif isinstance ( region , ee . FeatureCollection ) : ee_object = ee_object . clipToCollection ( region ) if layer_name not in self . ee_raster_layer_names : self . addLayer ( ee_object , { } , layer_name , False , opacity ) band_names = ee_object . bandNames ( ) ee_object = ee . ImageCollection ( ee_object . bandNames ( ) . map ( lambda b : ee_object . select ( [ b ] ) ) ) if labels is not None : if len ( labels ) != int ( ee_object . size ( ) . getInfo ( ) ) : raise ValueError ( "The length of labels must be equal to the number of bands in the image." ) else : labels = band_names . getInfo ( ) elif isinstance ( ee_object , ee . ImageCollection ) : if region is not None : if isinstance ( region , ee . Geometry ) : ee_object = ee_object . map ( lambda img : img . clip ( region ) ) elif isinstance ( region , ee . FeatureCollection ) : ee_object = ee_object . map ( lambda img : img . clipToCollection ( region ) ) if labels is not None : if len ( labels ) != int ( ee_object . size ( ) . getInfo ( ) ) : raise ValueError ( "The length of labels must be equal to the number of images in the ImageCollection." ) else : labels = ( ee_object . aggregate_array ( "system:time_start" ) . map ( lambda d : ee . Date ( d ) . format ( date_format ) ) . getInfo ( ) ) else : raise TypeError ( "The ee_object must be an ee.Image or ee.ImageCollection" ) first = ee . Image ( ee_object . first ( ) ) if layer_name not in self . ee_raster_layer_names : self . addLayer ( ee_object . toBands ( ) , { } , layer_name , False , opacity ) self . addLayer ( first , vis_params , "Image X" , True , opacity ) slider = widgets . IntSlider ( min = 1 , max = len ( labels ) , readout = False , continuous_update = False , layout = widgets . Layout ( width = slider_length ) , ) label = widgets . Label ( value = labels [ 0 ] , layout = widgets . Layout ( padding = "0px 5px 0px 5px" ) ) play_btn = widgets . Button ( icon = "play" , tooltip = "Play the time slider" , button_style = "primary" , layout = widgets . Layout ( width = "32px" ) , ) pause_btn = widgets . Button ( icon = "pause" , tooltip = "Pause the time slider" , button_style = "primary" , layout = widgets . Layout ( width = "32px" ) , ) close_btn = widgets . Button ( icon = "times" , tooltip = "Close the time slider" , button_style = "primary" , layout = widgets . Layout ( width = "32px" ) , ) play_chk = widgets . Checkbox ( value = False ) slider_widget = widgets . HBox ( [ slider , label , play_btn , pause_btn , close_btn ] ) def play_click ( b ) : play_chk . value = True def work ( slider ) : while play_chk . value : if slider . value < len ( labels ) : slider . value += 1 else : slider . value = 1 time . sleep ( time_interval ) thread = threading . Thread ( target = work , args = ( slider , ) ) thread . start ( ) def pause_click ( b ) : play_chk . value = False play_btn . on_click ( play_click ) pause_btn . on_click ( pause_click ) def slider_changed ( change ) : self . default_style = { "cursor" : "wait" } index = slider . value - 1 label . value = labels [ index ] image = ee . Image ( ee_object . toList ( ee_object . size ( ) ) . get ( index ) ) if layer_name not in self . ee_raster_layer_names : self . addLayer ( ee_object . toBands ( ) , { } , layer_name , False , opacity ) self . addLayer ( image , vis_params , "Image X" , True , opacity ) self . default_style = { "cursor" : "default" } slider . observe ( slider_changed , "value" ) def close_click ( b ) : play_chk . value = False self . toolbar_reset ( ) self . remove_ee_layer ( "Image X" ) self . remove_ee_layer ( layer_name ) if self . slider_ctrl is not None and self . slider_ctrl in self . controls : self . remove_control ( self . slider_ctrl ) slider_widget . close ( ) close_btn . on_click ( close_click ) slider_ctrl = ipyleaflet . WidgetControl ( widget = slider_widget , position = position ) self . add_control ( slider_ctrl ) self . slider_ctrl = slider_ctrl
Adds a time slider to the map.
Adds a time slider to the map .
"""Adds a time slider to the map.

        Args:
            ee_object (ee.Image | ee.ImageCollection): The Image or ImageCollection to visualize.
            vis_params (dict, optional): Visualization parameters to use for visualizing image. Defaults to {}.
            region (ee.Geometry | ee.FeatureCollection): The region to visualize.
            layer_name (str, optional): The layer name to be used. Defaults to "Time series".
            labels (list, optional): The list of labels to be used for the time series. Defaults to None.
            time_interval (int, optional): Time interval in seconds. Defaults to 1.
            position (str, optional): Position to place the time slider, can be any of ['topleft', 'topright', 'bottomleft', 'bottomright']. Defaults to "bottomright".
            slider_length (str, optional): Length of the time slider. Defaults to "150px".
            date_format (str, optional): The date format to use. Defaults to 'YYYY-MM-dd'.
            opacity (float, optional): The opacity of layers. Defaults to 1.0.

        Raises:
            TypeError: If the ee_object is not ee.Image | ee.ImageCollection.
        """ # if labels is not None:
 #     size = len(labels)
 # else:
 #     size = ee_object.size().getInfo()
 #     labels = [str(i) for i in range(1, size + 1)]

If the ee_object is not ee.Image | ee.ImageCollection.
If the ee_object is not ee . Image | ee . ImageCollection .
TypeError
self
ee_object
The Image or ImageCollection to visualize.
The Image or ImageCollection to visualize .
vis_params
Visualization parameters to use for visualizing image. Defaults to {}.
Visualization parameters to use for visualizing image . Defaults to {} .
{}
region
The region to visualize.
The region to visualize .
layer_name
The layer name to be used. Defaults to "Time series".
The layer name to be used . Defaults to " Time series " .
"Time series"
labels
The list of labels to be used for the time series. Defaults to None.
The list of labels to be used for the time series . Defaults to None .
None
time_interval
Time interval in seconds. Defaults to 1.
Time interval in seconds . Defaults to 1 .
1
position
Position to place the time slider, can be any of ['topleft', 'topright', 'bottomleft', 'bottomright']. Defaults to "bottomright".
Position to place the time slider can be any of [ ' topleft ' ' topright ' ' bottomleft ' ' bottomright ' ] . Defaults to " bottomright " .
"bottomright"
slider_length
Length of the time slider. Defaults to "150px".
Length of the time slider . Defaults to " 150px " .
"150px"
date_format
The date format to use. Defaults to 'YYYY-MM-dd'.
The date format to use . Defaults to ' YYYY - MM - dd ' .
'YYYY-MM-dd'
opacity
The opacity of layers. Defaults to 1.0.
The opacity of layers . Defaults to 1 . 0 .
1.0