Python CMR is an easy to use wrapper to the NASA EOSDIS Common Metadata Repository API.

Overview

This repository is a copy of jddeal/python_cmr 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

CodeQL

Python CMR is an easy to use wrapper to the NASA EOSDIS Common Metadata Repository API. 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:

>> for collection in collections: >>> print(collection["short_name"]) AST_L1A AST_L1AE AST_L1T >>> api = GranuleQuery() >>> granules = api.short_name("AST_L1T").point(-112.73, 42.5).get(3) >>> for granule in granules: >>> print(granule["title"]) SC:AST_L1T.003:2149105822 SC:AST_L1T.003:2149105820 SC:AST_L1T.003:2149155037 ">
>>> from cmr import CollectionQuery, GranuleQuery

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

>>> for collection in collections:
>>>   print(collection["short_name"])
AST_L1A
AST_L1AE
AST_L1T

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

>>> for granule in granules:
>>>   print(granule["title"])
SC:AST_L1T.003:2149105822
SC:AST_L1T.003:2149105820
SC:AST_L1T.003:2149155037

Installation

To install from pypi:

$ pip install python-cmr

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

$ git clone https://github.com/jddeal/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 collecton and granule queries:

>> 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()) # only include granules available for download >>> api.downloadable() # only include granules that are unavailable for download >>> api.online_only() # 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 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())

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

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

# 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')

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

>> api.orbit_number(5000) # 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 or platform >>> api.instrument("MODIS") >>> api.platform("Terra") ">
# 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)

# 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 or platform
>>> api.instrument("MODIS")
>>> api.platform("Terra")

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

>> 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') ">
# 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')

Service searches support the following methods

# 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')

Tool searches support the following methods

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

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

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

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:

# 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 retreive results from the API, the following methods are available:

# 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:

>>> granules = api.format("echo10").get(100)

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)
Comments
  • Variablesquery

    Variablesquery

    • Added in VariableQuery class to query umm-v
    • Added in tests for VariableQuery
    • Changed url in readme for github url
    • Concept_id function return self so we can chain functions
    opened by sliu008 1
  • Release/0.7.0

    Release/0.7.0

    [0.7.0]

    Added

    • New workflow that runs lint and test
    • New function Query.token to add an auth token to the request sent to CMR

    Changed

    opened by frankinspace 0
  • Release/0.6.0

    Release/0.6.0

    [0.6.0]

    Added

    • New support for querying variables (UMM-V)

    Changed

    • Can now import ToolQuery ServiceQuery VariableQuery straight from cmr module. (e.g. from cmr import ToolQuery)
    opened by frankinspace 0
  • Release/0.5.0

    Release/0.5.0

    [0.5.0]

    Added

    • New support for querying tools (UMM-T) and services (UMM-S)
    • CodeQL Analysis on pushes and pull requests

    Changed

    • Moved to github.com/nasa/python_cmr
    opened by frankinspace 0
  • New searching criterion: circle

    New searching criterion: circle

    Similar to the point criterion but includes a buffer around the point. One application is searching for granules with data within a certain distance of a waypoint such as a mooring or a meteorological station.

    opened by castelao 0
  • Bump certifi from 2021.10.8 to 2022.12.7

    Bump certifi from 2021.10.8 to 2022.12.7

    Bumps certifi from 2021.10.8 to 2022.12.7.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
Releases(v0.7.0)
  • v0.7.0(Nov 23, 2021)

    [0.7.0]

    Added

    • New workflow that runs lint and test
    • New function Query.token to add an authentication token to the request sent to CMR

    Changed

    What's Changed

    • Create python-app.yml by @frankinspace in https://github.com/nasa/python_cmr/pull/7
    • Feature/token by @sliu008 in https://github.com/nasa/python_cmr/pull/8
    • Release/0.7.0 by @frankinspace in https://github.com/nasa/python_cmr/pull/9

    Full Changelog: https://github.com/nasa/python_cmr/compare/v0.6.0...v0.7.0

    Source code(tar.gz)
    Source code(zip)
  • v0.6.0(Oct 28, 2021)

    [0.6.0]

    Added

    • New support for querying variables (UMM-V)

    Changed

    • Can now import ToolQuery ServiceQuery VariableQuery straight from cmr module. (e.g. from cmr import ToolQuery)
    Source code(tar.gz)
    Source code(zip)
  • v0.5.0(Oct 15, 2021)

    [0.5.0]

    Added

    • New support for querying tools (UMM-T) and services (UMM-S)
    • CodeQL Analysis on pushes and pull requests

    Changed

    • Moved to github.com/nasa/python_cmr
    Source code(tar.gz)
    Source code(zip)
Owner
NASA
Read about NASA's Open Data initiative here: https://www.nasa.gov/open/ & Members Find Instructions here: http://nasa.github.io/
NASA
🤖 A fully featured, easy to use Python wrapper for the Walmart Open API

