Skip to content

coreutils module

build_computed_object_tree(ee_object, layer_name='', opened=False)

Return a tree structure representing an EE object.

The source code was adapted from https://github.com/google/earthengine-jupyter. Credits to Tyler Erickson.

Parameters:

Name Type Description Default
ee_object Union[FeatureCollection, Image, Geometry, Feature]

The Earth Engine object.

required
layer_name str

The name of the layer. Defaults to "".

''
opened bool

Whether to expand the tree. Defaults to False.

False

Returns:

Type Description
dict[str, Any]

dict[str, Any]: The node representing the Earth Engine object information.

Source code in geemap/coreutils.py
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
def build_computed_object_tree(
    ee_object: Union[ee.FeatureCollection, ee.Image, ee.Geometry, ee.Feature],
    layer_name: str = "",
    opened: bool = False,
) -> dict[str, Any]:
    """Return a tree structure representing an EE object.

    The source code was adapted from https://github.com/google/earthengine-jupyter.
    Credits to Tyler Erickson.

    Args:
        ee_object (Union[ee.FeatureCollection, ee.Image, ee.Geometry, ee.Feature]):
            The Earth Engine object.
        layer_name (str, optional): The name of the layer. Defaults to "".
        opened (bool, optional): Whether to expand the tree. Defaults to False.

    Returns:
        dict[str, Any]: The node representing the Earth Engine object information.
    """

    # Convert EE object props to dicts. It's easier to traverse the nested structure.
    if isinstance(ee_object, ee.FeatureCollection):
        ee_object = ee_object.map(lambda f: ee.Feature(None, f.toDictionary()))

    layer_info = ee_object.getInfo()
    if not layer_info:
        return {}

    # Strip geometries because they're slow to render as text.
    if "geometry" in layer_info:
        layer_info.pop("geometry")

    # Sort the keys in layer_info and the nested properties.
    if properties := layer_info.get("properties"):
        layer_info["properties"] = dict(sorted(properties.items()))
    ordering_list = ["type", "id", "version", "bands", "properties"]
    layer_info = _order_items(layer_info, ordering_list)

    ee_type = layer_info.get("type", ee_object.__class__.__name__)

    band_info = ""
    if bands := layer_info.get("bands"):
        band_info = f" ({len(bands)} bands)"
    if layer_name:
        layer_name = f"{layer_name}: "

    return new_tree_node(
        f"{layer_name}{ee_type}{band_info}",
        _generate_tree(layer_info, opened),
        expanded=opened,
    )

check_cmap(cmap)

Check the colormap and return a list of colors.

Parameters:

Name Type Description Default
cmap Union[str, List[str], Box]

The colormap to check.

required

Returns:

Type Description
List[str]

List[str]: A list of colors.

Source code in geemap/coreutils.py
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
def check_cmap(cmap: Union[str, List[str]]) -> List[str]:
    """Check the colormap and return a list of colors.

    Args:
        cmap (Union[str, List[str], Box]): The colormap to check.

    Returns:
        List[str]: A list of colors.
    """

    from box import Box
    from .colormaps import get_palette

    if isinstance(cmap, str):
        try:
            palette = get_palette(cmap)
            if isinstance(palette, dict):
                palette = palette["default"]
            return palette
        except Exception as e:
            try:
                return check_color(cmap)
            except Exception as e:
                raise Exception(f"{cmap} is not a valid colormap.")
    elif isinstance(cmap, Box):
        return list(cmap["default"])
    elif isinstance(cmap, list) or isinstance(cmap, tuple):
        return cmap
    else:
        raise Exception(f"{cmap} is not a valid colormap.")

check_color(in_color)

Checks the input color and returns the corresponding hex color code.

Parameters:

Name Type Description Default
in_color Union[str, Tuple[int, int, int]]

It can be a string (e.g., 'red', '#ffff00', 'ffff00', 'ff0') or RGB tuple (e.g., (255, 127, 0)).

required

Returns:

Name Type Description
str str

A hex color code.

