#This example script accompanies the LabKey documentation topic here:
# https://www.labkey.org/Documentation/wiki-page.view?name=pythonDemo
# The target datasets and additional instructions are available there.

from labkey.api_wrapper import APIWrapper

# Set up an API Wrapper with details about where to find your data. Learn more in the documentation
# topic here: https://www.labkey.org/Documentation/wiki-page.view?name=pythonDemo#auth
#   labkey_server: base URL of your server. Ex: 'your_url.trial.labkey.host' or 'localhost:8080'
#   container_path: The project/folder path on that server
#   context_path: Optional - Dependent upon the server configuration, appearing between the base
#      URL and the project/folder path. Typically '' (None) or 'labkey'
#   use_ssl: Check your site settings. Typically 'True' for remote servers, such as a trial server
#      and false for a localhost machine
#   api_key='your_api_session_key_here' # Optional

labkey_server = 'localhost:8080'
container_path = 'Tutorials/Python Demo Study'
context_path = 'labkey'
use_ssl = False
#api_key='your_api_session_key_here'

api = APIWrapper(labkey_server, container_path, context_path, use_ssl)
# If using a hosted/trial server, remove the context path.  and use a session key:
#api = APIWrapper(labkey_server, container_path, use_ssl, api_key)

# Set schema/table: The schema and table you want to access in the above location
schema = 'study'
table = 'PythonDemo_ExamData'


participant_rows = api.query.select_rows(schema, table)
people = participant_rows['rows']

one_sixty_height_people = []
one_eighty_height_people = []
filtered_people = []


for person in people:
	height = person['Height'] or None
	weight = person['Weight'] or None

	if(height and weight):
		if (height >= 160 and height < 170):
			one_sixty_height_people.append({'ParticipantId': person['ParticipantId'], 'SequenceNum': person['SequenceNum'], 'height': height, 'weight': weight})
		elif (height >= 180 and height < 190):
			one_eighty_height_people.append({'ParticipantId': person['ParticipantId'], 'SequenceNum': person['SequenceNum'], 'height': height, 'weight': weight})
		filtered_people.append(person)

people = filtered_people  # only consider entries with weights and heights

average_one_sixty_weight = sum(person['weight'] for person in one_sixty_height_people) / len(one_sixty_height_people)
average_one_sixty_height = sum(person['height'] for person in one_sixty_height_people) / len(one_sixty_height_people)
average_one_sixty_bmi = round(average_one_sixty_weight / ((average_one_sixty_height / 100.0) ** 2), 2)  # cm * 100 = m
average_one_eighty_weight = sum(person['weight'] for person in one_eighty_height_people) / len(one_eighty_height_people)
average_one_eighty_height = sum(person['height'] for person in one_eighty_height_people) / len(one_eighty_height_people)
average_one_eighty_bmi = round(average_one_eighty_weight / ((average_one_eighty_height / 100.0) ** 2), 2)  # cm * 100 = m

for person in one_sixty_height_people:
	person['bmi'] = round(person['weight'] / ((person['height'] / 100.0) ** 2), 2)   # cm * 100 = m
	person['bmi_delta_from_avg160'] = round(abs(person['bmi'] - average_one_sixty_bmi), 2)
	person['bmi_delta_from_avg180'] = -1.0
for person in one_eighty_height_people:
	person['bmi'] = round(person['weight'] / ((person['height'] / 100.0) ** 2), 2)  # cm * 100 = m
	person['bmi_delta_from_avg160'] = -1.0
	person['bmi_delta_from_avg180'] = round(abs(person['bmi'] - average_one_eighty_bmi), 2)

new_exam_dataset_def = {
	'kind': 'StudyDatasetVisit',
	'domainDesign': {
		'name': 'Python Demo Exam With Delta From Average BMI',
		'fields': [
		# Participant ID, and Visit, are automatically added to the definition
		{
			'name': 'height',
			'label': 'Height',
			'rangeURI': 'int'
		}, {
			'name': 'weight',
			'label': 'Weight',
			'rangeURI': 'double'
		}, {
			'name': 'bmi',
			'label': 'BMI (kg / m^2)',
			'rangeURI': 'double'
		}, {
			'name': 'bmi_delta_from_avg160',
			'label': 'Delta From 160s Height Average BMI (kg / m^2)',
			'rangeURI': 'double'
		}, {
			'name': 'bmi_delta_from_avg180',
			'label': 'Delta From 180s Height Average BMI (kg / m^2)',
			'rangeURI': 'double'
		}]
	},
	'options': {
		'demographics': False   # (boolean) Determines whether the dataset is set as demographic
		#'datasetId' : (int) Specifies a dataset ID to use, the default is to auto generate an ID
		#'categoryId' : (int) Specifies an existing category ID
		#'keyPropertyName' : (str) The name of an additional key field to be used in conjunction with participantId and (visit/SequenceNum) to create unique records
		#'useTimeKeyField' : (boolean) Specifies to use the time portion of a date field as an additional key }
	}
}

print("Creating new dataset: Python Demo Exam With Delta From Average BMI")
new_exam_dataset_domain = api.domain.create(new_exam_dataset_def)

schema = 'study'
table = 'Python Demo Exam With Delta From Average BMI'

print("Inserting data into new dataset")
participant_rows = api.query.insert_rows(schema, table, one_sixty_height_people)
participant_rows = api.query.insert_rows(schema, table, one_eighty_height_people)

# Additional calculations for extending the example
average_all_weights = sum(person['Weight'] for person in people) / len(people)
average_all_heights = sum(person['Height'] for person in people) / len(people)
average_all_bmis = round(average_all_weights / ((average_all_heights / 100.0) ** 2), 2)  # cm * 100 = m
for person in people:
	person['BMI'] = round(person['Weight'] / ((person['Height'] / 100.0) ** 2), 2)  # cm * 100 = m
	person['bmi_delta_from_avg'] = round(abs(person['BMI'] - average_all_bmis), 2)  # not used in rest of example

# You can also use templates to create a definition. This would create a list called "Priority" (defined in priority.tsv in the simpletest_module).
#new_list_domain_from_template_def = {
#    'module': 'simpletest',
#    'domainGroup': 'todolist',
#    'domainKind': 'IntList',
#    'domainTemplate': 'Priority'
#}
#print("Creating new list: Priority")
#new_test_list_domain = api.domain.create(new_list_domain_from_template_def)


# This section will add a new 'BMI' column to the original PythonDemo_ExamData dataset and populate it:
#schema = 'study'
#table = 'PythonDemo_ExamData'
#print("Add and populate BMI column in PythonDemo_ExamData")
#
#PythonDemo_Exam_domain = api.domain.get(schema, table)
#PythonDemo_Exam_domain.add_field({
#    'name': 'BMI',
#    'rangeURI': 'double'
#})

#api.domain.save(schema, table, PythonDemo_Exam_domain)

#participant_rows = api.query.update_rows(schema, table, people)

print("Python script completed.")
