In [1]:
import requests
import json
import os
from time import sleep

In [266]:
# Good to know..
# Status Description
# 200 “OK”: nonspecific success
# 201 “Created”: successful resource creation
# 202 “Accepted”: successful start of an asynchronous action
# 204 “No Content”: success without any content
# 400 “Bad Request”: nonspecific failure
# 401 “Unauthorized”: failed authentication or authorization
# 404 “Not Found”: resource not found at the target URI
# 500 “Internal Server Error”: API malfunction

Credentials


In [2]:
#myIbmId = 'ips.app@outlook.com'
#myIbmIdPassword = 'ips.app1'
#myClientId = '5c20d153-09ad-40e3-9387-124cd132bc42'
#myClientSecret = 'R8qP7dF2kH4fH4iH3lH2iJ7uD3yI2fQ5oY0cH8pE2kY3eN0cJ8'

myIbmId = 'tsarouch@gmail.com'
myIbmIdPassword = 'Eat2@pples'
myClientId = '28701078-8029-4da5-a335-763d0b05951f'
myClientSecret = 'tY2pF6qW6fG2hC2qD3jQ3rF1gR8oF2yQ6cF0sM4yU1yH7kV0lH'

In [3]:
apiBase = 'https://' + myIbmId + ':' + myIbmIdPassword + '@api.ibm.com/pairs/run/v1/'
apiHeaders = {
    'Content-Type': 'application/json', # Required for POST and PUT operations
    'x-ibm-client-id': myClientId,
    'x-ibm-client-secret': myClientSecret
}

Check connection


In [4]:
# The "noop" operation is useful for checking API invocation credentials, gathering performance measures, monitoring API service availability, etc.
apiName = 'noop'
response = requests.get((apiBase + apiName), headers=apiHeaders)
print('HTTP status code: ' + str(response.status_code))
if (response.status_code != 204):
    print(response.json())


HTTP status code: 204

Delete a past query if needed


In [284]:
queryId = '41f3afebb1799875da9ba07a3d5d840a'
apiName = 'queries' + '/' + queryId
response = requests.delete((apiBase + apiName), headers=apiHeaders)
print('HTTP status code: ' + str(response.status_code))
if (response.status_code != 204):
    print(response.json())


HTTP status code: 204

Submit a query


In [555]:
df_geocodes = pd.read_csv('/Users/charilaostsarouchas/Downloads/extended.csv')
df_geocodes = df_geocodes.sample(frac=1)
df_geocodes['lat'] = df_geocodes['lat'].astype('str')
df_geocodes['long'] = df_geocodes['lon'].astype('str')
points_examples = df_geocodes[['lat', 'long']].drop_duplicates()[:10].to_dict('records')

In [568]:
points_examples


Out[568]:
[{'lat': '39.6247215271', 'long': '-0.595210015774'},
 {'lat': '42.3436415', 'long': '-7.8674242'},
 {'lat': '37.2575874', 'long': '-6.9484945'},
 {'lat': '42.035291', 'long': '0.1273884'},
 {'lat': '37.2961366', 'long': '-1.8807223'},
 {'lat': '39.42333775', 'long': '-0.478919564333'},
 {'lat': '38.353738', 'long': '-0.4901846'},
 {'lat': '41.4963684082', 'long': '2.16325998306'},
 {'lat': '37.8706817627', 'long': '-4.77859020233'},
 {'lat': '41.620353', 'long': '2.6017906'}]

In [586]:
apiName = 'queries'
apiBody = {
    "name": "point query",
    "spatial" : {
        "type" : "point",
        "point" : [{"lat" : "39.6247215271", "long" : "-0.595210015774"},
                   {"lat": '42.3436415', 'long': '-7.8674242'},
                   {'lat': '37.2575874', 'long': '-6.9484945'}]  
    },
    "datalayer" : [
        {"id" : "25001",
         "temporal": [["2016-02-01", "2016-03-01"]]
        }
    ]
}
query_response = requests.post((apiBase + apiName), headers=apiHeaders, data=json.dumps(apiBody))
print "the query id is: ", query_response.json()['query'][0]['id']


the query id is:  19bcb15f0cb2004b6ef3422693b480d9

Check the query and job status


