Binder

HS RDF HydroShare Python Client Resource Metadata Editing Examples


The following code snippets show examples for how to use the HS RDF HydroShare Python Client for creating and editing resource level metadata for a HydroShare resource.

Install the HS RDF HydroShare Python Client

The HS RDF Python Client for HydroShare won't be installed by default, so it has to be installed first before you can work with it. Use the following command to install the Python Client from the GitHub repository. Eventually we will distribute this package via the Python Package Index (PyPi) so that it can be installed via pip from PyPi.

!pip install hsclient

Authenticate with HydroShare

Before you start interacting with resources in HydroShare you will need to authenticate.

from hsclient import HydroShare

hs = HydroShare()
hs.sign_in()

Create a New Empty Resource

A "resource" is a container for your content in HydroShare. Think of it as a "working directory" into which you are going to organize the code and/or data you are using and want to share. The following code can be used to create a new, empty resource within which you can create content and metadata.

This code creates a new resource in HydroShare. It also creates an in-memory object representation of that resource in your local environmment that you can then manipulate with further code.

# Create the new, empty resource
new_resource = hs.create()

# Get the HydroShare identifier for the new resource
resIdentifier = new_resource.resource_id
print('The HydroShare Identifier for your new resource is: ' + resIdentifier)

# Construct a hyperlink for the new resource
print('Your new resource is available at: ' +  new_resource.metadata.url)

Creating and Editing Resource Metadata Elements

Editing metadata elements for a resource can be done in an object oriented way. You can specify all of the metadata elements in code, which will set their values in memory in your local environment. Values of metadata elements can be edited, removed, or replaced by setting them to a new value, appending new values (in the case where the metadata element accepts a list), or by removing the value entirely.

When you are ready to save edits to metadata elements from your local environment to the resource in HydroShare, you can call the save() function on your resource and all of the new metadata values you created/edited will be saved to the resource in HydroShare.

Resource Title and Abstract

The Title and Abstract metadata elements can be specified as text strings. To modify the Title or Abstract after it has been set, just set them to a different value.

# Set the Title for the resource
new_resource.metadata.title = 'Resource for Testing the HS RDF HydroShare Python Client'

# Set the Abstract text for the resource
new_resource.metadata.abstract = (
    'This resource was created as a demonstration of using the HS RDF ' 
    'Python Client for HydroShare. Once you have completed all of the '
    'steps in this notebook, you will have a fully populated HydroShare '
    'Resource.'
)

# Call the save function to save the metadata edits to HydroShare
new_resource.save()

# Print the title just added to the resource
print('Title: ' + new_resource.metadata.title)
print('Abstract: ' + new_resource.metadata.abstract)

Subject Keywords

Subject keywords can be specified as a Python list of strings. Keywords can be added by creating a list, appending new keywords to the existing list, or by overriding the existing list with a new one.

# Create subject keywords for the resource using a list of strings
new_resource.metadata.subjects = ['HS RDF', 'Python', 'HydroShare', 'Another Keyword']

# New keywords can be appended to the existing list
new_resource.metadata.subjects.append('Hydroinformatics')

# Keywords can be removed by removing them from the list
new_resource.metadata.subjects.remove('Another Keyword')

# Save the changes to the resource in HydroShare
new_resource.save()

# Print the keywords for the resource
print('The list of keywords for the resource includes:')
for keyword in new_resource.metadata.subjects:
  print(keyword)

Spatial and Temporal Coverage

Initially the spatial and temporal coverage for a resource are empty. To set them, you have to create a coverage object of the right type and set the spatial or temporal coverage to that object.

# Import the required metadata classes for coverage objects
from hsmodels.schemas.fields import BoxCoverage, PointCoverage, PeriodCoverage
from datetime import datetime

# Set the spatial coverage to a BoxCoverage object
new_resource.metadata.spatial_coverage = BoxCoverage(name='Logan, Utah',
                                                     northlimit=41.7910,
                                                     eastlimit=-111.7664,
                                                     southlimit=41.6732,
                                                     westlimit=-111.9079,
                                                     projection='WGS 84 EPSG:4326',
                                                     type='box',
                                                     units='Decimal degrees')

