Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Notebook rewrite #3

Merged
merged 3 commits into from
Apr 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion python_client/01_README.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"Start the notebook in the tutorial directory:\n",
"\n",
"```\n",
"cd tutorials\n",
"cd python_client\n",
"jupyter notebook\n",
"```\n",
"\n",
Expand Down
2 changes: 1 addition & 1 deletion python_client/02_Terminology.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.2"
"version": "3.7.2"
}
},
"nbformat": 4,
Expand Down
732 changes: 515 additions & 217 deletions python_client/03_SimpleTutorial.ipynb

Large diffs are not rendered by default.

8 changes: 2 additions & 6 deletions python_client/04_GetAnalytics.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,7 @@
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"metadata": {},
"outputs": [],
"source": [
"# Step 3. Create a daptics session on the server.\n",
Expand All @@ -120,9 +118,7 @@
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"metadata": {},
"outputs": [],
"source": [
"# Step 4. Save and validate the default experimental space parameters.\n",
Expand Down
4 changes: 1 addition & 3 deletions python_client/05_RestartSession.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,7 @@
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"metadata": {},
"outputs": [],
"source": [
"# Step 4. Reconnect to a daptics session on the server.\n",
Expand Down
153 changes: 120 additions & 33 deletions python_client/daptics_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
On the web at https://daptics.ai
By email at support@daptics.ai

Daptics API Version 0.5.1
Daptics API Version 0.6.0
Copyright (c) 2019 Daptics Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
Expand Down Expand Up @@ -42,7 +42,8 @@
import requests
import requests.auth
import time

import sys
from time import sleep

class TokenAuth(requests.auth.AuthBase):
"""A callable authentication object for the Python "requests" moudule.
Expand Down Expand Up @@ -162,6 +163,47 @@ def __init__(self, host):
self.validated_params = None
self.design = None

def print(self):
print("host = ",self.host)
print("user_id = ",self.user_id)
print("session_id = ",self.session_id)
print("current_task = ",self.current_task)
print("gen = ",self.gen)
if self.validated_params is not None:
print("Experimental Space Definition:")
for x in self.validated_params:
if x == 'space':
sp = self.validated_params[x]
for y in sp:
if y == 'table':
print('\t ESD Data:')
print("\t\t",sp['table']['colHeaders'])
for z in sp['table']['data']:
zz = [z[i] for i in range(len(z)) if z[i] != '']
print('\t\t',zz)
else:
print("\t",y,": ",sp[y])
else:
print("\t",x,": ",self.validated_params[x])
else:
print("Experimental Space Definition validated_params = None")

if self.design is not None:
print("Design:")
print(self.design['table']['colHeaders'])
for dd in self.design['table']['data']:
print(dd)
else:
print("design: None")

def call_api(self, doc, vars, timeout=None):
data = None
try:
data = self.gql.execute(doc, variable_values=vars,timeout = timeout)
except Exception as e:
data = {'error': str(e)}
return data

def save(self, fname):
"""Save the user and session id to a JSON file.

Expand Down Expand Up @@ -270,7 +312,7 @@ def login(self, email, password):
self.user_id = data['login']['user']['userId']
return data

def create_session(self, name, description, demo):
def create_session(self, name, description):
"""Create a new PDT session.

Parameters
Expand All @@ -279,8 +321,6 @@ def create_session(self, name, description, demo):
The unique name for the session among the authenticated user's sessions.
description : str
A description for the session.
is_demo : bool
If True, this will be a demo session with simulated designs and responses.

Returns
-------
Expand All @@ -293,10 +333,9 @@ def create_session(self, name, description, demo):
'userId': self.user_id,
'name': name,
'description': description,
'demo': demo
'demo': False # If True, this will be a demo session with simulated designs and responses.
}
}

# The 'createSession' mutation will add a new session to the backend's database,
# copy runtime files to a fresh Rserve session directory on the Rserve filesystem,
# start the session and return initial session information.
Expand All @@ -316,7 +355,13 @@ def create_session(self, name, description, demo):
}
}
""")
data = self.gql.execute(doc, variable_values=vars)
# data = self.gql.execute(doc, variable_values=vars)
data = self.call_api(doc,vars)
if 'error' in data:
print("Problem creating session!")
print("Error: {}".format(data['error']))
print("Hint: session name may have already been taken, in which case choose another one.")
return None
if 'createSession' in data and data['createSession'] is not None:
self.session_id = data['createSession']['sessionId']
self.initial_params = data['createSession']['params']
Expand Down Expand Up @@ -1054,7 +1099,14 @@ def poll_for_current_task(self, task_type=None):
}
}
""")
data = self.gql.execute(doc, variable_values=vars)

data = self.call_api(doc, vars)

if 'error' in data:
print("Problem finding current task!")
print("Error: {}".format(data['error']))
return None

if 'currentTask' in data and data['currentTask'] is not None \
and 'status' in data['currentTask'] \
and 'type' in data['currentTask']:
Expand All @@ -1066,11 +1118,11 @@ def poll_for_current_task(self, task_type=None):
self.current_task = data['currentTask']
elif status == 'canceled':
# Message will be in response error
# TESTME: will we ever get here, or will exception be thown first?
# TESTME: will we ever get here, or will exception be thrown first?
self.current_task = None
elif status == 'error':
# Message will be in response error
# TESTME: will we ever get here, or will exception be thown first?
# TESTME: will we ever get here, or will exception be thrown first?
self.current_task = None
elif status == 'success':
# Fetch non-error result
Expand All @@ -1088,6 +1140,37 @@ def poll_for_current_task(self, task_type=None):
self.current_task['pollRetries'] = retries + 1
return data

def wait_for_current_task(self):
"""Wraps poll_for_current_task() in a loop