Source code in geemap/coreutils.py
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
def check_color(in_color: Union[str, Tuple[int, int, int]]) -> str:
    """Checks the input color and returns the corresponding hex color code.

    Args:
        in_color (Union[str, Tuple[int, int, int]]): It can be a string (e.g.,
            'red', '#ffff00', 'ffff00', 'ff0') or RGB tuple (e.g., (255, 127, 0)).

    Returns:
        str: A hex color code.
    """
    import colour

    out_color = "#000000"  # default black color
    if isinstance(in_color, tuple) and len(in_color) == 3:
        # rescale color if necessary
        if all(isinstance(item, int) for item in in_color):
            in_color = [c / 255.0 for c in in_color]

        return colour.Color(rgb=tuple(in_color)).hex_l

    else:
        # try to guess the color system
        try:
            return colour.Color(in_color).hex_l

        except Exception as e:
            pass

        # try again by adding an extra # (GEE handle hex codes without #)
        try:
            return colour.Color(f"#{in_color}").hex_l

        except Exception as e:
            print(
                f"The provided color ({in_color}) is invalid. Using the default black color."
            )
            print(e)

        return out_color

create_code_cell(code='', where='below')

Creates a code cell in the IPython Notebook.

Parameters:

Name Type Description Default
code str

Code to fill the new code cell with. Defaults to ''.

''
where str

Where to add the new code cell. It can be one of the following: above, below, at_bottom. Defaults to 'below'.

'below'
Source code in geemap/coreutils.py
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
def create_code_cell(code: str = "", where: str = "below") -> None:
    """Creates a code cell in the IPython Notebook.

    Args:
        code (str, optional): Code to fill the new code cell with. Defaults to ''.
        where (str, optional): Where to add the new code cell. It can be one of
            the following: above, below, at_bottom. Defaults to 'below'.
    """

    import base64
    import pyperclip

    try:
        pyperclip.copy(str(code))
    except Exception as e:
        pass

    encoded_code = (base64.b64encode(str.encode(code))).decode()
    display(
        Javascript(
            """
        var code = IPython.notebook.insert_cell_{0}('code');
        code.set_text(atob("{1}"));
    """.format(
                where, encoded_code
            )
        )
    )

download_file(url=None, output=None, quiet=False, proxy=None, speed=None, use_cookies=True, verify=True, id=None, fuzzy=False, resume=False, unzip=True, overwrite=False)

Download a file from URL, including Google Drive shared URL.

Parameters:

Name Type Description Default
url Optional[str]

Google Drive URL is also supported. Defaults to None.

None
output Optional[str]

Output filename. Default is basename of URL.

None
quiet bool

Suppress terminal output. Default is False.

False
proxy Optional[str]

Proxy. Defaults to None.

None
speed Optional[float]

Download byte size per second (e.g., 256KB/s = 256 * 1024). Defaults to None.

None
use_cookies bool

Flag to use cookies. Defaults to True.

True
verify Union[bool, str]

Either a bool, in which case it controls whether the server's TLS certificate is verified, or a string, in which case it must be a path to a CA bundle to use. Default is True.

True
id Optional[str]

Google Drive's file ID. Defaults to None.

None
fuzzy bool

Fuzzy extraction of Google Drive's file Id. Defaults to False.

False
resume bool

Resume the download from existing tmp file if possible. Defaults to False.

False
unzip bool

Unzip the file. Defaults to True.

True
overwrite bool

Overwrite the file if it already exists. Defaults to False.

False

Returns:

Name Type Description
str str

The output file path.

Source code in geemap/coreutils.py
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
def download_file(
    url: Optional[str] = None,
    output: Optional[str] = None,
    quiet: bool = False,
    proxy: Optional[str] = None,
    speed: Optional[float] = None,
    use_cookies: bool = True,
    verify: Union[bool, str] = True,
    id: Optional[str] = None,
    fuzzy: bool = False,
    resume: bool = False,
    unzip: bool = True,
    overwrite: bool = False,
) -> str:
    """Download a file from URL, including Google Drive shared URL.

    Args:
        url (Optional[str], optional): Google Drive URL is also supported.
            Defaults to None.
        output (Optional[str], optional): Output filename. Default is basename of URL.
        quiet (bool, optional): Suppress terminal output. Default is False.
        proxy (Optional[str], optional): Proxy. Defaults to None.
        speed (Optional[float], optional): Download byte size per second (e.g.,
            256KB/s = 256 * 1024). Defaults to None.
        use_cookies (bool, optional): Flag to use cookies. Defaults to True.
        verify (Union[bool, str], optional): Either a bool, in which case it
            controls whether the server's TLS certificate is verified, or a
            string, in which case it must be a path to a CA bundle to use.
            Default is True.
        id (Optional[str], optional): Google Drive's file ID. Defaults to None.
        fuzzy (bool, optional): Fuzzy extraction of Google Drive's file Id.
            Defaults to False.
        resume (bool, optional): Resume the download from existing tmp file if
            possible. Defaults to False.
        unzip (bool, optional): Unzip the file. Defaults to True.
        overwrite (bool, optional): Overwrite the file if it already exists.
            Defaults to False.

    Returns:
        str: The output file path.
    """

    import gdown

    if output is None:
        if isinstance(url, str) and url.startswith("http"):
            output = os.path.basename(url)

    if isinstance(url, str):
        if os.path.exists(os.path.abspath(output)) and (not overwrite):
            print(
                f"{output} already exists. Skip downloading. Set overwrite=True to overwrite."
            )
            return os.path.abspath(output)
        else:
            url = github_raw_url(url)

    if "https://drive.google.com/file/d/" in url:
        fuzzy = True

    output = gdown.download(
        url, output, quiet, proxy, speed, use_cookies, verify, id, fuzzy, resume
    )

    if unzip and output.endswith(".zip"):
        with zipfile.ZipFile(output, "r") as zip_ref:
            if not quiet:
                print("Extracting files...")
            zip_ref.extractall(os.path.dirname(output))

    return os.path.abspath(output)

