diff --git a/CV - Display Images/CV - Display Images.step b/CV - Display Images/CV - Display Images.step new file mode 100644 index 00000000..4531c0e9 --- /dev/null +++ b/CV - Display Images/CV - Display Images.step @@ -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 (Neela.Vengateshwaran@sas.com)\",\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;"}} \ No newline at end of file diff --git a/CV - Display Images/README.md b/CV - Display Images/README.md new file mode 100644 index 00000000..eb1f1355 --- /dev/null +++ b/CV - Display Images/README.md @@ -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 (Neela.Vengateshwaran@sas.com) + +## Change Log +- Version 1.0 (06AUG2024) + - Initial version diff --git a/CV - Display Images/img/About_Tab.png b/CV - Display Images/img/About_Tab.png new file mode 100644 index 00000000..e71e8c54 Binary files /dev/null and b/CV - Display Images/img/About_Tab.png differ diff --git a/CV - Display Images/img/Parameters_Tab.png b/CV - Display Images/img/Parameters_Tab.png new file mode 100644 index 00000000..d4080d5f Binary files /dev/null and b/CV - Display Images/img/Parameters_Tab.png differ