Skip to content

Commit 7b3a016

Browse files
authored
Merge pull request #161 from neelan29/CV---Display-images
New custom step: CV - Display Images
2 parents 86c6d9d + 8fae099 commit 7b3a016

File tree

4 files changed

+68
-0
lines changed

4 files changed

+68
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"creationTimeStamp":"2024-07-23T16:18:20.370Z","modifiedTimeStamp":"2024-08-06T15:04:53.251Z","createdBy":"neveng","modifiedBy":"neveng","name":"CV - Display Images.step","displayName":"CV - Display Images.step","localDisplayName":"CV - Display Images.step","properties":{},"links":[{"method":"GET","rel":"self","href":"/dataFlows/steps/17dfac95-9abc-4e57-8ecb-c9859094a97d","uri":"/dataFlows/steps/17dfac95-9abc-4e57-8ecb-c9859094a97d","type":"application/vnd.sas.data.flow.step"},{"method":"GET","rel":"alternate","href":"/dataFlows/steps/17dfac95-9abc-4e57-8ecb-c9859094a97d","uri":"/dataFlows/steps/17dfac95-9abc-4e57-8ecb-c9859094a97d","type":"application/vnd.sas.data.flow.step.summary"},{"method":"GET","rel":"up","href":"/dataFlows/steps","uri":"/dataFlows/steps","type":"application/vnd.sas.collection","itemType":"application/vnd.sas.data.flow.step.summary"},{"method":"PUT","rel":"update","href":"/dataFlows/steps/17dfac95-9abc-4e57-8ecb-c9859094a97d","uri":"/dataFlows/steps/17dfac95-9abc-4e57-8ecb-c9859094a97d","type":"application/vnd.sas.data.flow.step","responseType":"application/vnd.sas.data.flow.step"},{"method":"DELETE","rel":"delete","href":"/dataFlows/steps/17dfac95-9abc-4e57-8ecb-c9859094a97d","uri":"/dataFlows/steps/17dfac95-9abc-4e57-8ecb-c9859094a97d"},{"method":"POST","rel":"copy","href":"/dataFlows/steps/17dfac95-9abc-4e57-8ecb-c9859094a97d/copy","uri":"/dataFlows/steps/17dfac95-9abc-4e57-8ecb-c9859094a97d/copy","responseType":"application/vnd.sas.data.flow.step"},{"method":"GET","rel":"transferExport","href":"/dataFlows/steps/17dfac95-9abc-4e57-8ecb-c9859094a97d","uri":"/dataFlows/steps/17dfac95-9abc-4e57-8ecb-c9859094a97d","responseType":"application/vnd.sas.transfer.object"},{"method":"PUT","rel":"transferImportUpdate","href":"/dataFlows/steps/17dfac95-9abc-4e57-8ecb-c9859094a97d","uri":"/dataFlows/steps/17dfac95-9abc-4e57-8ecb-c9859094a97d","type":"application/vnd.sas.transfer.object","responseType":"application/vnd.sas.summary"}],"metadataVersion":0.0,"version":2,"type":"code","flowMetadata":{"inputPorts":[{"name":"disp_ip_tbl","displayName":"disp_ip_tbl","localDisplayName":"disp_ip_tbl","minEntries":1,"maxEntries":1,"defaultEntries":0,"type":"table"}],"outputPorts":[]},"ui":"{\n\t\"showPageContentOnly\": true,\n\t\"pages\": [\n\t\t{\n\t\t\t\"id\": \"pageParameters\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"label\": \"Parameters\",\n\t\t\t\"children\": [\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"section1\",\n\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\"label\": \"Input parameters\",\n\t\t\t\t\t\"open\": true,\n\t\t\t\t\t\"visible\": \"\",\n\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"disp_ip_tbl\",\n\t\t\t\t\t\t\t\"type\": \"inputtable\",\n\t\t\t\t\t\t\t\"label\": \"Input table name:\",\n\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\"placeholder\": \"\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"disp_count\",\n\t\t\t\t\t\t\t\"type\": \"textfield\",\n\t\t\t\t\t\t\t\"label\": \"Number of images to view:\",\n\t\t\t\t\t\t\t\"placeholder\": \"3\",\n\t\t\t\t\t\t\t\"required\": false,\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"disp_dicom\",\n\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\"label\": \"The data consists of DICOM images.\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"id\": \"pageAbout\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"label\": \"About\",\n\t\t\t\"children\": [\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"text1\",\n\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\"text\": \"CV - Display Images\\n===============\\n\\nThis custom step displays images to the user. The step processes and displays the images contained in an input table. \\n\\nPrerequisites:\\n\\n1. This custom step runs on data loaded to SAS Cloud Analytics Services (CAS). Ensure you are connected to CAS before running this step.\\n2. Ensure SAS Viya has access to an active Python environment. This custom step requires Python (through proc python) to be enabled inside SAS compute. \\n3. Install all required Python packages (see section \\\"Python packages required\\\").\",\n\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"packages_section\",\n\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\"label\": \"Python packages required\",\n\t\t\t\t\t\"open\": false,\n\t\t\t\t\t\"visible\": \"\",\n\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"packages_list\",\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"text\": \"This custom step makes use of the following Python packages: \\n\\n1. swat (version 1.13.3)\\n2. python-dlpy (version 1.2.1-dev)\\n3. matplotlib \\n\\nNavigate to \\\"Documentation\\\" section to see documentation links for the above packages.\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"about_parameters\",\n\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\"label\": \"Parameters\",\n\t\t\t\t\t\"open\": false,\n\t\t\t\t\t\"visible\": \"\",\n\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"parameters_input\",\n\t\t\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\t\t\"label\": \"Input Parameters\",\n\t\t\t\t\t\t\t\"open\": true,\n\t\t\t\t\t\t\t\"visible\": \"\",\n\t\t\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"id\": \"input_parameters_text\",\n\t\t\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\t\t\"text\": \"1. Input table name (Required): Select/attach an input table node to this custom step. Provide a valid table name and caslib name of the CAS table containing images which the user would like to view. \\n\\n2. Number of images to view (Optional): Provide an input value for the number of images to be displayed to the user. By default, the value is set to 3. \\n\\n3. The data consists of DICOM images (Optional): Choose whether the data contains 3-Dimensional medical DICOM images. By default, the option is set to No. \",\n\t\t\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"about_documentation\",\n\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\"label\": \"Documentation\",\n\t\t\t\t\t\"open\": false,\n\t\t\t\t\t\"visible\": \"\",\n\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"documentation_text\",\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"text\": \"1. Documentation on the swat package: https://sassoftware.github.io/python-swat/\\n\\n2. Documentation on python-dlpy package:\\nhttps://github.com/sassoftware/python-dlpy\\n\\n3. Documentation on SAS callback object and methods: https://go.documentation.sas.com/doc/da/pgmsascdc/default/proc/p0z7ahqmabxu6kn193kdojjhc477.htm\\n\\n4. Matplotlib package: https://matplotlib.org/stable/index.html\\n\\n5. This SAS Communities article provides details on the environment variables which facilitate connecting to CAS using the swat package within SAS Studio: https://communities.sas.com/t5/SAS-Communities-Library/Hotwire-your-SWAT-inside-SAS-Studio/ta-p/835956\\n\\n6. Peter Styliadis provides this helpful post (SAS documentation link contained therein) on how to identify a current active CAS session: https://communities.sas.com/t5/SAS-Viya/Programmatically-detect-an-active-CAS-session/m-p/890914#M1985\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"change_log_text\",\n\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\"text\": \"Version: 1.0 06AUG2024\",\n\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"contact_text\",\n\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\"text\": \"Created/contact: \\n\\n- Neela Vengateshwaran ([email protected])\",\n\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t],\n\t\"syntaxversion\": \"1.3.0\",\n\t\"values\": {\n\t\t\"disp_ip_tbl\": {\n\t\t\t\"library\": \"\",\n\t\t\t\"table\": \"\"\n\t\t},\n\t\t\"disp_count\": \"3\",\n\t\t\"disp_dicom\": false\n\t}\n}","templates":{"SAS":"/*-------------------------------*\n CREATE MACRO DEFINITIONS\n*------------------------------*/\n\n/* -----------------------------------------------------------------------------------------* \n This macro definition identifies if an active CAS session exists. About[doc] for details\n*------------------------------------------------------------------------------------------ */\n\n%if %sysfunc(symexist(_SESSREF_)) %then %do;\n %let casSessionExists= %sysfunc(sessfound(&_SESSREF_.));\n%end;\n\nproc python restart;\nsubmit;\n\n#############################################################################################\n# Imports\n#############################################################################################\n\nimport swat\nimport dlpy as dlpy\nimport os\nimport numpy as np\nfrom swat import *\nfrom matplotlib import pyplot\nimport matplotlib.pylab as plt\nimport matplotlib\n\n#############################################################################################\n# Establish a connection to CAS, attempting to connect to an existing connection.\n# Ensure that an active CAS connection exists prior to running\n# Otherwise, default to a new connection \n#############################################################################################\n\ncas_session_exists = SAS.symget(\"casSessionExists\")\ncas_host_path = SAS.symget(\"_CASHOST_SHARED_\")\ncas_host_port = SAS.symget(\"_CASPORT_\")\n\nSAS.logMessage(f\"Host is {cas_host_path}\")\nSAS.logMessage(f\"Port is {cas_host_port}\")\n\nos.environ['CAS_CLIENT_SSL_CA_LIST'] = os.environ['SSLCALISTLOC']\n\nif cas_session_exists=='1':\n sessuuid = SAS.symget(\"_IOCASUUID_\")\n SAS.logMessage(\"Connection exists. Session UUID is {}\".format(sessuuid))\n s = swat.CAS(hostname= cas_host_path.strip('\"'), port=cas_host_port, password=os.environ['SAS_SERVICES_TOKEN'],session=sessuuid)\n SAS.logMessage(\"Connected to existing session.\")\n\nelse:\n SAS.logMessage(\"New Connection made to CAS through swat.\")\n s = swat.CAS(hostname=cas_host_path.strip('\"'),port=cas_host_port, password=os.environ['SAS_SERVICES_TOKEN'])\n\n#############################################################################################\n# Get user inputs from UI \n#############################################################################################\n\ns.loadactionset(\"image\")\ns.loadactionset(\"bioMedImage\")\n\nimg_count = SAS.symget(\"disp_count\")\ninput_table_name\t= SAS.symget(\"disp_ip_tbl_name_base\")\ninput_caslib = SAS.symget(\"disp_ip_table_lib\")\nis_dicom = SAS.symget(\"disp_dicom\")\n\ns.sessionProp.setSessOpt(caslib=input_caslib)\n\ninput_castbl = s.CASTable(input_table_name)\n\nif int(is_dicom) == 1:\n\t\n\ts.image.processimages(\n\t\t\t\t\t\t casout=dict(name=input_castbl, replace=True),\n\t\t\t\t\t\t imageFunctions=[{\"functionOptions\":{\"functionType\":\"CONVERT_COLOR\", \"type\":\"GRAY2COLOR\"}}],\n\t\t\t\t\t\t table = input_castbl\n\t\t\t\t\t\t )\n\nfor i in range(int(img_count)):\n\ta = input_castbl.fetchimages().Images['Image'][i] \n\tplt.xticks([]), plt.yticks([])\n\tplt.imshow(a)\n\tSAS.pyplot(plt)\n\nendsubmit;\nquit;\n\n%symdel casSessionExists;"}}

CV - Display Images/README.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# CV - Display Images
2+
3+
## Description
4+
This custom step displays images to the user. The step processes an input image table and displays the images contained in the input table.
5+
6+
## User Interface
7+
#### About Tab:
8+
9+
![alt text for screen readers](./img/About_Tab.png)
10+
11+
#### Parameters Tab:
12+
13+
![alt text for screen readers](./img/Parameters_Tab.png)
14+
15+
## SAS Viya Version Support
16+
17+
Tested on Viya 4, Stable 2024.01
18+
19+
## Requirements
20+
21+
#### Ensure:
22+
23+
- You are connected to CAS before running this step. This custom step runs on data loaded to SAS Cloud Analytics Services (CAS).
24+
25+
- SAS Viya has access to an active Python environment. This custom step requires Python (through proc python) to be enabled inside SAS compute.
26+
27+
- Required Python packages (see section "Python packages") are installed.
28+
29+
### Python packages required
30+
31+
- swat (1.13.3)
32+
- python-DLPy (1.2.1-dev - NOTE: This is a dev version and cannot be directly pip installed. Instead, to access this version, use the command "pip install git+https://github. com/sassoftware/python-dlpy.git")
33+
- matplotlib
34+
35+
Refer documentation link below for package details.
36+
37+
### Parameters
38+
39+
#### Input:
40+
1. Input table name (Required): Select/attach an input table node to this custom step. Provide a valid table name and caslib name of the CAS table containing images which the user would like to view.
41+
42+
2. Number of images to view (Optional): Provide an input value for the number of images to be displayed to the user. By default, the value is set to 3.
43+
44+
3. The data consists of DICOM images (Optional): Choose whether the data contains 3-Dimensional medical DICOM images. By default, the option is set to No.
45+
46+
## Documentation:
47+
1. Documentation on the swat package: https://sassoftware.github.io/python-swat/
48+
49+
2. Documentation on python-dlpy package:
50+
https://github.com/sassoftware/python-dlpy
51+
52+
3. Documentation on SAS callback object and methods: https://go.documentation.sas.com/doc/da/pgmsascdc/default/proc/p0z7ahqmabxu6kn193kdojjhc477.htm
53+
54+
4. This SAS Communities article provides details on the environment variables which facilitate connecting to CAS using the swat package within SAS Studio: https://communities.sas.com/t5/SAS-Communities-Library/Hotwire-your-SWAT-inside-SAS-Studio/ta-p/835956
55+
56+
5. Peter Styliadis provides this helpful post (SAS documentation link contained therein) on how to identify a current active CAS session: https://communities.sas.com/t5/SAS-Viya/Programmatically-detect-an-active-CAS-session/m-p/890914#M1985
57+
58+
## Ideas for future enhancements
59+
- Modify Python routine to create a CAS session using SAS.submit() when there is no existing CAS session. Currently, when there is no CAS session a new one will be created using SWAT. Which means that SAS Compute has no knowledge about the CAS session. Code snippets can be found [here](https://github.com/sassoftware/sas-studio-custom-steps/tree/main/_codegen_snippets/code-samples/Reuse-CAS-session-from-SWAT#alternative-approaches-when-cas-session-does-not-exist).
60+
61+
## Created / contact:
62+
63+
- Neela Vengateshwaran ([email protected])
64+
65+
## Change Log
66+
- Version 1.0 (06AUG2024)
67+
- Initial version

CV - Display Images/img/About_Tab.png

34.9 KB
Loading
8.94 KB
Loading

0 commit comments

Comments
 (0)