Wapy Wapy is a fully featured Python wrapper for the Walmart Open API. Features Easy to use, object oriented interface to the Walmart Open API. (Produ

Carlos Roso 43 Oct 14, 2022
A modern, easy to use, feature-rich, and async ready API wrapper for Discord written in Python.

A modern, easy to use, feature-rich, and async ready API wrapper for Discord written in Python. Key Features Modern Pythonic API using async and await

Senpai Development 4 Nov 5, 2021
Petpy is an easy-to-use and convenient Python wrapper for the Petfinder API.

Petpy is an easy-to-use and convenient Python wrapper for the Petfinder API. Includes methods for parsing output JSON into pandas DataFrames for easier data analysis

Aaron Schlegel 27 Nov 19, 2022
A modern, easy to use, feature-rich, and async ready API wrapper for Discord written in Python.

disfork A modern, easy to use, feature-rich, and async ready API wrapper for Discord written in Python. Key Features Modern Pythonic API using async a

null 2 Feb 9, 2022
A modern, easy to use, feature-rich, and async ready API wrapper improved and revived from original discord.py.

A Python API wrapper that is improved and revived from the original discord.py

Orion 19 Nov 6, 2021
Easy to use API Wrapper for somerandomapi.ml.

Overview somerandomapi is an API Wrapper for some-random-api.ml Examples Asynchronous from somerandomapi import Animal import asyncio async def main

Myxi 1 Dec 31, 2021
Easy to use API Wrapper for somerandomapi.ml.

Overview somerandomapi is an API Wrapper for some-random-api.ml Examples Asynchronous from somerandomapi import Animal

Myxi 1 Dec 31, 2021
🚀 An asynchronous python API wrapper meant to replace discord.py - Snappy discord api wrapper written with aiohttp & websockets

Pincer An asynchronous python API wrapper meant to replace discord.py ❗ The package is currently within the planning phase ?? Links |Join the discord

Pincer 125 Dec 26, 2022
Low-level, feature rich and easy to use discord python wrapper

PWRCord Low-level, feature rich and easy to use discord python wrapper Important Note: At this point, this library API is considered unstable and can

MIguel Lopes 1 Dec 26, 2021
Aws-lambda-requests-wrapper - Request/Response wrapper for AWS Lambda with API Gateway

AWS Lambda Requests Wrapper Request/Response wrapper for AWS Lambda with API Gat

null 1 May 20, 2022
SickNerd aims to slowly enumerate Google Dorks via the googlesearch API then requests found pages for metadata

CLI tool for making Google Dorking a passive recon experience. With the ability to fetch and filter dorks from GHDB.

Jake Wnuk 21 Jan 2, 2023
PRAW, an acronym for "Python Reddit API Wrapper", is a python package that allows for simple access to Reddit's API.

PRAW: The Python Reddit API Wrapper PRAW, an acronym for "Python Reddit API Wrapper", is a Python package that allows for simple access to Reddit's AP

Python Reddit API Wrapper Development 3k Dec 29, 2022
PRAW, an acronym for "Python Reddit API Wrapper", is a python package that allows for simple access to Reddit's API.

PRAW: The Python Reddit API Wrapper PRAW, an acronym for "Python Reddit API Wrapper", is a Python package that allows for simple access to Reddit's AP

Python Reddit API Wrapper Development 3k Dec 29, 2022
The Github repository for the Amari API wrapper.

Amari.py Amari.py is an async, easy to use API wrapper for the AmariBot. Installation Enter any of these commands to install the library: pip install

TheF1ng3r 5 Dec 19, 2022
Scratch2py or S2py is a easy to use, versatile tool to communicate with the Scratch API Based of Scratch2py

Scratch2py Scratch2py or S2py is a easy to use, versatile tool to communicate with the Scratch API Based of Scratch2py Installation Run this command i

null 2 Jan 13, 2022
Python API wrapper around Trello's API

A wrapper around the Trello API written in Python. Each Trello object is represented by a corresponding Python object. The attributes of these objects

Richard Kolkovich 904 Jan 2, 2023
Async ready API wrapper for Revolt API written in Python.

Mutiny Async ready API wrapper for Revolt API written in Python. Installation Python 3.9 or higher is required To install the library, you can just ru

null 16 Mar 29, 2022
A Python API wrapper for the Twitter API!

PyTweet PyTweet is an api wrapper made for twitter using twitter's api version 2! Installation Windows py3 -m pip install PyTweet Linux python -m pip

TheFarGG 1 Nov 19, 2022
Python API wrapper library for Convex Value API

convex-value-python Python API wrapper library for Convex Value API. Further Links: Convex Value homepage @ConvexValue on Twitter JB on Twitter Authen

Aaron DeVera 2 May 11, 2022