In [588]:
# query
query_id = query_response.json()['query'][0]['id']
print "Query ID: ", query_id
apiName = 'queries' + '/' + query_id + "?done=true"
query_response = requests.get((apiBase + apiName), headers=apiHeaders)
print "Query Status Response: ", query_response.status_code


# job
job_id = query_response.json()['query'][0]['job']['id']
print "Job ID: ", job_id
apiName = 'jobs' + '/' + job_id
job_response = requests.get((apiBase + apiName), headers=apiHeaders)
print "Job Status Response: ", job_response.status_code


Query ID:  19bcb15f0cb2004b6ef3422693b480d9
Query Status Response:  200
Job ID:  7ac58840852a06af32be94fe3b88271a
Job Status Response:  200

In [589]:
query_id = query_response.json()['query'][0]['id']
print query_id

apiName = 'queries' + '/' + query_id + "?done=true"
response = requests.get((apiBase + apiName), headers=apiHeaders)

print  "Query status: ", response.status_code

result = None
if response.status_code == 200:
    response = requests.get((apiBase + apiName), headers=apiHeaders)

    print  "Query - Job status: ", response.json()['query'][0]['job']['status']
    if response.json()['query'][0]['job']['status'] == '201':
        downloadUrl = response.json()['query'][0]['result']['refs'][0]['url']
        result = requests.get(downloadUrl)


19bcb15f0cb2004b6ef3422693b480d9
Query status:  200
Query - Job status:  201

In [590]:
print "N datapoints: ", len(json.loads(result.content)['data'])


N datapoints:  116

Retrieve data to DataFrame


In [591]:
import datetime
import pandas as pd
data = []
for i in range(len(json.loads(result.content)['data'])):
    ts = json.loads(result.content)['data'][i]['timestamp']
    dt = datetime.datetime.fromtimestamp(int(ts/1000)).strftime('%Y-%m-%d %H:%M:%S')
    date = dt[:10]
    temp_K = json.loads(result.content)['data'][i]['value']
    temp_C = temp_K -273.15
    lat = json.loads(result.content)['data'][i]['lat']
    lon = json.loads(result.content)['data'][i]['lon']
    data.append([lat, lon, ts, dt, date, temp_C])
df = pd.DataFrame(data=data, columns = ['lat', 'lon', 'timestamp', 'datetime', 'date', 'temperature'])

In [592]:
df.head()


Out[592]:
lat lon timestamp datetime date temperature
0 39.624722 -0.59521 1456790400000 2016-03-01 01:00:00 2016-03-01 5.074487
1 39.624722 -0.59521 1456768800000 2016-02-29 19:00:00 2016-02-29 7.257257
2 39.624722 -0.59521 1456747200000 2016-02-29 13:00:00 2016-02-29 8.097009
3 39.624722 -0.59521 1456725600000 2016-02-29 07:00:00 2016-02-29 4.240259
4 39.624722 -0.59521 1456704000000 2016-02-29 01:00:00 2016-02-29 5.112756

Visualize


In [593]:
import os
import numpy as np
import folium
from folium.plugins import HeatMap

In [594]:
df.groupby(['lat','lon'])['temperature'].agg('sum')


Out[594]:
lat        lon     
39.624722  -0.59521    999.962396
Name: temperature, dtype: float64

In [595]:
m = folium.Map([48., 5.], tiles='stamentoner', zoom_start=7)
data = df[['lat', 'lon', 'temperature']].values.tolist()
HeatMap(data).add_to(m)
m.save(os.path.join('/Users/charilaostsarouchas/Downloads/', 'Heatmap.html'))
m


Out[595]:

In [531]:
import folium
import folium.plugins as plugins
import numpy as np

np.random.seed(3141592)
initial_data = (
    np.random.normal(size=(100, 2)) * np.array([[1, 1]]) +
    np.array([[48, 5]])
)

move_data = np.random.normal(size=(100, 2)) * 0.01

data = [(initial_data + move_data * i).tolist() for i in range(100)]

In [ ]:
df.groupby('')

In [538]:
data = df.sort_values(by='timestamp')[['lat', 'lon', 'temperature']].values.tolist()
m = folium.Map([48., 5.], tiles='stamentoner', zoom_start=6)
hm = plugins.HeatMapWithTime(data)
hm.add_to(m)
m


Out[538]:

In [ ]:


In [ ]:


In [ ]:
# curl \
#   -X POST "https://ibmpairs-mvp2-api.mybluemix.net/queryjobs?spatialLimitsType=area" \
#   -H "Content-Type: application/json" \
#   -H "X-Access-Token: 4usk9y29lzsj2vuwb0rwvad1rg9ogdmbijcp4b6a" \
#   -d '{"name":"Agriculture in Midwestern U.S.","description":"We compare the US Department of Agriculture's crop data with PRISM (historical weather observation in USA) temperature data during the beginning of June 2017. Since the crop data is associated with January 1st, the query uses different temporal intervals for each layer.","isPublic":true,"layers":[{"dataLayerId":"48522","startingDateTime":"2017-01-01T00:00:00.000Z","endingDateTime":"2017-01-01T00:00:00.000Z","aggregationOperator":"None","dimensions":[]},{"dataLayerId":"92","startingDateTime":"2017-06-01T00:00:00.000Z","endingDateTime":"2017-06-07T00:00:00.000Z","aggregationOperator":"None","dimensions":[]}],"filters":[],"space":{"northEastCoordinate":{"latitude":42.391008609205045,"longitude":-88.83544921875},"southWestCoordinate":{"latitude":36.13787471840729,"longitude":-100.61279296875}}}'
                                
# curl "https://ibmpairs-mvp2-api.mybluemix.net/queryjobs/00000000-2137-8c84-0000-00002155c70a" \
#   -H "X-Access-Token: 4usk9y29lzsj2vuwb0rwvad1rg9ogdmbijcp4b6a"

In [55]:
import os
cmd = 'curl "https://ibmpairs-mvp2-api.mybluemix.net/queryjobs/00000000-0cd6-1fa3-0000-000002f71050" -H "X-Access-Token: 4usk9y29lzsj2vuwb0rwvad1rg9ogdmbijcp4b6a"'
result = os.popen(cmd).read()

# move str result to dictionary
d = json.loads(result)

In [56]:
# move d to json
print(json.dumps(d, indent=2))


{
  "status": "success", 
  "visualization": {
    "displayedBoundingBox": {
      "northEastCoordinate": {
        "latitude": 71.254509, 
        "longitude": 33.1398048
      }, 
      "southWestCoordinate": {
        "latitude": 33.0167274, 
        "longitude": -11.8601971
      }
    }, 
    "layers": [
      {
        "endingDateTime": "2015-01-01T00:00:00.084Z", 
        "aggregationOperator": "None", 
        "dataLayer": {
          "description": null, 
          "timeRange": {
            "startingDateTime": "2000-01-01T00:00:01.000Z", 
            "endingDateTime": "2015-01-01T00:00:01.000Z"
          }, 
          "boundingBox": {
            "northEastCoordinate": {
              "latitude": 83.80147199999999, 
              "longitude": 180.185856
            }, 
            "southWestCoordinate": {
              "latitude": -56.183424, 
              "longitude": -180.0
            }
          }, 
          "units": "humans/km^2", 
          "dimensions": [], 
          "type": "RASTER", 
          "id": "48774", 
          "dataSetId": "106", 
          "name": "Global Population Density"
        }, 
        "displayUnits": "humans/km^2", 
        "wms": {
          "filter": "", 
          "legendStyledLayerDescriptor": "https://pairs.res.ibm.com:443/map/sld?type=raster&min=0.000000&max=250.000000&colorTableId=4&property=value&layer=pairs:1520182800_21381516GlobalPopulation-GlobalPopulationDensity-01_01_2015T000000", 
          "styledLayerDescriptor": "https://pairs.res.ibm.com:443/map/sld?type=raster&min=0.000000&max=250.000000&colorTableId=4&no_data=-1&property=value&layer=pairs:1520182800_21381516GlobalPopulation-GlobalPopulationDensity-01_01_2015T000000", 
          "geoserverUrl": "https://pairs.res.ibm.com:8443/geoserver/wms", 
          "name": "1520182800_21381516GlobalPopulation-GlobalPopulationDensity-01_01_2015T000000"
        }, 
        "startingDateTime": "2015-01-01T00:00:00.084Z", 
        "id": "2029537337", 
        "dimensions": []
      }
    ], 
    "timeRange": {
      "startingDateTime": "2015-01-01T00:00:00.000Z", 
      "endingDateTime": "2015-01-01T00:00:00.000Z"
    }
  }, 
  "isSampleQueryJob": true, 
  "queuePosition": 0, 
  "statusDescription": "Success", 
  "notebook": null, 
  "progress": 100, 
  "query": {
    "layers": [
      {
        "startingDateTime": "2015-01-01T00:00:00.000Z", 
        "dataLayerId": "48774", 
        "endingDateTime": "2015-01-01T00:00:00.000Z", 
        "aggregationOperator": "None", 
        "dimensions": []
      }
    ], 
    "name": "Population Density of Europe", 
    "space": {
      "northEastCoordinate": {
        "latitude": 71.25450934954355, 
        "longitude": 33.139802999999986
      }, 
      "southWestCoordinate": {
        "latitude": 33.016726206498475, 
        "longitude": -11.860197000000005
      }
    }, 
    "isPublic": true, 
    "filters": [], 
    "description": "The query shows the population density of Europe. Using the settings menu to change the color scale leads to a better graphical representation of areas with low or high population respectively."
  }, 
  "ownerId": null, 
  "queueSize": 1, 
  "creationDateTime": "2018-03-04T22:48:55.926Z", 
  "id": "00000000-0cd6-1fa3-0000-000002f71050", 
  "downloadUri": null
}

