Package: erddap-python
ERDDAP python libraryAboutERDDAPis a data server that gives you a simple, consistent way to download subsets of gridded and tabular scientific datasets in common file formats and make graphs and maps.erddap-python is a python client for the ERDDAP Restful API, it can obtain server status metrics, provides search methods, gives tabledap and griddap class objects for metadata and data access.This library was initially built forCICESE,CIGOM,OORCO, andCEMIEOceanoprojects for the automation of reports, interactive custom visualizations and data analysis.  Most of the functionality was inspired on the work oferddapylibrary, but designed more for a more flexible backend service construction in mind.Full API reference can be foundhere.Projects using erddap-pythonERDDAP server's status metrics dashboard using StreamlitModule for Ocean Observatory Data Analysis libraryRequirementspython 3python libraries numpy, pandas, xarray, netCDF4InstallationUsing pip:$ pip install erddap-pythonUsageExplore a ERDDAP ServerConnect to a ERDDAP Server, and get some basic search.>>>fromerddapClientimportERDDAP_Server>>>>>>remoteServer=ERDDAP_Server('https://coastwatch.pfeg.noaa.gov/erddap')>>>remoteServer<erddapClient.ERDDAP_Server>Serverversion:ERDDAP_version=2.11searchandadvancedSerchmethods are available, it builds the search request URL and also can
make the request to the ERDDAP restful services to obtain results.>>>searchRequest=remoteServer.search(searchFor="gliders")>>>searchRequest<erddapClient.ERDDAP_SearchResults>Results:1[0-<erddapClient.ERDDAP_Tabledap>scrippsGliders,"Gliders, Scripps Institution of Oceanography, 2014-present"]The methods returns an object with a list of the ERDDAP Tabledap or Griddap objects that matched the search filters.Connect to Tabledap datasetsUsing theERDDAP_Tabledapclass to build ERDDAP data request URL's>>>fromerddapClientimportERDDAP_Tabledap>>>>>>remote=ERDDAP_Tabledap('https://coastwatch.pfeg.noaa.gov/erddap','cwwcNDBCMet')>>>>>>remote.setResultVariables(['station','time','atmp'])>>>print(remote.getURL('htmlTable'))'https://coastwatch.pfeg.noaa.gov/erddap/tabledap/cwwcNDBCMet.htmlTable?station%2Ctime%2Catmp'The tabledap object as internally a stack for resultVariables, constrainst and server side operations. You
can keep adding them and get the different urls.>>>importdatetimeasdt>>>>>>remote.addConstraint('time>=2020-12-29T00:00:00Z')\..:.addConstraint({'time<=':dt.datetime(2020,12,31)})>>>remote.getURL()'https://coastwatch.pfeg.noaa.gov/erddap/tabledap/cwwcNDBCMet.csvp?station%2Ctime%2Catmp&time%3E=2020-12-29T00%3A00%3A00Z&time%3C=2020-12-31T00%3A00%3A00Z'>>>>>>remote.orderByClosest(['station','time/1day'])>>>remote.getURL()'https://coastwatch.pfeg.noaa.gov/erddap/tabledap/cwwcNDBCMet.csvp?station%2Ctime%2Catmp&time%3E=2020-12-29T00%3A00%3A00Z&time%3C=2020-12-31T00%3A00%3A00Z&orderByClosest(%22station%2Ctime/1day%22)'>>>The class has methods to clear the result variables, the constraints, and the server side operations that are added in the stack:clearConstraints(),clearResultVariable(),clearServerSideFunctionsorclearQuery()Tabledap data subset requestAn user can build the query chaining the result variables, constraints and server side operations, and make the data
request in all the available formats that ERDDAP provides.>>>>>>remote.clearQuery()>>>>>>responseCSV=(..:remote.setResultVariables(['station','time','atmp'])..:.addConstraint('time>=2020-12-29T00:00:00Z')..:.addConstraint('time<=2020-12-31T00:00:00Z')..:.orderByClosest(['station','time/1day'])..:.getData('csvp')..:)>>>>>>print(responseCSV)station,time(UTC),atmp(degree_C)41001,2020-12-29T00:00:00Z,17.341001,2020-12-30T00:00:00Z,13.741001,2020-12-31T00:00:00Z,15.941004,2020-12-29T00:10:00Z,18.141004,2020-12-30T00:00:00Z,17.141004,2020-12-31T00:00:00Z,21.241008,2020-12-29T00:50:00Z,14.8....>>>>>>remote.clearQuery()>>>>>>responsePandas=(..:remote.setResultVariables(['station','time','atmp'])..:.addConstraint('time>=2020-12-29T00:00:00Z')..:.addConstraint('time<=2020-12-31T00:00:00Z')..:.orderByClosest(['station','time/1day'])..:.getDataFrame()..:)>>>>>>responsePandasstationtime(UTC)atmp(degree_C)0410012020-12-29T00:00:00Z17.31410012020-12-30T00:00:00Z13.72410012020-12-31T00:00:00Z15.93410042020-12-29T00:00:00Z18.24410042020-12-30T00:00:00Z17.1............2006YKRV22020-12-30T00:00:00ZNaN2007YKRV22020-12-31T00:00:00Z8.12008YKTV22020-12-29T00:00:00Z11.32009YKTV22020-12-30T00:00:00ZNaN2010YKTV22020-12-31T00:00:00Z7.1[2011rowsx3columns]Griddap datasetsAll the url building functions, and data request functionality is available in theERDDAP_Griddapclass.With this class you can download data subsets in all the available ERDDAP data formats, plus the posibility to request a fully described xarray.DataArrays objects.This class can parse the griddap query, and detect if the query is malformed before requesting data from the
ERDDAP server.Usage sample:>>>fromerddapClientimportERDDAP_Griddap>>>>>>remote=ERDDAP_Griddap('https://coastwatch.pfeg.noaa.gov/erddap','hycom_gom310D')>>>>>>print(remote)<erddapClient.ERDDAP_Griddap>Title:NRLHYCOM1/25degmodeloutput,GulfofMexico,10.04Expt31.0,2009-2014,AtDepthsServerURL:https://coastwatch.pfeg.noaa.gov/erddapDatasetID:hycom_gom310DDimensions:time(double)range=(cftime.DatetimeGregorian(2009,4,2,0,0,0,0),cftime.DatetimeGregorian(2014,8,30,0,0,0,0))Standardname:timeUnits:secondssince1970-01-01T00:00:00Zdepth(float)range=(0.0,5500.0)Standardname:depthUnits:mlatitude(float)range=(18.09165,31.96065)Standardname:latitudeUnits:degrees_northlongitude(float)range=(-98.0,-76.40002)Standardname:longitudeUnits:degrees_eastVariables:temperature(float)Standardname:sea_water_potential_temperatureUnits:degCsalinity(float)Standardname:sea_water_practical_salinityUnits:psuu(float)Standardname:eastward_sea_water_velocityUnits:m/sv(float)Standardname:northward_sea_water_velocityUnits:m/sw_velocity(float)Standardname:upward_sea_water_velocityUnits:m/sYou can query the dimensions information.>>>print(remote.dimensions)<erddapClient.ERDDAP_Griddap_dimensions>Dimensions:-time(nValues=1977)1238630400..1409356800-depth(nValues=40)0.0..5500.0-latitude(nValues=385)18.091648..31.960648-longitude(nValues=541)-98.0..-76.400024>>>print(remote.dimensions['time'])<erddapClient.ERDDAP_Griddap_dimension>Dimension:time_nValues:1977_evenlySpaced:True_averageSpacing:1day_dataType:double_CoordinateAxisType:Timeactual_range:(cftime.DatetimeGregorian(2009,4,2,0,0,0,0),cftime.DatetimeGregorian(2014,8,30,0,0,0,0))axis:Tcalendar:standardioos_category:Timelong_name:Timestandard_name:timetime_origin:01-JAN-197000:00:00units:secondssince1970-01-01T00:00:00ZGriddap data request in a xarray.DataArrayRequest a data subset and store it in a fully described xarray.DataArray object.>>>xSubset=(remote.setResultVariables('temperature')..:.setSubset(time="2012-01-13",..:depth=slice(0,2000),..:latitude=slice(18.09165,31.96065),..:longitude=slice(-98.0,-76.40002))..:.getxArray())>>>xSubset<xarray.Dataset>Dimensions:(depth:33,latitude:385,longitude:541,time:1)Coordinates:*time(time)object2012-01-1300:00:00*depth(depth)float640.05.010.015.0...1.5e+031.75e+032e+03*latitude(latitude)float6418.0918.1318.17...31.8931.9331.96*longitude(longitude)float64-98.0-97.96-97.92...-76.48-76.44-76.4Datavariables:temperature(time,depth,latitude,longitude)float32...Attributes:(12/32)cdm_data_type:GridConventions:COARDS,CF-1.0,ACDD-1.3creator_email:hycomdata@coaps.fsu.educreator_name:NavalResearchLaboratorycreator_type:institutioncreator_url:https://www.hycom.org......standard_name_vocabulary:CFStandardNameTablev70summary:NRLHYCOM1/25degmodeloutput,GulfofMexi...time_coverage_end:2014-08-30T00:00:00Ztime_coverage_start:2009-04-02T00:00:00Ztitle:NRLHYCOM1/25degmodeloutput,GulfofMexi...Westernmost_Easting:-98.0The above data request can also be done using the ERDDAP opendap extended query format, by example :>>>xSubset=(remote.setResultVariables('temperature[(2012-01-13)][(0):(2000)][(18.09165):(31.96065)][(-98.0):(-76.40002)]')..:.getxArray()Make request for subsets in different formats.>>># Request a location subset in a pandas dataframe>>>>>>remote.clearQuery()>>>dfSubset=(remote.setResultVariables(['temperature','salinity'])..:.setSubset(time=slice("2009-04-02","2014-8-30"),..:depth=0,..:latitude=22.5,..:longitude=-95.5)..:.getDataFrame(header=0,..:names=['time','depth','latitude','longitude','temperature','salinity'],..:parse_dates=['time'],..:index_col='time'))>>>dfSubsetdepthlatitudelongitudetemperaturesalinitytime2009-04-0200:00:00+00:000.022.51696-95.4799824.80179836.1670762009-04-0300:00:00+00:000.022.51696-95.4799824.60557036.2564502009-04-0400:00:00+00:000.022.51696-95.4799824.47788436.0863462009-04-0500:00:00+00:000.022.51696-95.4799824.55235736.1332242009-04-0600:00:00+00:000.022.51696-95.4799825.76194636.179676..................2014-08-2600:00:00+00:000.022.51696-95.4799830.27754636.4400372014-08-2700:00:00+00:000.022.51696-95.4799830.25890736.4858442014-08-2800:00:00+00:000.022.51696-95.4799830.29859736.5075302014-08-2900:00:00+00:000.022.51696-95.4799830.24687436.4934002014-08-3000:00:00+00:000.022.51696-95.4799830.38784036.487934[1977rowsx5columns]>>>Sample notebooksCheck the demostrationnotebooks folderfor more advanced usage of the library classes.