# You can remove the spatial coverage element by setting it to None
new_resource.metadata.spatial_coverage = None

# If you want to set the spatial coverage to a PointCoverage instead
new_resource.metadata.spatial_coverage = PointCoverage(name='Logan, Utah',
                                                       north=41.7371,
                                                       east=-111.8351,
                                                       projection='WGS 84 EPSG:4326',
                                                       type='point',
                                                       units='Decimal degrees')

# Create a beginning and ending date for a time period
beginDate = datetime.strptime('2020-12-01T00:00:00Z', '%Y-%m-%dT%H:%M:%S%fZ')
endDate = datetime.strptime('2020-12-31T00:00:00Z', '%Y-%m-%dT%H:%M:%S%fZ')

# Set the temporal coverage of the resource to a PeriodCoverage object
new_resource.metadata.period_coverage = PeriodCoverage(start=beginDate,
                                                       end=endDate)

# Save the changes to the resource in HydroShare
new_resource.save()

# Print the temporal coverage information
print('Temporal Coverage')
print(new_resource.metadata.period_coverage)

# Print the spatial coverage information
print('\nSpatial Coverage')
print(new_resource.metadata.spatial_coverage)

Additional/Extended Metadata

HydroShare allows you to create new, extended metadata elements for a HydroShare resource as key-value pairs. You can add new elements, edit existing elements, or remove these elements. Extended metadata elements are stored in the resource as a Python dictionary.

# Add an extended metadata element as a key-value pair
new_resource.metadata.additional_metadata['New Element Key'] = 'Text value of new element key.'

# Remove an individual key-value pair using its key
del new_resource.metadata.additional_metadata['New Element Key']

# Or, you can clear out all of the additional metadata elements that might exist
new_resource.metadata.additional_metadata.clear()

# Add multiple key-value pairs at once using a Python dictionary
new_resource.metadata.additional_metadata = {
    'Observed Variable': 'Oxygen, dissolved',
    'Site Location': 'Located on downstream side of river bridge',
    'Observation Depth': '1 meter'
}

# Save the changes to the resource in HydroShare
new_resource.save()

# Print the extended metadata elements for the resource
print('The extended metadata elements for the resource include:')
for key, value in new_resource.metadata.additional_metadata.items():
    print (key + ':', value)

Sources

Sources are stored as a list of strings. Sources can be added or removed by adding or removing source strings from the list.

# If you have existing Sources in your resource, you can remove all of them
# by clearing the local list and then saving the resource 
new_resource.metadata.sources.clear()
new_resource.save()

# Add a Source to the resource
sourceString = (
    'Mihalevich, B. A., Horsburgh, J. S., Melcher, A. A. (2017). High-frequency '
    'measurements reveal spatial and temporal patterns of dissolved organic '
    'matter in an urban water conveyance, Environmental Monitoring and '
    'Assessment, http://dx.doi.org/10.1007/s10661-017-6310-y.'
)
new_resource.metadata.sources.append(sourceString)

# Save the changes to the resource in HydroShare
new_resource.save()

# Print the Source metadata
print('The list of Sources includes:')
for source in new_resource.metadata.sources:
  print(source)

Related Resources are specified using a string that encodes the citation for the Related Resource along with a relationship type. Because of this, Related Resources are stored as a list of Relation objects. To create a new Related Resource, you have to first instantiate a Relation object and then add it to the list of Related Resources.

# Import the required metadata class for a Relation object
from hsmodels.schemas.fields import Relation
from hsmodels.schemas.enums import RelationType

# If you have existing Related Resources, you can remove all of them
# by clearing the local list and then saving the resource
new_resource.metadata.relations.clear()
new_resource.save()

# Create a new relation object
newRelation = Relation(type=RelationType.isDataFor, 
                       value=('Bastidas Pacheco, C. J., Horsburgh, J. S., Tracy, ' 
                              'R. J. (2020). A low-cost, open source monitoring ' 
                              'system for collecting high-resolution water use '
                              'data on magnetically-driven residential water ' 
                              'meters, Sensors, 20(13), 3655, '
                              'https://doi.org/10.3390/s20133655.'))