In [57]:
print [str(i) for i in d.keys()]


['status', 'visualization', 'isSampleQueryJob', 'queuePosition', 'statusDescription', 'notebook', 'progress', 'query', 'ownerId', 'queueSize', 'creationDateTime', 'id', 'downloadUri']

In [61]:
d['query']


Out[61]:
{u'description': u'The query shows the population density of Europe. Using the settings menu to change the color scale leads to a better graphical representation of areas with low or high population respectively.',
 u'filters': [],
 u'isPublic': True,
 u'layers': [{u'aggregationOperator': u'None',
   u'dataLayerId': u'48774',
   u'dimensions': [],
   u'endingDateTime': u'2015-01-01T00:00:00.000Z',
   u'startingDateTime': u'2015-01-01T00:00:00.000Z'}],
 u'name': u'Population Density of Europe',
 u'space': {u'northEastCoordinate': {u'latitude': 71.25450934954355,
   u'longitude': 33.139802999999986},
  u'southWestCoordinate': {u'latitude': 33.016726206498475,
   u'longitude': -11.860197000000005}}}

In [30]:
import pandas as pd
pd.DataFrame(d)


Out[30]:
creationDateTime downloadUri id isSampleQueryJob notebook ownerId progress query queuePosition queueSize status statusDescription visualization
description 2018-03-05T03:31:31.949Z None 00000000-2137-8c84-0000-00002155c70a True None None 100 We compare the US Department of Agriculture's ... 0 1 success Success NaN
displayedBoundingBox 2018-03-05T03:31:31.949Z None 00000000-2137-8c84-0000-00002155c70a True None None 100 NaN 0 1 success Success {u'northEastCoordinate': {u'latitude': 42.3910...
filters 2018-03-05T03:31:31.949Z None 00000000-2137-8c84-0000-00002155c70a True None None 100 [] 0 1 success Success NaN
isPublic 2018-03-05T03:31:31.949Z None 00000000-2137-8c84-0000-00002155c70a True None None 100 True 0 1 success Success NaN
layers 2018-03-05T03:31:31.949Z None 00000000-2137-8c84-0000-00002155c70a True None None 100 [{u'startingDateTime': u'2017-01-01T00:00:00.0... 0 1 success Success [{u'endingDateTime': u'2017-01-01T00:00:00.882...
name 2018-03-05T03:31:31.949Z None 00000000-2137-8c84-0000-00002155c70a True None None 100 Agriculture in Midwestern U.S. 0 1 success Success NaN
space 2018-03-05T03:31:31.949Z None 00000000-2137-8c84-0000-00002155c70a True None None 100 {u'northEastCoordinate': {u'latitude': 42.3910... 0 1 success Success NaN
timeRange 2018-03-05T03:31:31.949Z None 00000000-2137-8c84-0000-00002155c70a True None None 100 NaN 0 1 success Success {u'startingDateTime': u'2017-01-01T00:00:00.00...

In [ ]: