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

New custom step: CV - Display Images #161

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions CV - Display Images/CV - Display Images.step
Original file line number Diff line number Diff line change
@@ -0,0 +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;"}}
64 changes: 64 additions & 0 deletions CV - Display Images/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# CV - Display Images

## Description
This custom step displays images to the user. The step processes an input image table and displays the images contained in the input table.

## User Interface
#### About Tab:

![alt text for screen readers](./img/About_Tab.png)

#### Parameters Tab:

![alt text for screen readers](./img/Parameters_Tab.png)

## SAS Viya Version Support

Tested on Viya 4, Stable 2024.01

## Requirements

#### Ensure:

- You are connected to CAS before running this step. This custom step runs on data loaded to SAS Cloud Analytics Services (CAS).

- SAS Viya has access to an active Python environment. This custom step requires Python (through proc python) to be enabled inside SAS compute.

- Required Python packages (see section "Python packages") are installed.

### Python packages required

- swat (1.13.3)
- 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")
- matplotlib

Refer documentation link below for package details.

### Parameters

#### Input:
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.

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.

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.

## Documentation:
1. Documentation on the swat package: https://sassoftware.github.io/python-swat/

2. Documentation on python-dlpy package:
https://github.com/sassoftware/python-dlpy

3. Documentation on SAS callback object and methods: https://go.documentation.sas.com/doc/da/pgmsascdc/default/proc/p0z7ahqmabxu6kn193kdojjhc477.htm

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

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

## Created / contact:

- Neela Vengateshwaran ([email protected])

## Change Log
- Version 1.0 (06AUG2024)
- Initial version
Binary file added CV - Display Images/img/About_Tab.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added CV - Display Images/img/Parameters_Tab.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.