python-cmr


Namepython-cmr JSON
Version 0.13.0 PyPI version JSON
download
home_pagehttps://github.com/nasa/python_cmr
SummaryPython wrapper to the NASA Common Metadata Repository (CMR) API.
upload_time2024-09-13 22:35:08
maintainerNone
docs_urlNone
authorpython_cmr
requires_python<4.0.0,>=3.8.1
licenseMIT
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            This repository is a copy
of [jddeal/python_cmr](https://github.com/jddeal/python-cmr/tree/ef0f9e7d67ce99d342a568bd6a098c3462df16d2) which is no
longer maintained. It has been copied here with the permission of the original author for the purpose of continuing to
develop a python library that can be used for CMR access.

----

Python CMR
==========

[![PyPI](https://img.shields.io/pypi/v/python_cmr.svg)](https://pypi.python.org/pypi/python_cmr)
[![Downloads](https://img.shields.io/pypi/dm/python_cmr)](https://pypistats.org/packages/python_cmr)
[![Python versions](https://img.shields.io/pypi/pyversions/python_cmr.svg)](https://pypi.python.org/pypi/python_cmr)
[![Build Status](https://github.com/nasa/python_cmr/actions/workflows/python-app.yml/badge.svg)](https://github.com/nasa/python_cmr/actions)
[![CodeQL](https://github.com/nasa/python_cmr/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/nasa/python_cmr/actions/workflows/codeql-analysis.yml)
[![Checked with mypy](https://www.mypy-lang.org/static/mypy_badge.svg)](https://mypy-lang.org/)

Python CMR is an easy to use wrapper to the NASA
EOSDIS [Common Metadata Repository API](https://cmr.earthdata.nasa.gov/search/). This package aims to make querying the
API intuitive and less error-prone by providing methods that will preemptively check for invalid input and handle the
URL encoding the CMR API expects.

Getting access to NASA's earth science metadata is as simple as this:

```python
from cmr import CollectionQuery, GranuleQuery, ToolQuery, ServiceQuery, VariableQuery

api = CollectionQuery()
collections = api.archive_center("LP DAAC").keyword("AST_L1*").get(5)

print("Collections:")
for collection in collections:
  print(collection["short_name"])

api = GranuleQuery()
granules = api.short_name("AST_L1T").point(-112.73, 42.5).get(3)

print("Granule Titles:")
for granule in granules:
  print(granule["title"])
```

``` text
Collections:
AST_L1A
AST_L1AE
AST_L1T
Granule Titles:
SC:AST_L1T.003:2149105822
SC:AST_L1T.003:2149105820
SC:AST_L1T.003:2149155037
```

Installation
============

To install from pypi:

```plain
pip install python-cmr
```

To install from GitHub, perhaps to try out the dev branch:

```plain
git clone https://github.com/nasa/python_cmr
cd python-cmr
pip install .
```

Examples
========

This library is broken into two classes, CollectionQuery and GranuleQuery. Each of these classes provide a large set of
methods used to build a query for CMR. Not all parameters provided by the CMR API are covered by this version of
python-cmr.

The following methods are available to both collection and granule queries:

```python
# search for granules matching a specific product/short_name
api.short_name("AST_L1T")

# search for granules matching a specific version
api.version("006")

# search for granules at a specific longitude and latitude
api.point(-112.73, 42.5)

# search for granules in an area bound by a box (lower left lon/lat, upper right lon/lat)
api.bounding_box(-112.70, 42.5, -110, 44.5)

# search for granules in a polygon (these need to be in counter clockwise order and the
# last coordinate must match the first in order to close the polygon)
api.polygon([(-100, 40), (-110, 40), (-105, 38), (-100, 40)])

# search for granules in a line
api.line([(-100, 40), (-90, 40), (-95, 38)])

# search for granules in an open or closed date range
api.temporal("2016-10-10T01:02:00Z", "2016-10-12T00:00:30Z")
api.temporal("2016-10-10T01:02:00Z", None)
api.temporal(datetime(2016, 10, 10, 1, 2, 0), datetime.now())

# search for granules by revision_date
api.revision_date("2022-05-16", "2024-06-30")

# only include granules available for download
api.downloadable()

# only include granules that are unavailable for download
api.online_only()

# filter by specific satellite platform
api.platform("Terra")

# search for collections/granules associated with or identified by concept IDs
# note: often the ECHO collection ID can be used here as well
# note: when using CollectionQuery, only collection concept IDs can be passed
# note: when uses GranuleQuery, passing a collection's concept ID will filter by granules associated
#       with that particular collection.
api.concept_id("C1299783579-LPDAAC_ECS")
api.concept_id(["G1327299284-LPDAAC_ECS", "G1326330014-LPDAAC_ECS"])

# search by provider
api.provider('POCLOUD')

# search non-ops CMR environment
from cmr import CMR_UAT
api.mode(CMR_UAT)
```

Granule searches support these methods (in addition to the shared methods above):

```python
# search for a granule by its unique ID
api.granule_ur("SC:AST_L1T.003:2150315169")
# search for granules from a specific orbit
api.orbit_number(5000)
# search for a granule by name
api.short_name("MOD09GA").readable_granule_name(["*h32v08*","*h30v13*"])

# filter by the day/night flag
api.day_night_flag("day")

# filter by cloud cover percentage range
api.cloud_cover(25, 75)

# filter by specific instrument
api.instrument("MODIS")

# filter by a sort_key note: sort_keys are require some other fields to find
# some existing granules before they can be sorted
api.parameters(short_name="OMNO2", version="003", provider='GES_DISC', sort_key='-start_date')
```

Collection searches support these methods (in addition to the shared methods above):

```python
# search for collections from a specific archive center
api.archive_center("LP DAAC")

# case insensitive, wildcard enabled text search through most collection fields
api.keyword("M*D09")

# search by native_id
api.native_id('native_id')

# filter by tool concept id
api.tool_concept_id('TL2092786348-POCLOUD')

# filter by service concept id
api.service_concept_id('S1962070864-POCLOUD')

# filter by processing level id
api.processing_level_id('3')
```

Service searches support the following methods

```python
# Search via provider
api = ServiceQuery()
api.provider('POCLOUD')

# Search via native_id
api.native_id('POCLOUD_podaac_l2_cloud_subsetter')

# Search via name
api.name('PODAAC L2 Cloud Subsetter')

# Search via concept_id
api.concept_id('S1962070864-POCLOUD')
```

Tool searches support the following methods

```python
# Search via provider
api = ToolQuery()
api.provider('POCLOUD')

# Search via native_id
api.native_id('POCLOUD_hitide')

# Search via name
api.name('hitide')

# Search via concept_id
api.concept_id('TL2092786348-POCLOUD')
```

Variable searches support the following methods

```python
# Search via provider
api = VariableQuery()
api.provider('POCLOUD')

# Search via native_id
api.native_id('JASON_CS_S6A_L2_AMR_RAD_STATIC_CALIBRATION-AMR_Side_1-acc_lat')

# Search via name
api.name('/AMR_Side_1/acc_lat')

# Search via concept_id
api.concept_id('V2112019824-POCLOUD')

# Search via instance format
api.instance_format(["zarr", "kerchunk"])
```

As an alternative to chaining methods together to set the parameters of your query, a method exists to allow you to pass
your parameters as keyword arguments:

```python
# search for AST_L1T version 003 granules at latitude 42, longitude -100
api.parameters(
    short_name="AST_L1T",
    version="003",
    point=(-100, 42)
)
```

Note: the kwarg key should match the name of a method from the above examples, and the value should be a tuple if it's a
parameter that requires multiple values.

To inspect and retrieve results from the API, the following methods are available:

```python
# inspect the number of results the query will return without downloading the results
print(api.hits())

# retrieve 100 granules
granules = api.get(100)

# retrieve 25,000 granules
granules = api.get(25000)

# retrieve all the granules possible for the query
granules = api.get_all()  # this is a shortcut for api.get(api.hits())
```

By default the responses will return as json and be accessible as a list of python dictionaries. Other formats can be
specified before making the request:

```python
granules = api.format("echo10").get(100)
```

We can add token to the api calls by setting headers using the following functions:

```python
# Use token function for EDL echo-token or launchpad token
api.token(token)

# Use bearer token function for EDL bearer tokens
api.bearer_token(token)
```

The following formats are supported for both granule and collection queries:

- json (default)
- xml
- echo10
- iso
- iso19115
- csv
- atom
- kml
- native

Collection queries also support the following formats:

- dif
- dif10
- opendata
- umm_json
- umm_json_vX_Y (ex: umm_json_v1_9)

Developing
==========

python-cmr uses the [poetry](https://python-poetry.org/) build system. Download and install poetry before starting
development

Install Dependencies
--------------------

With dev dependencies:

```shell
poetry install
```

Without dev dependencies:

```shell
poetry install --no-dev
```

Update Dependencies
-------------------

```shell
poetry update
```

Add new Dependency
------------------

```shell
poetry add requests
```

Development-only dependency:

```shell
poetry add --dev pytest
```

Build project
-------------

```shell
poetry build
```

Lint project
------------

```shell
poetry run flake8
```

Run Tests
---------

```shell
poetry run pytest
```

Run Type Checks
---------------

```shell
poetry run mypy cmr tests
```


            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/nasa/python_cmr",
    "name": "python-cmr",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0.0,>=3.8.1",
    "maintainer_email": null,
    "keywords": null,
    "author": "python_cmr",
    "author_email": "nasa/python_cmr@github.com",
    "download_url": "https://files.pythonhosted.org/packages/5d/04/fbe29a33172fc093d998600c8ee14bfb82e6b4b2ce3d08da1afc04ff5fce/python_cmr-0.13.0.tar.gz",
    "platform": null,
    "description": "This repository is a copy\nof [jddeal/python_cmr](https://github.com/jddeal/python-cmr/tree/ef0f9e7d67ce99d342a568bd6a098c3462df16d2) which is no\nlonger maintained. It has been copied here with the permission of the original author for the purpose of continuing to\ndevelop a python library that can be used for CMR access.\n\n----\n\nPython CMR\n==========\n\n[![PyPI](https://img.shields.io/pypi/v/python_cmr.svg)](https://pypi.python.org/pypi/python_cmr)\n[![Downloads](https://img.shields.io/pypi/dm/python_cmr)](https://pypistats.org/packages/python_cmr)\n[![Python versions](https://img.shields.io/pypi/pyversions/python_cmr.svg)](https://pypi.python.org/pypi/python_cmr)\n[![Build Status](https://github.com/nasa/python_cmr/actions/workflows/python-app.yml/badge.svg)](https://github.com/nasa/python_cmr/actions)\n[![CodeQL](https://github.com/nasa/python_cmr/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/nasa/python_cmr/actions/workflows/codeql-analysis.yml)\n[![Checked with mypy](https://www.mypy-lang.org/static/mypy_badge.svg)](https://mypy-lang.org/)\n\nPython CMR is an easy to use wrapper to the NASA\nEOSDIS [Common Metadata Repository API](https://cmr.earthdata.nasa.gov/search/). This package aims to make querying the\nAPI intuitive and less error-prone by providing methods that will preemptively check for invalid input and handle the\nURL encoding the CMR API expects.\n\nGetting access to NASA's earth science metadata is as simple as this:\n\n```python\nfrom cmr import CollectionQuery, GranuleQuery, ToolQuery, ServiceQuery, VariableQuery\n\napi = CollectionQuery()\ncollections = api.archive_center(\"LP DAAC\").keyword(\"AST_L1*\").get(5)\n\nprint(\"Collections:\")\nfor collection in collections:\n  print(collection[\"short_name\"])\n\napi = GranuleQuery()\ngranules = api.short_name(\"AST_L1T\").point(-112.73, 42.5).get(3)\n\nprint(\"Granule Titles:\")\nfor granule in granules:\n  print(granule[\"title\"])\n```\n\n``` text\nCollections:\nAST_L1A\nAST_L1AE\nAST_L1T\nGranule Titles:\nSC:AST_L1T.003:2149105822\nSC:AST_L1T.003:2149105820\nSC:AST_L1T.003:2149155037\n```\n\nInstallation\n============\n\nTo install from pypi:\n\n```plain\npip install python-cmr\n```\n\nTo install from GitHub, perhaps to try out the dev branch:\n\n```plain\ngit clone https://github.com/nasa/python_cmr\ncd python-cmr\npip install .\n```\n\nExamples\n========\n\nThis library is broken into two classes, CollectionQuery and GranuleQuery. Each of these classes provide a large set of\nmethods used to build a query for CMR. Not all parameters provided by the CMR API are covered by this version of\npython-cmr.\n\nThe following methods are available to both collection and granule queries:\n\n```python\n# search for granules matching a specific product/short_name\napi.short_name(\"AST_L1T\")\n\n# search for granules matching a specific version\napi.version(\"006\")\n\n# search for granules at a specific longitude and latitude\napi.point(-112.73, 42.5)\n\n# search for granules in an area bound by a box (lower left lon/lat, upper right lon/lat)\napi.bounding_box(-112.70, 42.5, -110, 44.5)\n\n# search for granules in a polygon (these need to be in counter clockwise order and the\n# last coordinate must match the first in order to close the polygon)\napi.polygon([(-100, 40), (-110, 40), (-105, 38), (-100, 40)])\n\n# search for granules in a line\napi.line([(-100, 40), (-90, 40), (-95, 38)])\n\n# search for granules in an open or closed date range\napi.temporal(\"2016-10-10T01:02:00Z\", \"2016-10-12T00:00:30Z\")\napi.temporal(\"2016-10-10T01:02:00Z\", None)\napi.temporal(datetime(2016, 10, 10, 1, 2, 0), datetime.now())\n\n# search for granules by revision_date\napi.revision_date(\"2022-05-16\", \"2024-06-30\")\n\n# only include granules available for download\napi.downloadable()\n\n# only include granules that are unavailable for download\napi.online_only()\n\n# filter by specific satellite platform\napi.platform(\"Terra\")\n\n# search for collections/granules associated with or identified by concept IDs\n# note: often the ECHO collection ID can be used here as well\n# note: when using CollectionQuery, only collection concept IDs can be passed\n# note: when uses GranuleQuery, passing a collection's concept ID will filter by granules associated\n#       with that particular collection.\napi.concept_id(\"C1299783579-LPDAAC_ECS\")\napi.concept_id([\"G1327299284-LPDAAC_ECS\", \"G1326330014-LPDAAC_ECS\"])\n\n# search by provider\napi.provider('POCLOUD')\n\n# search non-ops CMR environment\nfrom cmr import CMR_UAT\napi.mode(CMR_UAT)\n```\n\nGranule searches support these methods (in addition to the shared methods above):\n\n```python\n# search for a granule by its unique ID\napi.granule_ur(\"SC:AST_L1T.003:2150315169\")\n# search for granules from a specific orbit\napi.orbit_number(5000)\n# search for a granule by name\napi.short_name(\"MOD09GA\").readable_granule_name([\"*h32v08*\",\"*h30v13*\"])\n\n# filter by the day/night flag\napi.day_night_flag(\"day\")\n\n# filter by cloud cover percentage range\napi.cloud_cover(25, 75)\n\n# filter by specific instrument\napi.instrument(\"MODIS\")\n\n# filter by a sort_key note: sort_keys are require some other fields to find\n# some existing granules before they can be sorted\napi.parameters(short_name=\"OMNO2\", version=\"003\", provider='GES_DISC', sort_key='-start_date')\n```\n\nCollection searches support these methods (in addition to the shared methods above):\n\n```python\n# search for collections from a specific archive center\napi.archive_center(\"LP DAAC\")\n\n# case insensitive, wildcard enabled text search through most collection fields\napi.keyword(\"M*D09\")\n\n# search by native_id\napi.native_id('native_id')\n\n# filter by tool concept id\napi.tool_concept_id('TL2092786348-POCLOUD')\n\n# filter by service concept id\napi.service_concept_id('S1962070864-POCLOUD')\n\n# filter by processing level id\napi.processing_level_id('3')\n```\n\nService searches support the following methods\n\n```python\n# Search via provider\napi = ServiceQuery()\napi.provider('POCLOUD')\n\n# Search via native_id\napi.native_id('POCLOUD_podaac_l2_cloud_subsetter')\n\n# Search via name\napi.name('PODAAC L2 Cloud Subsetter')\n\n# Search via concept_id\napi.concept_id('S1962070864-POCLOUD')\n```\n\nTool searches support the following methods\n\n```python\n# Search via provider\napi = ToolQuery()\napi.provider('POCLOUD')\n\n# Search via native_id\napi.native_id('POCLOUD_hitide')\n\n# Search via name\napi.name('hitide')\n\n# Search via concept_id\napi.concept_id('TL2092786348-POCLOUD')\n```\n\nVariable searches support the following methods\n\n```python\n# Search via provider\napi = VariableQuery()\napi.provider('POCLOUD')\n\n# Search via native_id\napi.native_id('JASON_CS_S6A_L2_AMR_RAD_STATIC_CALIBRATION-AMR_Side_1-acc_lat')\n\n# Search via name\napi.name('/AMR_Side_1/acc_lat')\n\n# Search via concept_id\napi.concept_id('V2112019824-POCLOUD')\n\n# Search via instance format\napi.instance_format([\"zarr\", \"kerchunk\"])\n```\n\nAs an alternative to chaining methods together to set the parameters of your query, a method exists to allow you to pass\nyour parameters as keyword arguments:\n\n```python\n# search for AST_L1T version 003 granules at latitude 42, longitude -100\napi.parameters(\n    short_name=\"AST_L1T\",\n    version=\"003\",\n    point=(-100, 42)\n)\n```\n\nNote: the kwarg key should match the name of a method from the above examples, and the value should be a tuple if it's a\nparameter that requires multiple values.\n\nTo inspect and retrieve results from the API, the following methods are available:\n\n```python\n# inspect the number of results the query will return without downloading the results\nprint(api.hits())\n\n# retrieve 100 granules\ngranules = api.get(100)\n\n# retrieve 25,000 granules\ngranules = api.get(25000)\n\n# retrieve all the granules possible for the query\ngranules = api.get_all()  # this is a shortcut for api.get(api.hits())\n```\n\nBy default the responses will return as json and be accessible as a list of python dictionaries. Other formats can be\nspecified before making the request:\n\n```python\ngranules = api.format(\"echo10\").get(100)\n```\n\nWe can add token to the api calls by setting headers using the following functions:\n\n```python\n# Use token function for EDL echo-token or launchpad token\napi.token(token)\n\n# Use bearer token function for EDL bearer tokens\napi.bearer_token(token)\n```\n\nThe following formats are supported for both granule and collection queries:\n\n- json (default)\n- xml\n- echo10\n- iso\n- iso19115\n- csv\n- atom\n- kml\n- native\n\nCollection queries also support the following formats:\n\n- dif\n- dif10\n- opendata\n- umm_json\n- umm_json_vX_Y (ex: umm_json_v1_9)\n\nDeveloping\n==========\n\npython-cmr uses the [poetry](https://python-poetry.org/) build system. Download and install poetry before starting\ndevelopment\n\nInstall Dependencies\n--------------------\n\nWith dev dependencies:\n\n```shell\npoetry install\n```\n\nWithout dev dependencies:\n\n```shell\npoetry install --no-dev\n```\n\nUpdate Dependencies\n-------------------\n\n```shell\npoetry update\n```\n\nAdd new Dependency\n------------------\n\n```shell\npoetry add requests\n```\n\nDevelopment-only dependency:\n\n```shell\npoetry add --dev pytest\n```\n\nBuild project\n-------------\n\n```shell\npoetry build\n```\n\nLint project\n------------\n\n```shell\npoetry run flake8\n```\n\nRun Tests\n---------\n\n```shell\npoetry run pytest\n```\n\nRun Type Checks\n---------------\n\n```shell\npoetry run mypy cmr tests\n```\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Python wrapper to the NASA Common Metadata Repository (CMR) API.",
    "version": "0.13.0",
    "project_urls": {
        "Homepage": "https://github.com/nasa/python_cmr",
        "Repository": "https://github.com/nasa/python_cmr"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "79e25fa011e34bf81a3d47fb45e3a2ff86baabbc2853439285205bd14b245922",
                "md5": "935d1f986a270ccc14f62329142dd145",
                "sha256": "4c71f15ae662f58d0220f533abb662c14937c91f93f66976ef533f369d0f5cd7"
            },
            "downloads": -1,
            "filename": "python_cmr-0.13.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "935d1f986a270ccc14f62329142dd145",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0.0,>=3.8.1",
            "size": 14897,
            "upload_time": "2024-09-13T22:35:07",
            "upload_time_iso_8601": "2024-09-13T22:35:07.073105Z",
            "url": "https://files.pythonhosted.org/packages/79/e2/5fa011e34bf81a3d47fb45e3a2ff86baabbc2853439285205bd14b245922/python_cmr-0.13.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "5d04fbe29a33172fc093d998600c8ee14bfb82e6b4b2ce3d08da1afc04ff5fce",
                "md5": "f7fc515e5af6512409da934e918d3756",
                "sha256": "ac671d9696979427ee1f98104bf1dbe2ae547f8e0cc9f63ae5efcc6d1f436c6d"
            },
            "downloads": -1,
            "filename": "python_cmr-0.13.0.tar.gz",
            "has_sig": false,
            "md5_digest": "f7fc515e5af6512409da934e918d3756",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0.0,>=3.8.1",
            "size": 17175,
            "upload_time": "2024-09-13T22:35:08",
            "upload_time_iso_8601": "2024-09-13T22:35:08.531651Z",
            "url": "https://files.pythonhosted.org/packages/5d/04/fbe29a33172fc093d998600c8ee14bfb82e6b4b2ce3d08da1afc04ff5fce/python_cmr-0.13.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-09-13 22:35:08",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "nasa",
    "github_project": "python_cmr",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "python-cmr"
}
        
Elapsed time: 0.29701s