userguide:thinknode
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
userguide:thinknode [2015/06/26 01:08] – [SOBP Dose Calculation] kerhart | userguide:thinknode [2015/07/02 15:42] (current) – removed dpatenaude | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== thinknode™ Examples ====== | ||
- | These examples provide a starting point for issuing http connections and requests to the dosimetry app on the thinknode™ framework. They are provided as is, and are written in python and c++. Any further dependencies are listed along with the provided scripts. | ||
- | |||
- | ====== C++ ====== | ||
- | |||
- | A simple C++ project that handles posting immutable objects and calculation requests to thinknode™ framework. The //main()// function toggles on which task to perform. Below are the defined functions of the project as well as a link to download the file in its entirety. | ||
- | |||
- | Dependencies: | ||
- | * [[http:// | ||
- | * [[https:// | ||
- | |||
- | ===thinknode.cpp=== | ||
- | |||
- | * {{: | ||
- | |||
- | <code cpp> | ||
- | // Copyright (c) 2015 .decimal, Inc. All rights reserved. | ||
- | // Desc: | ||
- | |||
- | #include " | ||
- | #include < | ||
- | #include < | ||
- | #include < | ||
- | #include < | ||
- | #include < | ||
- | #include < | ||
- | |||
- | #define CURL_STATICLIB | ||
- | #include < | ||
- | |||
- | using namespace std; | ||
- | |||
- | // API configuration | ||
- | string basic_user = " | ||
- | string api_url = " | ||
- | string app_name = " | ||
- | string app_version = " | ||
- | |||
- | // Curl get request call back | ||
- | static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) | ||
- | ... | ||
- | |||
- | // Select a specific json tag into string | ||
- | string get_json_value(string json, string id, int num = 0) | ||
- | ... | ||
- | |||
- | // Curllib get http request | ||
- | string do_curl_get(string auth, string url) | ||
- | ... | ||
- | |||
- | // Curllib post http request | ||
- | string do_curl_post(string auth, string json, string url) | ||
- | ... | ||
- | |||
- | // Handles http request to get the user ID from the basic_user | ||
- | string get_user_token() | ||
- | ... | ||
- | |||
- | // Handles http request for realm id | ||
- | string get_realm_id(string token) | ||
- | ... | ||
- | |||
- | // Handles http request for context id | ||
- | string get_context_id(std:: | ||
- | ... | ||
- | |||
- | // API Authentication | ||
- | std:: | ||
- | ... | ||
- | |||
- | // Grab and post the specified calc request | ||
- | void post_calc_request() | ||
- | ... | ||
- | |||
- | // Grab and post sepcified object to the ISS | ||
- | void post_immutable_object() | ||
- | ... | ||
- | |||
- | int main(void) | ||
- | ... | ||
- | |||
- | </ | ||
- | |||
- | ===== C++: Immutable Storage ===== | ||
- | |||
- | |||
- | The below example is a function in the [[userguide: | ||
- | |||
- | |||
- | Dependencies: | ||
- | * {{: | ||
- | |||
- | <code cpp> | ||
- | void post_immutable_object() | ||
- | { | ||
- | // Immutable info | ||
- | string path = " | ||
- | string sjon_iss_file = " | ||
- | string obj_name = " | ||
- | |||
- | std:: | ||
- | |||
- | // Read local immutable json file | ||
- | std:: | ||
- | string str((std:: | ||
- | | ||
- | // Post object | ||
- | std::cout << " | ||
- | string authentication_string = " | ||
- | string res = do_curl_post( | ||
- | authentication_string, | ||
- | str, | ||
- | api_url + "/ | ||
- | std::cout << " | ||
- | } | ||
- | </ | ||
- | |||
- | **Returns: | ||
- | - The ID (in json) of the object stored in Immutable Storage. | ||
- | |||
- | ===== C++: Calculation Request ===== | ||
- | |||
- | The below example is a function in the [[userguide: | ||
- | |||
- | Dependencies: | ||
- | * {{: | ||
- | |||
- | <code cpp> | ||
- | void post_calc_request() | ||
- | { | ||
- | // Request info | ||
- | string path = " | ||
- | string sjon_iss_file = " | ||
- | |||
- | std:: | ||
- | |||
- | std:: | ||
- | string str((std:: | ||
- | | ||
- | string authentication_string = " | ||
- | // Get calculation id | ||
- | std::cout << " | ||
- | string calculation_id = get_json_value( | ||
- | do_curl_post(authentication_string, | ||
- | str, api_url + "/ | ||
- | " | ||
- | |||
- | // Get calculation Status - using long polling | ||
- | std::cout << " | ||
- | string calculation_status = get_json_value( | ||
- | do_curl_get(authentication_string, | ||
- | api_url + "/ | ||
- | " | ||
- | if (calculation_status.find(" | ||
- | { | ||
- | std::cout << " | ||
- | return; | ||
- | } | ||
- | |||
- | // Get calculation Result | ||
- | std::cout << " | ||
- | string calculation_result = do_curl_get( | ||
- | authentication_string, | ||
- | api_url + "/ | ||
- | |||
- | std::cout << " | ||
- | } | ||
- | </ | ||
- | |||
- | **Returns: | ||
- | - The calculation result (in json) of the API function called. | ||
- | ====== Python ====== | ||
- | |||
- | The provided python scripts and libraries are meant to be a foundation and starting point for using the astroid Dosimetry app on the thinknode™ framework. The provided scripts outline the basics of using ISS to store objects, as well as constructing and making calculation requests to the calculation provider. The below sections detail the basic usage for each script. | ||
- | |||
- | **Download: | ||
- | |||
- | ====thinknode.cfg==== | ||
- | |||
- | There is a simple configuration file (thinknode.cfg) that is used to store user data for connecting to the Dosimetry app on the thinknode™ framework. This file is required by all scripts in the python astroid_script_library to authenticate and use the Dosimetry app. A sample file with no user data is available in the repository and the details of the information to include in the file are provided below. | ||
- | |||
- | * // | ||
- | * //api_url// being the connection string to the thinknode™ framework. | ||
- | * // | ||
- | * // | ||
- | |||
- | <code json thinknode.cfg> | ||
- | { | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | } | ||
- | |||
- | </ | ||
- | ===== Python: Immutable Storage ===== | ||
- | ==== Post Generic ISS Object ==== | ||
- | |||
- | The // | ||
- | |||
- | Dependencies: | ||
- | * [[userguide: | ||
- | * [[userguide: | ||
- | * compute_aperture_creation_params.json (or any other prebuilt json file of a dosimetry object as described in the [[http:// | ||
- | |||
- | <code python post_iss_object_generic.py> | ||
- | # Copyright (c) 2015 .decimal, Inc. All rights reserved. | ||
- | # Desc: Post an immutable json object to the thinknode framework | ||
- | |||
- | from lib import thinknode_worker as thinknode | ||
- | from lib import decimal_logging as dl | ||
- | import requests | ||
- | import json | ||
- | |||
- | iss_dir = " | ||
- | json_iss_file = " | ||
- | obj_name = " | ||
- | |||
- | # Get IAM ids | ||
- | iam = thinknode.authenticate(thinknode.read_config(' | ||
- | |||
- | # App object to post to iss | ||
- | with open(iss_dir + '/' | ||
- | json_data = json.load(data_file) | ||
- | |||
- | # Post immutable object to ISS | ||
- | res = thinknode.post_immutable(iam, | ||
- | dl.data(" | ||
- | |||
- | </ | ||
- | |||
- | **Returns: | ||
- | - The ID (in json) of the object stored in Immutable Storage. | ||
- | ===== Python: Calculation Request ===== | ||
- | |||
- | ==== Generic Calc Request ==== | ||
- | |||
- | The // | ||
- | |||
- | Dependencies: | ||
- | * [[userguide: | ||
- | * [[userguide: | ||
- | * compute_aperture.json (or any other prebuilt json file of a dosimetry object as described in the [[http:// | ||
- | |||
- | <code python post_calc_request_generic.py> | ||
- | # Copyright (c) 2015 .decimal, Inc. All rights reserved. | ||
- | # Desc: Post a json calculation request to the thinknode framework | ||
- | |||
- | from lib import thinknode_worker as thinknode | ||
- | from lib import decimal_logging as dl | ||
- | import requests | ||
- | import json | ||
- | |||
- | request_dir = " | ||
- | json_calc_file = " | ||
- | |||
- | # Get IAM ids | ||
- | iam = thinknode.authenticate(thinknode.read_config(' | ||
- | |||
- | # App calculation request | ||
- | with open(request_dir + '/' | ||
- | json_data = json.load(data_file) | ||
- | |||
- | # Send calc request and wait for answer | ||
- | res = thinknode.do_calculation(iam, | ||
- | dl.data(" | ||
- | </ | ||
- | |||
- | **Returns: | ||
- | - The calculation result (in json) of the API function called. | ||
- | |||
- | ==== SOBP Dose Calculation ==== | ||
- | The // | ||
- | |||
- | The // | ||
- | |||
- | The // | ||
- | |||
- | Dependencies: | ||
- | * [[userguide: | ||
- | * [[userguide: | ||
- | |||
- | === Example === | ||
- | |||
- | Below is an abbreviated version of the // | ||
- | In the below sample, the // | ||
- | |||
- | * Modules used and explanation: | ||
- | * The // | ||
- | * The // | ||
- | * The // | ||
- | |||
- | Refer to the [[userguide: | ||
- | |||
- | <code python> | ||
- | import json | ||
- | from lib import thinknode_worker as thinknode | ||
- | from lib import decimal_logging as dl | ||
- | from lib import dosimetry_types as dt | ||
- | |||
- | # Get IAM ids | ||
- | iam = thinknode.authenticate(thinknode.read_config(' | ||
- | |||
- | def make_grid(corner, | ||
- | ... | ||
- | |||
- | def make_water_phantom(corner, | ||
- | ... | ||
- | |||
- | def make_dose_points(pointCount): | ||
- | ... | ||
- | |||
- | def get_example_sobp_machine(id): | ||
- | ... | ||
- | |||
- | def make_layers(sad, | ||
- | ... | ||
- | |||
- | def make_target(): | ||
- | return \ | ||
- | thinknode.function(" | ||
- | [ | ||
- | thinknode.value([-32, | ||
- | thinknode.value([16, | ||
- | ]) | ||
- | |||
- | def make_view(): | ||
- | mv = dt.multiple_source_view() | ||
- | ds = {} | ||
- | ds[' | ||
- | ds[' | ||
- | mv.display_surface = ds | ||
- | mv.center = [0, 0, 0] | ||
- | mv.direction = [0, 1, 0] | ||
- | mv.distance = [2270, 2270] | ||
- | mv.up = [0, 0, 1] | ||
- | |||
- | return mv.out() | ||
- | |||
- | def compute_aperture(): | ||
- | ap_params = dt.aperture_creation_params() | ||
- | |||
- | # ap_params.targets.append(thinknode.reference(" | ||
- | ap_params.targets.append(make_target()) | ||
- | ap_params.target_margin = 20.0 | ||
- | ap_params.view = make_view() | ||
- | ap_params.mill_radius = 0.0 | ||
- | ap_params.downstream_edge = 250.5 | ||
- | |||
- | # Make aperture_creation_params | ||
- | args = {} | ||
- | args[" | ||
- | args[" | ||
- | args[" | ||
- | args[" | ||
- | args[" | ||
- | args[" | ||
- | args[" | ||
- | args[" | ||
- | args[" | ||
- | args[" | ||
- | |||
- | return \ | ||
- | thinknode.function(" | ||
- | [ | ||
- | thinknode.structure_named_type(" | ||
- | ]) | ||
- | |||
- | beam_geometry = \ | ||
- | ... | ||
- | |||
- | # Call compute_sobp_pb_dose2 | ||
- | dose_calc = \ | ||
- | thinknode.function(" | ||
- | [ | ||
- | make_water_phantom([-100, | ||
- | thinknode.value(make_dose_points(181)), | ||
- | beam_geometry, | ||
- | make_grid([-75, | ||
- | make_layers(2270.0, | ||
- | compute_aperture(), | ||
- | thinknode.value([proton_degr]) # degraders | ||
- | ]) | ||
- | | ||
- | # Perform calculation | ||
- | res = thinknode.do_calculation(iam, | ||
- | dl.data(" | ||
- | </ | ||
- | ===== Python: decimal Libraries ===== | ||
- | |||
- | ==== dosimetry_types ==== | ||
- | |||
- | The // | ||
- | |||
- | Each data type detailed in the [[http:// | ||
- | |||
- | |||
- | Below you will see as snippet from the dosimetiry_types module that shows the class for the // | ||
- | * **Interdependence: | ||
- | * **//out// function:** Each class' | ||
- | |||
- | <code python> | ||
- | class aperture_creation_params: | ||
- | |||
- | #Initialize | ||
- | def __init__(self): | ||
- | self.targets = [] | ||
- | self.target_margin = 0.0 | ||
- | multiple_source_vie = multiple_source_view() | ||
- | self.view = multiple_source_vie.out() | ||
- | self.mill_radius = 0.0 | ||
- | self.organs = [] | ||
- | self.half_planes = [] | ||
- | self.corner_planes = [] | ||
- | self.centerlines = [] | ||
- | self.overrides = [] | ||
- | self.downstream_edge = 0.0 | ||
- | |||
- | def out(self): | ||
- | values = OrderedDict([(" | ||
- | (" | ||
- | (" | ||
- | (" | ||
- | (" | ||
- | (" | ||
- | (" | ||
- | (" | ||
- | (" | ||
- | (" | ||
- | ]) | ||
- | return values | ||
- | </ | ||
- | ==== thinknode_worker ==== | ||
- | |||
- | The // | ||
- | |||
- | Refer to the [[https:// | ||
- | |||
- | <code python> | ||
- | # Authenticate with thinknode and store necessary ids | ||
- | # Gets the realm_id, bucket_id, and context_id for the current iam configuration | ||
- | # param config: connection settings (url and unique basic user authentication) | ||
- | def authenticate(config): | ||
- | |||
- | # Send calculation request to thinknode api | ||
- | # param config: connection settings (url, user token, and ids for context and realm) | ||
- | # param json_data: calculation request in json format | ||
- | # param return_data: | ||
- | def do_calculation(config, | ||
- | |||
- | # Post immutable object to ISS | ||
- | # param config: connection settings (url, user token, and ids for context and realm) | ||
- | # param json_data: immutable object in json format | ||
- | # param obj_name: object name of app to post to | ||
- | def post_immutable(config, | ||
- | |||
- | # Post immutable object to ISS | ||
- | # param config: connection settings (url, user token, and ids for context and realm) | ||
- | # param obj_id: thinknode iss reference id for object to get | ||
- | def get_immutable(config, | ||
- | |||
- | |||
- | </ | ||
- | |||
- | ==== decimal_logging ==== | ||
- | |||
- | The // | ||
- | |||
- | The following settings are available in the decimal_logging.py file: | ||
- | **display_timestamps: | ||
- | **display_types: | ||
- | **log_file: ** sets the logfile name and location | ||
- | |||
- | The following image shows the logging settings for each message type as: | ||
- | - Timestamps = //True//; Types = //True// | ||
- | - Timestamps = //False//; Types = //True// | ||
- | - Timestamps = //False//; Types = //False// | ||
- | |||
- | {{ : | ||
- | ====== Node.js ====== | ||
- | |||
- | The following section contains examples using node.js and (if applicable) the specified modules. These examples are for a high level approach to encoding and decoding the blob data that is part of the Dosimetry App calculation request. | ||
- | |||
- | **Base64 Blob Format** | ||
- | |||
- | The blob returned by a calculation request is formatted as such: | ||
- | |||
- | <code cpp> | ||
- | // value_type enum definitions | ||
- | // Nil = 0; | ||
- | // Boolean = 1; | ||
- | // Number = 2; | ||
- | // String = 3; | ||
- | // Blob = 4; | ||
- | // List = 5; | ||
- | // Record = 6; | ||
- | |||
- | // For value_types nil, boolean, number, string | ||
- | // <uint32 value_type enum (4 bytes)>< | ||
- | |||
- | // For value_types blob, list, record | ||
- | // <uint31 value_type enum (4 bytes)>< | ||
- | </ | ||
- | |||
- | ===== Node: Decrypt Base64 Blob Data ===== | ||
- | |||
- | The following example shows , using node.js, how to decode the base64 encoded data returned by a calculation request. | ||
- | |||
- | <code javascript> | ||
- | // The below base64string is a blob array with the values [ -25, -25, 25, -25, 25, 25, -25, 25 ] | ||
- | var b64string = " | ||
- | |||
- | // The below base64string is a number set to the value 25.1 | ||
- | //var b64string = " | ||
- | |||
- | var buf = new Buffer(b64string, | ||
- | |||
- | var zlib = require(' | ||
- | |||
- | function read_base_255_number(buf, | ||
- | var n = 0; | ||
- | var s = 0; | ||
- | while (offset < buf.length) { | ||
- | var digit = buf[offset]; | ||
- | var value = buf.readUInt8(offset); | ||
- | offset++; | ||
- | s++; | ||
- | if (digit.toString(16) === ' | ||
- | break; | ||
- | } | ||
- | n = n * 255; | ||
- | n += value; | ||
- | } | ||
- | return [s, n]; | ||
- | } | ||
- | |||
- | var size = read_base_255_number(buf, | ||
- | |||
- | zlib.unzip(buf.slice(4 + size[0]), function (err, data) { | ||
- | if (err) { | ||
- | throw err | ||
- | } | ||
- | var value_type = data.readUInt32LE(0); | ||
- | |||
- | // Number | ||
- | if (value_type === 2) { | ||
- | console.log(" | ||
- | } | ||
- | // Blob | ||
- | else if (value_type === 4) { | ||
- | // Read size here | ||
- | var values = []; | ||
- | for (var i = 12; i < data.length; | ||
- | values.push(data.readDoubleLE(i)); | ||
- | } | ||
- | console.log(values); | ||
- | } | ||
- | }); | ||
- | |||
- | </ | ||
- | |||
- | {{page> |
userguide/thinknode.1435280916.txt.gz · Last modified: 2021/07/29 18:19 (external edit)