ee_initialize(token_name='EARTHENGINE_TOKEN', auth_mode=None, auth_args=None, user_agent_prefix='geemap', project=None, **kwargs)

Authenticates Earth Engine and initialize an Earth Engine session

Parameters:

Name Type Description Default
token_name str

The name of the Earth Engine token. Defaults to "EARTHENGINE_TOKEN". In Colab, you can also set a secret named "EE_PROJECT_ID" to initialize Earth Engine.

'EARTHENGINE_TOKEN'
auth_mode str

The authentication mode, can be one of colab, notebook, localhost, or gcloud. See https://developers.google.com/earth-engine/guides/auth for more details. Defaults to None.

None
auth_args dict

Additional authentication parameters for aa.Authenticate(). Defaults to {}.

None
user_agent_prefix str

If set, the prefix (version-less) value used for setting the user-agent string. Defaults to "geemap".

'geemap'
project str

The Google cloud project ID for Earth Engine. Defaults to None.

None
kwargs dict

Additional parameters for ee.Initialize(). For example, opt_url='https://earthengine-highvolume.googleapis.com' to use the Earth Engine High-Volume platform. Defaults to {}.

{}
Source code in geemap/coreutils.py
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
def ee_initialize(
    token_name: str = "EARTHENGINE_TOKEN",
    auth_mode: Optional[str] = None,
    auth_args: Optional[Dict[str, Any]] = None,
    user_agent_prefix: str = "geemap",
    project: Optional[str] = None,
    **kwargs: Any,
) -> None:
    """Authenticates Earth Engine and initialize an Earth Engine session

    Args:
        token_name (str, optional): The name of the Earth Engine token.
            Defaults to "EARTHENGINE_TOKEN". In Colab, you can also set a secret
            named "EE_PROJECT_ID" to initialize Earth Engine.
        auth_mode (str, optional): The authentication mode, can be one of colab,
            notebook, localhost, or gcloud.
            See https://developers.google.com/earth-engine/guides/auth for more
            details. Defaults to None.
        auth_args (dict, optional): Additional authentication parameters for
            aa.Authenticate(). Defaults to {}.
        user_agent_prefix (str, optional): If set, the prefix (version-less)
            value used for setting the user-agent string. Defaults to "geemap".
        project (str, optional): The Google cloud project ID for Earth Engine.
            Defaults to None.
        kwargs (dict, optional): Additional parameters for ee.Initialize().
            For example, opt_url='https://earthengine-highvolume.googleapis.com'
            to use the Earth Engine High-Volume platform. Defaults to {}.
    """
    import google.oauth2.credentials
    from .__init__ import __version__

    user_agent = f"{user_agent_prefix}/{__version__}"
    ee.data.setUserAgent(user_agent)

    if ee.data._credentials is not None:
        return

    ee_token = get_env_var(token_name)
    if ee_token is not None:

        stored = json.loads(ee_token)
        credentials = google.oauth2.credentials.Credentials(
            None,
            token_uri="https://oauth2.googleapis.com/token",
            client_id=stored["client_id"],
            client_secret=stored["client_secret"],
            refresh_token=stored["refresh_token"],
            quota_project_id=stored["project"],
        )

        ee.Initialize(credentials=credentials, **kwargs)
        return

    if auth_args is None:
        auth_args = {}

    if project is None:
        kwargs["project"] = get_env_var("EE_PROJECT_ID")
    else:
        kwargs["project"] = project

    if auth_mode is None:
        if in_colab_shell() and (ee.data._credentials is None):
            ee.Authenticate()
            ee.Initialize(**kwargs)
            return
        else:
            auth_mode = "notebook"

    auth_args["auth_mode"] = auth_mode

    ee.Authenticate(**auth_args)
    ee.Initialize(**kwargs)

geojson_to_ee(geo_json, geodesic=False, encoding='utf-8')

Converts a GeoJSON to an Earth Engine Geometry or FeatureCollection.

Parameters:

Name Type Description Default
geo_json Union[Dict[str, Any], str]

A GeoJSON geometry dictionary or file path.

required
geodesic bool

Whether line segments should be interpreted as spherical geodesics. If false, indicates that line segments should be interpreted as planar lines in the specified CRS. If absent, defaults to true if the CRS is geographic (including the default EPSG:4326), or to false if the CRS is projected. Defaults to False.

False
encoding str

The encoding of characters. Defaults to "utf-8".

'utf-8'

Returns:

Type Description
Union[Geometry, FeatureCollection]

Union[ee.Geometry, ee.FeatureCollection]: An Earth Engine Geometry or FeatureCollection.

Raises:

Type Description
Exception

If the GeoJSON cannot be converted to an Earth Engine object.

Source code in geemap/coreutils.py
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
def geojson_to_ee(
    geo_json: Union[Dict[str, Any], str],
    geodesic: bool = False,
    encoding: str = "utf-8",
) -> Union[ee.Geometry, ee.FeatureCollection]:
    """Converts a GeoJSON to an Earth Engine Geometry or FeatureCollection.

    Args:
        geo_json (Union[Dict[str, Any], str]): A GeoJSON geometry dictionary or
            file path.
        geodesic (bool, optional): Whether line segments should be interpreted
            as spherical geodesics. If false, indicates that line segments
            should be interpreted as planar lines in the specified CRS. If
            absent, defaults to true if the CRS is geographic (including the
            default EPSG:4326), or to false if the CRS is projected. Defaults to False.
        encoding (str, optional): The encoding of characters. Defaults to "utf-8".

    Returns:
        Union[ee.Geometry, ee.FeatureCollection]: An Earth Engine Geometry or FeatureCollection.

    Raises:
        Exception: If the GeoJSON cannot be converted to an Earth Engine object.
    """

    try:
        if isinstance(geo_json, str):
            if geo_json.startswith("http") and geo_json.endswith(".geojson"):
                geo_json = github_raw_url(geo_json)
                out_geojson = temp_file_path(extension=".geojson")
                download_file(geo_json, out_geojson)
                with open(out_geojson, "r", encoding=encoding) as f:
                    geo_json = json.loads(f.read())
                os.remove(out_geojson)

            elif os.path.isfile(geo_json):
                with open(os.path.abspath(geo_json), encoding=encoding) as f:
                    geo_json = json.load(f)

        # geo_json["geodesic"] = geodesic
        if geo_json["type"] == "FeatureCollection":
            for feature in geo_json["features"]:
                if feature["geometry"]["type"] != "Point":
                    feature["geometry"]["geodesic"] = geodesic
            features = ee.FeatureCollection(geo_json)
            return features
        elif geo_json["type"] == "Feature":
            geom = None
            if "style" in geo_json["properties"]:
                keys = geo_json["properties"]["style"].keys()
                if "radius" in keys:  # Checks whether it is a circle
                    geom = ee.Geometry(geo_json["geometry"])
                    radius = geo_json["properties"]["style"]["radius"]
                    geom = geom.buffer(radius)
                elif geo_json["geometry"]["type"] == "Point":
                    geom = ee.Geometry(geo_json["geometry"])
                else:
                    geom = ee.Geometry(geo_json["geometry"], "", geodesic)
            elif (
                geo_json["geometry"]["type"] == "Point"
            ):  # Checks whether it is a point
                coordinates = geo_json["geometry"]["coordinates"]
                longitude = coordinates[0]
                latitude = coordinates[1]
                geom = ee.Geometry.Point(longitude, latitude)
            else:
                geom = ee.Geometry(geo_json["geometry"], "", geodesic)
            return geom
        else:
            raise Exception("Could not convert the geojson to ee.Geometry()")

    except Exception as e:
        print("Could not convert the geojson to ee.Geometry()")
        raise Exception(e)

geometry_type(ee_object)

Get geometry type of an Earth Engine object.

Parameters:

Name Type Description Default
ee_object Any

An Earth Engine object.

required

Returns:

Name Type Description
str str

Returns geometry type. One of Point, MultiPoint, LineString, LinearRing, MultiLineString, BBox, Rectangle, Polygon, MultiPolygon.

Raises:

Type Description
TypeError

If the ee_object is not one of ee.Geometry, ee.Feature, ee.FeatureCollection.

Source code in geemap/coreutils.py
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
def geometry_type(ee_object: Any) -> str:
    """Get geometry type of an Earth Engine object.

    Args:
        ee_object (Any): An Earth Engine object.

    Returns:
        str: Returns geometry type. One of Point, MultiPoint, LineString,
            LinearRing, MultiLineString, BBox, Rectangle, Polygon, MultiPolygon.

    Raises:
        TypeError: If the ee_object is not one of ee.Geometry, ee.Feature,
            ee.FeatureCollection.
    """
    if isinstance(ee_object, ee.Geometry):
        return ee_object.type().getInfo()
    elif isinstance(ee_object, ee.Feature):
        return ee_object.geometry().type().getInfo()
    elif isinstance(ee_object, ee.FeatureCollection):
        return ee.Feature(ee_object.first()).geometry().type().getInfo()
    else:
        raise TypeError(
            "The ee_object must be one of ee.Geometry, ee.Feature, ee.FeatureCollection."
        )

get_env_var(key)

Retrieves an environment variable or Colab secret for the given key.

Colab secrets have precedence over environment variables.

Parameters:

Name Type Description Default
key str

The key that's used to fetch the environment variable.

required

Returns:

Type Description
Optional[str]

Optional[str]: The retrieved key, or None if no environment variable was found.

Source code in geemap/coreutils.py
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
def get_env_var(key: str) -> Optional[str]:
    """Retrieves an environment variable or Colab secret for the given key.

    Colab secrets have precedence over environment variables.

    Args:
        key (str): The key that's used to fetch the environment variable.

    Returns:
        Optional[str]: The retrieved key, or None if no environment variable was found.
    """
    if not key:
        return None

    if in_colab_shell():
        from google.colab import userdata

        try:
            return userdata.get(key)
        except (userdata.SecretNotFoundError, userdata.NotebookAccessError):
            pass

    return os.environ.get(key)

get_google_maps_api_key(key='GOOGLE_MAPS_API_KEY')

Retrieves the Google Maps API key from the environment or Colab user data.

Parameters:

Name Type Description Default
key str

The name of the environment variable or Colab user data key where the API key is stored. Defaults to 'GOOGLE_MAPS_API_KEY'.

'GOOGLE_MAPS_API_KEY'

Returns:

Name Type Description
str Optional[str]

The API key, or None if it could not be found.

Source code in geemap/coreutils.py
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
def get_google_maps_api_key(key: str = "GOOGLE_MAPS_API_KEY") -> Optional[str]:
    """
    Retrieves the Google Maps API key from the environment or Colab user data.

    Args:
        key (str, optional): The name of the environment variable or Colab user
            data key where the API key is stored. Defaults to
            'GOOGLE_MAPS_API_KEY'.

    Returns:
        str: The API key, or None if it could not be found.
    """
    if api_key := get_env_var(key):
        return api_key
    return os.environ.get(key, None)

get_info(ee_object, layer_name='', opened=False, return_node=False)

Print out the information for an Earth Engine object using a tree structure. The source code was adapted from https://github.com/google/earthengine-jupyter. Credits to Tyler Erickson.

Parameters:

Name Type Description Default
ee_object Union[FeatureCollection, Image, Geometry, Feature]

The Earth Engine object.

required
layer_name str

The name of the layer. Defaults to "".

''
opened bool

Whether to expand the tree. Defaults to False.

False
return_node bool

Whether to return the widget as ipytree.Node. If False, returns the widget as ipytree.Tree. Defaults to False.

False

Returns:

Type Description
Union[Node, Tree, None]

Union[Node, Tree, None]: The tree or node representing the Earth Engine object information.

Source code in geemap/coreutils.py
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
def get_info(
    ee_object: Union[ee.FeatureCollection, ee.Image, ee.Geometry, ee.Feature],
    layer_name: str = "",
    opened: bool = False,
    return_node: bool = False,
) -> Union[Node, Tree, None]:
    """Print out the information for an Earth Engine object using a tree structure.
    The source code was adapted from https://github.com/google/earthengine-jupyter.
    Credits to Tyler Erickson.

    Args:
        ee_object (Union[ee.FeatureCollection, ee.Image, ee.Geometry, ee.Feature]):
            The Earth Engine object.
        layer_name (str, optional): The name of the layer. Defaults to "".
        opened (bool, optional): Whether to expand the tree. Defaults to False.
        return_node (bool, optional): Whether to return the widget as ipytree.Node.
            If False, returns the widget as ipytree.Tree. Defaults to False.

    Returns:
        Union[Node, Tree, None]: The tree or node representing the Earth Engine
            object information.
    """

    tree_json = build_computed_object_tree(ee_object, layer_name, opened)

    def _create_node(data):
        """Create a widget for the computed object tree."""
        node = Node(data.get("label", "Node"), opened=data.get("expanded", False))
        if children := data.get("children"):
            for child in children:
                node.add_node(_create_node(child))
        else:
            node.icon = "file"
            node.value = str(data)  # Store the entire data as a string
        return node

    root_node = _create_node(tree_json)
    if return_node:
        return root_node
    else:
        tree = Tree()
        tree.add_node(root_node)
        return tree

github_raw_url(url)

Get the raw URL for a GitHub file.

Parameters:

Name Type Description Default
url str

The GitHub URL.

required

Returns:

Name Type Description
str str

The raw URL.

Source code in geemap/coreutils.py
662
663
664
665
666
667
668
669
670
671
672
673
674
675
def github_raw_url(url: str) -> str:
    """Get the raw URL for a GitHub file.

    Args:
        url (str): The GitHub URL.

    Returns:
        str: The raw URL.
    """
    if isinstance(url, str) and url.startswith("https://github.com/") and "blob" in url:
        url = url.replace("github.com", "raw.githubusercontent.com").replace(
            "blob/", "", 1
        )
    return url

hex_to_rgb(value='FFFFFF')

Converts hex color to RGB color.

Parameters:

Name Type Description Default
value str

Hex color code as a string. Defaults to 'FFFFFF'.

'FFFFFF'

Returns:

Type Description
Tuple[int, int, int]

Tuple[int, int, int]: RGB color as a tuple.

Source code in geemap/coreutils.py
471
472
473
474
475
476
477
478
479
480
481
482
def hex_to_rgb(value: str = "FFFFFF") -> Tuple[int, int, int]:
    """Converts hex color to RGB color.

    Args:
        value (str, optional): Hex color code as a string. Defaults to 'FFFFFF'.

    Returns:
        Tuple[int, int, int]: RGB color as a tuple.
    """
    value = value.lstrip("#")
    lv = len(value)
    return tuple(int(value[i : i + lv // 3], 16) for i in range(0, lv, lv // 3))

in_colab_shell()

Checks if the code is running in a Google Colab environment.

Returns:

Name Type Description
bool bool

True if running in Google Colab, False otherwise.

Source code in geemap/coreutils.py
361
362
363
364
365
366
367
368
def in_colab_shell() -> bool:
    """
    Checks if the code is running in a Google Colab environment.

    Returns:
        bool: True if running in Google Colab, False otherwise.
    """
    return "google.colab" in sys.modules

new_tree_node(label, children=None, expanded=False, top_level=False)

Returns node JSON for an interactive representation of an EE ComputedObject.

Source code in geemap/coreutils.py
117
118
119
120
121
122
123
124
125
126
127
128
129
def new_tree_node(
    label: str,
    children: Optional[list[dict[str, Any]]] = None,
    expanded: bool = False,
    top_level: bool = False,
) -> Dict[str, Any]:
    """Returns node JSON for an interactive representation of an EE ComputedObject."""
    return {
        "label": label,
        "children": children or [],
        "expanded": expanded,
        "topLevel": top_level,
    }

open_url(url)

Opens the URL in a new browser tab.

Parameters:

Name Type Description Default
url str

The URL to open.

required
Source code in geemap/coreutils.py
646
647
648
649
650
651
652
653
654
655
656
657
658
659
def open_url(url: str) -> None:
    """Opens the URL in a new browser tab.

    Args:
        url (str): The URL to open.
    """
    if in_colab_shell():
        display(
            Javascript('window.open("{url}", "_blank", "noopener")'.format(url=url))
        )
    else:
        import webbrowser

        webbrowser.open_new_tab(url)

random_string(string_length=3)

Generates a random string of fixed length.

Parameters:

Name Type Description Default
string_length int

Fixed length. Defaults to 3.

3

Returns:

Name Type Description
str str

A random string.

Source code in geemap/coreutils.py
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
def random_string(string_length: int = 3) -> str:
    """Generates a random string of fixed length.

    Args:
        string_length (int, optional): Fixed length. Defaults to 3.

    Returns:
        str: A random string.
    """
    import random
    import string

    # random.seed(1001)
    letters = string.ascii_lowercase
    return "".join(random.choice(letters) for i in range(string_length))

rgb_to_hex(rgb=(255, 255, 255))

Converts RGB to hex color. In RGB color, R stands for Red, G stands for Green, and B stands for Blue, and it ranges from the decimal value of 0 – 255.

Parameters:

Name Type Description Default
rgb Tuple[int, int, int]

RGB color code as a tuple of (red, green, blue). Defaults to (255, 255, 255).

(255, 255, 255)

Returns:

Name Type Description
str str

Hex color code.

Source code in geemap/coreutils.py
457
458
459
460
461
462
463
464
465
466
467
468
def rgb_to_hex(rgb: Tuple[int, int, int] = (255, 255, 255)) -> str:
    """Converts RGB to hex color. In RGB color, R stands for Red, G stands for
        Green, and B stands for Blue, and it ranges from the decimal value of 0 – 255.

    Args:
        rgb (Tuple[int, int, int], optional): RGB color code as a tuple of
            (red, green, blue). Defaults to (255, 255, 255).

    Returns:
        str: Hex color code.
    """
    return "%02x%02x%02x" % rgb

temp_file_path(extension)

Returns a temporary file path.

Parameters:

Name Type Description Default
extension str

The file extension.

required

Returns:

Name Type Description
str str

The temporary file path.

Source code in geemap/coreutils.py
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
def temp_file_path(extension: str) -> str:
    """Returns a temporary file path.

    Args:
        extension (str): The file extension.

    Returns:
        str: The temporary file path.
    """

    import tempfile
    import uuid

    if not extension.startswith("."):
        extension = "." + extension
    file_id = str(uuid.uuid4())
    file_path = os.path.join(tempfile.gettempdir(), f"{file_id}{extension}")

    return file_path

to_hex_colors(colors)

Convert a GEE color palette into hexadecimal color codes. Can handle mixed formats.

Parameters:

Name Type Description Default
colors List[Union[str, Tuple[int, int, int]]]

A list of colors in hex or RGB format.

required

Returns:

Type Description
List[str]

List[str]: A list of hex color codes prefixed with #.

Source code in geemap/coreutils.py
444
445
446
447
448
449
450
451
452
453
454
def to_hex_colors(colors: List[Union[str, Tuple[int, int, int]]]) -> List[str]:
    """Convert a GEE color palette into hexadecimal color codes. Can handle mixed formats.

    Args:
        colors (List[Union[str, Tuple[int, int, int]]]): A list of colors in hex or RGB format.

    Returns:
        List[str]: A list of hex color codes prefixed with #.
    """

    return [check_color(c) for c in colors]

widget_template(widget=None, opened=True, show_close_button=True, widget_icon='gear', close_button_icon='times', widget_args=None, close_button_args=None, display_widget=None, m=None, position='topright')

Create a widget template.

Parameters:

Name Type Description Default
widget Optional[Widget]

The widget to be displayed. Defaults to None.

None
opened bool

Whether to open the toolbar. Defaults to True.

True
show_close_button bool

Whether to show the close button. Defaults to True.

True
widget_icon str

The icon name for the toolbar button. Defaults to 'gear'.

'gear'
close_button_icon str

The icon name for the close button. Defaults to "times".

'times'
widget_args Optional[Dict[str, Any]]

Additional arguments to pass to the toolbar button. Defaults to None.

None
close_button_args Optional[Dict[str, Any]]

Additional arguments to pass to the close button. Defaults to None.

None
display_widget Optional[Widget]

The widget to be displayed when the toolbar is clicked. Defaults to None.

None
m Optional[Map]

The ipyleaflet.Map instance. Defaults to None.

None
position str

The position of the toolbar. Defaults to "topright".

'topright'

Returns:

Type Description
Optional[Widget]

Optional[widgets.Widget]: The created widget template.

Source code in geemap/coreutils.py
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
def widget_template(
    widget: Optional[widgets.Widget] = None,
    opened: bool = True,
    show_close_button: bool = True,
    widget_icon: str = "gear",
    close_button_icon: str = "times",
    widget_args: Optional[Dict[str, Any]] = None,
    close_button_args: Optional[Dict[str, Any]] = None,
    display_widget: Optional[widgets.Widget] = None,
    m: Optional["ipyleaflet.Map"] = None,
    position: str = "topright",
) -> Optional[widgets.Widget]:
    """Create a widget template.

    Args:
        widget (Optional[widgets.Widget], optional): The widget to be displayed.
            Defaults to None.
        opened (bool, optional): Whether to open the toolbar. Defaults to True.
        show_close_button (bool, optional): Whether to show the close button.
            Defaults to True.
        widget_icon (str, optional): The icon name for the toolbar button.
            Defaults to 'gear'.
        close_button_icon (str, optional): The icon name for the close button.
            Defaults to "times".
        widget_args (Optional[Dict[str, Any]], optional): Additional arguments
            to pass to the toolbar button. Defaults to None.
        close_button_args (Optional[Dict[str, Any]], optional): Additional
            arguments to pass to the close button. Defaults to None.
        display_widget (Optional[widgets.Widget], optional): The widget to be
            displayed when the toolbar is clicked. Defaults to None.
        m (Optional[ipyleaflet.Map], optional): The ipyleaflet.Map instance.
            Defaults to None.
        position (str, optional): The position of the toolbar. Defaults to "topright".

    Returns:
        Optional[widgets.Widget]: The created widget template.
    """

    name = "_" + random_string()  # a random attribute name

    if widget_args is None:
        widget_args = {}

    if close_button_args is None:
        close_button_args = {}

    if "value" not in widget_args:
        widget_args["value"] = False
    if "tooltip" not in widget_args:
        widget_args["tooltip"] = "Toolbar"
    if "layout" not in widget_args:
        widget_args["layout"] = widgets.Layout(
            width="28px", height="28px", padding="0px 0px 0px 4px"
        )
    widget_args["icon"] = widget_icon

    if "value" not in close_button_args:
        close_button_args["value"] = False
    if "tooltip" not in close_button_args:
        close_button_args["tooltip"] = "Close the tool"
    if "button_style" not in close_button_args:
        close_button_args["button_style"] = "primary"
    if "layout" not in close_button_args:
        close_button_args["layout"] = widgets.Layout(
            height="28px", width="28px", padding="0px 0px 0px 4px"
        )
    close_button_args["icon"] = close_button_icon

    try:
        toolbar_button = widgets.ToggleButton(**widget_args)
    except:
        widget_args.pop("layout")
        toolbar_button = widgets.ToggleButton(**widget_args)
        toolbar_button.layout.width = "28px"
        toolbar_button.layout.height = "28px"
        toolbar_button.layout.padding = "0px 0px 0px 4px"

    try:
        close_button = widgets.ToggleButton(**close_button_args)
    except:
        close_button_args.pop("layout")
        close_button = widgets.ToggleButton(**close_button_args)
        close_button.layout.width = "28px"
        close_button.layout.height = "28px"
        close_button.layout.padding = "0px 0px 0px 4px"

    toolbar_widget = widgets.VBox()
    toolbar_widget.children = [toolbar_button]
    toolbar_header = widgets.HBox()
    if show_close_button:
        toolbar_header.children = [close_button, toolbar_button]
    else:
        toolbar_header.children = [toolbar_button]
    toolbar_footer = widgets.VBox()

    if widget is not None:
        toolbar_footer.children = [
            widget,
        ]
    else:
        toolbar_footer.children = []

    def toolbar_btn_click(change):
        if change["new"]:
            close_button.value = False
            toolbar_widget.children = [toolbar_header, toolbar_footer]
            if display_widget is not None:
                widget.outputs = ()
                with widget:
                    display(display_widget)
        else:
            toolbar_widget.children = [toolbar_button]

    toolbar_button.observe(toolbar_btn_click, "value")

    def close_btn_click(change):
        if change["new"]:
            toolbar_button.value = False
            if m is not None:
                control = getattr(m, name)
                if control is not None and control in m.controls:
                    m.remove_control(control)
                    delattr(m, name)
            toolbar_widget.close()

    close_button.observe(close_btn_click, "value")

    toolbar_button.value = opened
    if m is not None:
        import ipyleaflet

        toolbar_control = ipyleaflet.WidgetControl(
            widget=toolbar_widget, position=position
        )

        if toolbar_control not in m.controls:
            m.add_control(toolbar_control)

            setattr(m, name, toolbar_control)

    else:
        return toolbar_widget