Returns
_______
None for normal exit.
task['currentTask']['errors'] if ever task['currentTask']['status'] == 'error'.
"""
# Poll the task. Repeat until task disappears, when `status` is `success` (or `failure`).
cnt = 0
while True:
task = self.poll_for_current_task()
if task['currentTask'] is not None:
sys.stdout.write("\r")
if task['currentTask']['status'] == 'error':
sys.stdout.write("\n")
print("Error! Messages are:")
# print(task)
for ee in task['currentTask']['errors'][0]:
print(ee,'\t',task['currentTask']['errors'][0][ee])
print("------------ end of error messages.")
return
mystr = "status = "+str(task['currentTask']['status'])+" -- "+str(cnt)+" seconds."
sys.stdout.write(mystr)
sleep(1)
cnt = cnt+1
else:
sys.stdout.write("\n")
print("Error: no client found!")
break

def get_validated_experimental_space(self, timeout=5*60):
"""Utility method to retrieve the validated experimental space from
the session. If the session was restarted and the experimental space
Expand All @@ -1114,25 +1197,24 @@ def get_validated_experimental_space(self, timeout=5*60):
tmax = time.time()
if timeout is not None and timeout > 0:
tmax += timeout
while True:
data = self.poll_for_current_task('space')
if 'currentTask' in data and data['currentTask'] is not None:
type_ = data['currentTask']['type']
if type_ == 'space':
status = data['currentTask']['status']
if status == 'success' and self.validated_params is not None:
return self.validated_params['space']
elif status != 'new' and status != 'running':
raise TaskFailedError('space')
else:
raise TaskTypeError('space')
if 'currentTask' in data and data['currentTask'] is not None:
type_ = data['currentTask']['type']
if type_ == 'space':
status = data['currentTask']['status']
if status == 'success' and self.validated_params is not None:
return self.validated_params['space']
elif status != 'new' and status != 'running':
raise TaskFailedError('space')
else:
raise NoCurrentTaskError()
if tmax < time.time():
raise TaskTimeoutError()
time.sleep(1.0)
raise TaskTypeError('space')
else:
raise NoCurrentTaskError()
if tmax < time.time():
raise TaskTimeoutError()
time.sleep(1.0)


def get_generated_design(self, gen, timeout=30*60):
def get_generated_design(self, gen=None, timeout=30*60):
"""Utility method to retrieve a design generation from
the session. If the session was restarted and the design for the
specified generation number is available, it will be in the `design`
Expand All @@ -1155,6 +1237,8 @@ def get_generated_design(self, gen, timeout=30*60):
with empty responses with `colHeaders`, and `data` keys.
"""

if gen == None:
gen = self.gen
if self.validated_params is None or gen < 0:
raise SessionParametersNotValidatedError()

Expand Down Expand Up @@ -1339,21 +1423,22 @@ def export_initial_experiments_template_csv(self, fname, timeout=5*60):

space = self.get_validated_experimental_space(timeout)
col_headers = self.experiments_table_column_names(space)
self.export_csv({'colHeaders': colHeaders, 'data':[]}, fname)
self.export_csv({'colHeaders': col_headers, 'data':[]}, fname)
return col_headers

def export_generated_design_csv(self, gen, fname, timeout=30*60):
def export_generated_design_csv(self, fname, gen = None, timeout=30*60):
"""Retrieves a design generation from the session, adn writes the
experiments table (with empty responses) to a CSV file on disk.

Parameters
----------
gen : int
The generation number for the design to be retrieved.

fname : str
The filesystem path where the file will be written.

gen : int
The generation number for the design to be retrieved. Default current
generation.

timeout : int
The maximum number of seconds that the client will poll the session
to retrieve the generated design. The default is 1800 (30 minutes).
Expand All @@ -1364,6 +1449,8 @@ def export_generated_design_csv(self, gen, fname, timeout=30*60):
with empty responses with `colHeaders`, and `data` keys.
"""

if gen is None:
gen = self.gen
design = self.get_generated_design(gen, timeout)
self.export_csv(design['table'], fname)
return design
Expand Down
6 changes: 3 additions & 3 deletions python_client/esd-factorial-3x5.csv
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
V11,numerical,0,1,2,3,4
V12,numerical,0,1,2,3,4
V13,numerical,0,1,2,3,4
param1,numerical,0,1,2,3,4
param2,numerical,0,1,2,3,4
param3,numerical,0,1,2,3,4
4 changes: 4 additions & 0 deletions python_client/esd-factorial-4x8.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
param1,numerical,0,1,2,3,4,5,6,7
param2,numerical,0,1,2,3,4,5,6,7
param3,numerical,0,1,2,3,4,5,6,7
param4,numerical,0,1,2,3,4,5,6,7
16 changes: 8 additions & 8 deletions python_client/esd-factorial-8x5.csv
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
V11,numerical,0,1,2,3,4
V12,numerical,0,1,2,3,4
V13,numerical,0,1,2,3,4
t11,numerical,5,10,15,20,25
t12,numerical,5,10,15,20,25
V21,numerical,0,1,2,3,4
V22,numerical,0,1,2,3,4
V23,numerical,0,1,2,3,4
param1,numerical,0,1,2,3,4
param2,numerical,0,1,2,3,4
param3,numerical,0,1,2,3,4
param4,numerical,5,10,15,20,25
param5,numerical,5,10,15,20,25
param6,numerical,0,1,2,3,4
param7,numerical,0,1,2,3,4
param8,numerical,0,1,2,3,4
10 changes: 5 additions & 5 deletions python_client/esd-mixture-5.csv
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
p1,unit,0,5
p2,unit,0,5
p3,unit,1,5
p4,unit,1,5
p5,unit,1,5
param1,unit,0,5
param2,unit,0,5
param3,unit,1,5
param4,unit,1,5
param5,unit,1,5