# Append the new Related Resource to the list of Related Resources
new_resource.metadata.relations.append(newRelation)

# Save the changes to the resource in HydroShare
new_resource.save()

# Print the list of Related Resources
print('The list of Related Resources includes:')
for relatedResource in new_resource.metadata.relations:
  print(relatedResource.type.value + ': ' + relatedResource.value)

Funding Agency Credits

Funding agency information contains multiple attributes when you add a funding agency to a HydroShare resource. You can create multiple funding agency entries for a resource, which get stored as a Python list.

# Import the required metadata class for an AwardInfo object
from hsmodels.schemas.fields import AwardInfo

# If you have existing funding agency information, you can remove all of them
# by clearing the local list and then saving the resource
new_resource.metadata.awards.clear()
new_resource.save()

# Create a new AwardInfo object
newAwardInfo = AwardInfo(funding_agency_name='National Science Foundation',
                         title=('Collaborative Research: Elements: Advancing Data Science ' 
                                'and Analytics for Water (DSAW)'),
                         number='OAC 1931297',
                         funding_agency_url='https://www.nsf.gov/awardsearch/showAward?AWD_ID=1931297')

# Append the new AwardInfo object to the list of funding agencies
new_resource.metadata.awards.append(newAwardInfo)

# Save the changes to the resource in HydroShare
new_resource.save()

# Print the AwardInfo
print('Funding sources added: ')
for award in new_resource.metadata.awards:
  print('Award Title: ' + award.title)

Authors

In HydroShare, an "Author" is the same as the Dublin Core metadata "Creator" element. The Creator element is a list of creators for the resource. However, the order of the Creators matters. When setting Creator information for the resource, you need to edit the local list of creators so that it reflects the order you want. When you call the save() function on the resource, the Creator information in HydroShare will be updated to match what you set locally. To add a new Creator to the list of Creators, you must first instantiate a Creator object and then add it to the list of Creators for the resource. Creator objects can be created by supplying all of the Creator metadata or by copying from a HydroShare user's profile.

# Import the required metadata class for a Creator object
from hsmodels.schemas.fields import Creator

# Instantiate a new Creator object for a Creator that is a HydroShare user
newCreator1 = Creator(name='Jones, Amber Spackman',
                      organization='Utah State University',
                      email='amber.jones@usu.edu',
                      description='/user/510/')

# Append the new Creator to the resource's list of Creators
new_resource.metadata.creators.append(newCreator1)

# Instantiate a new Creator object for a Creator that is not a HydroShare user
newCreator2 = Creator(name='Doe, John A.',
                     organization='Utah Water Research Laboratory',
                     email='john.doe@usu.edu',
                     address='8200 Old Main Hill, Logan, UT 84322-8200',
                     phone='123-456-7890')

# Append the new Creator to the resource's list of Creators
new_resource.metadata.creators.append(newCreator2)

# Instantiate a new Creator object for a Creator that is an organization
newCreator3 = Creator(organization='Utah Water Research Laboratory',
                      email='uwrl.receptionist@usu.edu',
                      address='8200 Old Main Hill, Logan, UT 84322-8200',
                      homepage='http://uwrl.usu.edu',
                      phone='435-797-3168 ')

# Append the new Creator to the resource's list of Creators
new_resource.metadata.creators.append(newCreator3)

# Instantiate a new Creator object using a HydroShare user object
# First, retrieve HydroShare user object
tony = hs.user(11)

# Generate a Creator object from a HydroShare user object and append
# the new Creator to the resource's list of Creators
newCreator4 = Creator.from_user(tony)
new_resource.metadata.creators.append(newCreator4)

# Save the changes to the resource in HydroShare
new_resource.save()

# Print the Creator names
print('The list of Creators includes: ')
for creator in new_resource.metadata.creators:
  if creator.name is None:
    print(creator.organization)
  else:
    print(creator.name)

The previous step leaves the resource with a list of 5 Creators. The order in which Creators appear in the metadata and on the Resource Landing Page is controlled by the order in which they appear in the the Creator list. To update the Creator order, update the order of the Creator list and then save the resource.

# Change the order of the Creators in the list
creatorOrder = [3, 2, 0, 1, 4]
new_resource.metadata.creators = [new_resource.metadata.creators[i] for i in creatorOrder]

# Save the changes to the resource in HydroShare
new_resource.save()

# Print the modified order of the Creator names
print('The list of Creators includes: ')
for creator in new_resource.metadata.creators:
  if creator.name is None:
    print(creator.organization)
  else:
    print(creator.name)

Creators can be removed by removing them from the local list of creators and then calling the save() function on the resource. Note that there must always be at least one creator.

# Example of removing all but the first creator
del new_resource.metadata.creators[1:]
new_resource.save()

print('Number of remaining creators: ' + str(len(new_resource.metadata.creators)))

Contributors

Contributors can be existing HydroShare users or others who do not have HydroShare accounts. Creating and removing contributors is similar to how Creators are handled. Contributors do not have a designated order.

# Import the required metadata class for a Contributor object
from hsmodels.schemas.fields import Contributor

# Instantiate a new Contributor object for a Contributor that is not a HydroShare user
newContributor1 = Contributor(name='Horsburgh, Jeffery S.',
                              organization='Utah State University',
                              email='jeff.horsburgh@usu.edu',
                              phone='(435) 797-2946',
                              ORCID='https://orcid.org/0000-0002-0768-3196',
                              address='Utah, US',
                              google_scholar_id='https://scholar.google.com/citations?user=mu4k534AAAAJ&hl=en',
                              homepage='http://jeffh.usu.edu',
                              research_gate_id='https://www.researchgate.net/profile/Jeffery_Horsburgh')

# Append the new Contributor to the resource's list of Contributors
new_resource.metadata.contributors.append(newContributor1)

# Instantiate a new Contributor object for a Contributor that is not a HydroShare user
# Not all of the available metadata for a contributor have to be filled out
newContributor2 = Contributor(name='Doe, John A.',
                              organization='Utah State University',
                              email='john.doe@usu.edu')

# Append the new Contributor to the resource's list of Contributors
new_resource.metadata.contributors.append(newContributor2)

# Instantiate a new Contributor object using a HydroShare user object
# First, retrieve HydroShare user object
tony = hs.user(11)

# Generate a Contributor object from the HydroShare user object
newContributor3 = Contributor.from_user(tony)
new_resource.metadata.contributors.append(newContributor3)

# Save the changes to the resource in HydroShare
new_resource.save()

# Print the Contributor names
print('The list of Contributors includes: ')
for Contributor in new_resource.metadata.contributors:
  print(Contributor.name)

Similar to other elements, if you want to remove Contributors, you can modify the local list of Creators and then call the save() function on the resource to save the changes in HydroShare.

# Clear the list of Contributors and save to HydroShare
new_resource.metadata.contributors.clear()
new_resource.save()

print('Number of remaining Contributors: ' + str(len(new_resource.metadata.contributors)))

License and Rights Statement

The license under which a Resource is shared can be modified. HydroShare defaults to one of the Creative Commons licenses, but you can change it to a license that meets your needs. The license consists of a rights statement stored as as string and a URL that is a link to a description of the license on the Internet.

# Import the required metadata class for a Rights object
from hsmodels.schemas.fields import Rights

# Set the rights statement and the URL that points to its description
new_resource.metadata.rights.statement = (
    'This resource is shared under the Creative Commons '
    'Attribution-NoCommercial-NoDerivs CC BY-NC-ND.'
)
new_resource.metadata.rights.url = 'http://creativecommons.org/licenses/by-nc-nd/4.0/'

# Save the changes to the resource in HydroShare
new_resource.save()

# Print the rights statement:
print(new_resource.metadata.rights.statement)
print(new_resource.metadata.rights.url)

# You can also use one of the available, pre-generated Rights Statements 
# available in HydroShare
new_resource.metadata.rights = Rights.Creative_Commons_Attribution_CC_BY()
new_resource.save()

# Print the rights statement:
print(new_resource.metadata.rights.statement)
print(new_resource.metadata.rights.url)