Getting Started

Installation

pip install pyskywise

If the package is not located, ensure that you have WDT’s PyPi server in your pip.conf.


Configuration

To make calls to a SkyWise API, you must first point your resource to your API and configure authentication:

from skywise.platform import PlatformResource

# Initialize Endpoints
PlatformResource.set_site("http://base.platform.url")
PlatformResource.set_user("3ScaleUsername")
PlatformResource.set_password("3ScalePassword")

For convenience, each SkyWise API package will attempt to initialize itself using its corresponding environment variables to eliminate the need for configuration in your application. Here’s an example from Platform:

#!/bin/bash
export PSW_PLATFORM_SITE="http://base.platform.url"
export PSW_PLATFORM_USER="3ScaleUsername"
export PSW_PLATFORM_PASSWORD="3ScalePassword"

See each API’s documentation for reference to these variables, but they should follow the convention of PSW_{API_NAME}_{FIELD}.

The rest of the documentation will proceed assuming that these variables have been set and that further endpoint configuration is not needed.


Basic Usage

Each API in PySkyWise follows a pattern for searching for its resources: the find() method. Think of each resource class’ find() method as a resource factory.

Requesting Resources

Request All Resources

To find all of a given resource, just call the find() method without any parameters.

from skywise.platform import Product

products = Product.find()
# [<Product 'skywise-1hr-precipitation-analysis'>, <Product ...>, ...]

Request A Single Resource by ID

To find a single resource, simply pass its ID as the first and only parameter.

precip_product = Product.find('skywise-1hr-precipitation-analysis')
# <Product 'skywise-1hr-precipitation-analysis'>

Request Resources w/ Parameters

Many endpoints allow optional parameters. Simply add the parameter as a keyword argument in the find method. All resource classes should allow the developer to pass in commonly used python data types and objects as parameters, eliminating the need to pass in strings formatted for a request URL. Here, we’ll query hourly precip frames for the past day.

import arrow
from skywise.platform import ProductFrame

start = arrow.get().replace(days=-1).datetime
end = arrow.get().datetime
frames = ProductFrame.find(product_id=precip_product.id, start=start, end=end)

The ProductFrame resource handles all of the start/end datetime request url serialization behind the scenes, so that you don’t have to. But this still looks a bit tedious, since we have to import Frame and call Frame.find() directly. Instead, we could have used a Product convenience method for accessing its frames:

frames = precip_product.get_frames(start=start, end=end)

Convenience methods that simplify the interface to other resources are a common pattern in PySkyWise.

Asynchronous Requests

Using the find_async() method along with map() on your resource allows for multiple requests to be called asynchronously. In Platform, for example, this is useful for datapoint or map tile requests for a large number of frames. Here is a trivial example using products.

product_ids = ['skywise-24hr-precipitation-analysis',
               'skywise-1hr-precipitation-analysis',
               'weatherops-24hr-precipitation-forecast',
               'weatherops-1hr-precipitation-forecast']

# Prep Requests
skywise_requests = [Product.find_async(id) for id in product_ids]

# Call Asynchronously
products = Product.map(skywise_requests)

Grouping Resources

Any list of resources returned by our find() or map() methods will have a group() method. Using this method, we can group by data attributes on our resources. Here’s an example that groups all of our Platform products by their source and content type:

from skywise.platform import Product

products = Product.find()
products.group(['source', 'contentType'])
"""
{
  'wdssii': {
          'precipitation': [<Product skywise-1hr-precipitation-analysis>,
                            <Product skywise-1hr-precipitation-forecast>,
                            <Product skywise-24hr-precipitation-analysis>,
                            <Product skywise-24hr-precipitation-forecast]
  },
  'wrf': {
          'solar-radiation': [<Product skywise-1hr-solar-radiation-analysis>,
                              <Product skywise-1hr-solar-radiation-forecast>,
                              <Product skywise-24hr-solar-radiation-analysis>,
                              <Product skywise-24hr-solar-radiation-forecast>]
  }
  ...
}
"""

group() accepts a list of attribute accessor strings. You can string attributes together using dot notation: [‘foo.bar’, ‘baz’].


Creating Resources

Basic functionality has been added that allows you to create resources for your SkyWise API’s. The process for this will be described more fully in the future in a Creating Custom Resources section.

import geojson
from skywise.agriculture import Field

field = Field()
field.description = 'Arthur Farm'
field.add_geometry(MultiPolygon([
   ([(-97.194156646728, 35.667442627764),
   (-97.191281318664, 35.668349114403),
   (-97.185573577880, 35.672497902647),
   (-97.185616493225, 35.676402447539),
   (-97.194499969482, 35.671591463121),
   (-97.194156646728, 35.667442627764)])
]))
field.save()
assert field.id is not None

Updating a resource is just as easy.

field.description = 'Arthur NW Field'
field.save()

# Requesting a fresh version of the field verifies that it's been updated
fresh_field = Field.find(field.id)
assert field.id == fresh_field.id
assert field.description == fresh_field.description

Exception Handling

Exception handling is still poorly implemented, but all calls that result in a request response of a non 20X value will raise an exception. Future work needs to be done especially to give the developer better feedback for improper parameter passing.