Skip to content

Commit 9a71979

Browse files
committed
Interoperability and test data
1 parent 1e39882 commit 9a71979

File tree

8 files changed

+611
-0
lines changed

8 files changed

+611
-0
lines changed

isc/py/ens/Operation.cls

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/// Sample operation. Executes Python code and returns requsted variables
2+
Class isc.py.ens.Operation Extends Ens.BusinessOperation
3+
{
4+
5+
Parameter ADAPTER = "isc.py.ens.OutboundAdapter";
6+
7+
Property Adapter As isc.py.ens.OutboundAdapter;
8+
9+
/// This is the default message handler. All request types not declared in the message map are delivered here
10+
Method OnMessage(request As isc.py.ens.Request, Output response As isc.py.ens.Response) As %Status
11+
{
12+
set response = ##class(isc.py.ens.Response).%New()
13+
set variables = $lfs(request.Variables)
14+
quit:'$Listvalid(variables) $$$ERROR($$$AttributeValueMustBeList, "variables")
15+
16+
set variable = $lg(variables, 1)
17+
set value = ..Adapter.Execute(request.Code, variable)
18+
19+
do:variable'="" response.Variables.SetAt(value, variable)
20+
21+
for i=2:1:$ll(variables) {
22+
set variable = $lg(variables, i)
23+
continue:variable=""
24+
set value = ..Adapter.Execute("", variable)
25+
do response.Variables.SetAt(value, variable)
26+
}
27+
28+
quit $$$OK
29+
}
30+
31+
}
32+

isc/py/ens/OutboundAdapter.cls

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
Class isc.py.ens.OutboundAdapter Extends Ens.OutboundAdapter
2+
{
3+
4+
/// Do requred in-process initialization.
5+
/// System-wide initialization: do ##class(isc.py.Callout).Setup()
6+
/// assumed to be done before this point.
7+
Method OnInit() As %Status
8+
{
9+
do ##class(isc.py.Callout).Initialize()
10+
quit $$$OK
11+
}
12+
13+
/// Free Python library
14+
Method OnTearDown() As %Status
15+
{
16+
do ##class(isc.py.Callout).Finalize()
17+
do ##class(isc.py.Callout).Unload()
18+
quit $$$OK
19+
}
20+
21+
/// Main method execute code and return variable.
22+
/// Both arguments are optional.
23+
/// code can be $c(10) or $c(13,10) delimited.
24+
Method Execute(code = "", variable = "") As %String
25+
{
26+
set codeList=$lfs(code, $c(10))
27+
28+
for i=1:1:$ll(codeList)-1 {
29+
do ##class(isc.py.Callout).SimpleString($lg(codeList, i))
30+
}
31+
set result = ##class(isc.py.Callout).SimpleString($lg(codeList, $ll(codeList)), variable)
32+
quit result
33+
}
34+
35+
}
36+

isc/py/ens/ProcessUtils.cls

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/// Utilities for Python PB
2+
Class isc.py.ens.ProcessUtils
3+
{
4+
5+
/// Get value of activity annatation by name
6+
ClassMethod GetAnnotation(name) As %String [ CodeMode = objectgenerator ]
7+
{
8+
set sc = $$$OK
9+
try {
10+
#; Don't run this method on the base class
11+
quit:%compiledclass.Name="isc.py.ens.AbstractBPLProcess"
12+
quit:##class(%Dictionary.CompiledXData).%ExistsId(%class.Name_"||BPLERROR")
13+
14+
#; find XDATA block named BPL
15+
if ##class(%Dictionary.CompiledXData).%ExistsId(%class.Name_"||BPL") {
16+
set index = %compiledclass.XDatas.FindObjectId(%class.Name_"||BPL")
17+
18+
#; get XDATA as stream
19+
set stream = %compiledclass.XDatas.GetAt(index).Data
20+
do stream.Rewind()
21+
22+
set parser=##class(Ens.BPL.Parser).%New()
23+
24+
#; Parse the specified stream and obtain the root of the parse tree,
25+
#; Ens.BPL.Process
26+
#dim process As Ens.BPL.Process
27+
set sc = parser.ParseStream(stream,.process)
28+
quit:$$$ISERR(sc)
29+
30+
#dim activities As Ens.BPL.ActivityList
31+
set activities = process.Sequence.Activities
32+
33+
for i=1:1:activities.Count() {
34+
#dim activity As Ens.BPL.Activity
35+
set activity = activities.GetAt(i)
36+
set annotationText = $$$quote(activity.Annotation)
37+
do:activity.Annotation'="" %code.WriteLine(" quit:name=""" _ activity.Name _ """ " _ annotationText)
38+
}
39+
do %code.WriteLine(" quit """"")
40+
}
41+
} catch ex {
42+
set sc = ex.AsStatus()
43+
}
44+
quit sc
45+
}
46+
47+
}
48+

isc/py/ens/Request.cls

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/// Request to python operation
2+
Class isc.py.ens.Request Extends Ens.Request
3+
{
4+
5+
/// Python code to execute
6+
Property Code As %VarString;
7+
8+
/// Comma-separated list of variables to get in response message
9+
Property Variables As %String;
10+
11+
Storage Default
12+
{
13+
<Data name="RequestDefaultData">
14+
<Subscript>"Request"</Subscript>
15+
<Value name="1">
16+
<Value>Code</Value>
17+
</Value>
18+
<Value name="2">
19+
<Value>Variables</Value>
20+
</Value>
21+
</Data>
22+
<DefaultData>RequestDefaultData</DefaultData>
23+
<Type>%Library.CacheStorage</Type>
24+
}
25+
26+
}
27+

isc/py/ens/Response.cls

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/// Response from Python environment
2+
Class isc.py.ens.Response Extends Ens.Response
3+
{
4+
5+
/// Array of Python variables
6+
Property Variables As array Of %VarString;
7+
8+
Storage Default
9+
{
10+
<Data name="Variables">
11+
<Attribute>Variables</Attribute>
12+
<Structure>subnode</Structure>
13+
<Subscript>"isc.py.ens.Response.Variables"</Subscript>
14+
</Data>
15+
<Type>%Library.CacheStorage</Type>
16+
}
17+
18+
}
19+

isc/py/test/CannibalizationData.cls

Lines changed: 343 additions & 0 deletions
Large diffs are not rendered by default.

isc/py/test/Process.cls

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/// Sample process
2+
Class isc.py.test.Process Extends (Ens.BusinessProcessBPL, isc.py.ens.ProcessUtils)
3+
{
4+
5+
/// BPL Definition
6+
XData BPL [ XMLNamespace = "http://www.intersystems.com/bpl" ]
7+
{
8+
<process language='objectscript' request='Ens.Request' response='Ens.Response' height='2000' width='2000' >
9+
<sequence xend='200' yend='650' >
10+
<call name='Correlation Matrix: Tabular' target='isc.py.ens.Operation' async='1' xpos='200' ypos='250' >
11+
<annotation><![CDATA[import pyodbc
12+
import pandas as pd
13+
cnxn=pyodbc.connect(('DSN=ENSEMBLE(PYTHON);UID=dev;PWD=123'),autocommit=True)
14+
y=1
15+
Data=pd.read_sql('SELECT * FROM isc_py_test.CannibalizationData',cnxn)
16+
Data0=Data.drop(['WEEK'],axis=1)
17+
Data0['BRATWURST']=pd.to_numeric(Data0['BRATWURST'])
18+
Data0['CERVELAS']=pd.to_numeric(Data0['CERVELAS'])
19+
Data0['CHARCUTERIE']=pd.to_numeric(Data0['CHARCUTERIE'])
20+
Data0['DAUERFLEISCHWAREN']=pd.to_numeric(Data0['DAUERFLEISCHWAREN'])
21+
Data0['GEFLUEGEL']=pd.to_numeric(Data0['GEFLUEGEL'])
22+
Data0['GERAEUCHERTES_ZUM_KOCHEN']=pd.to_numeric(Data0['GERAEUCHERTES_ZUM_KOCHEN'])
23+
Data0['HACKFLEISCH']=pd.to_numeric(Data0['HACKFLEISCH'])
24+
Data0['INNEREIEN_DIVERSES']=pd.to_numeric(Data0['INNEREIEN_DIVERSES'])
25+
Data0['KALB']=pd.to_numeric(Data0['KALB'])
26+
Data0['KANINCHEN']=pd.to_numeric(Data0['KANINCHEN'])
27+
Data0['LAMM']=pd.to_numeric(Data0['LAMM'])
28+
Data0['MARINADEN']=pd.to_numeric(Data0['MARINADEN'])
29+
Data0['PASTETEN_TERRINEN_STREICHWURST']=pd.to_numeric(Data0['PASTETEN_TERRINEN_STREICHWURST'])
30+
Data0['PFANNENFERTIGES']=pd.to_numeric(Data0['PFANNENFERTIGES'])
31+
Data0['PFERD']=pd.to_numeric(Data0['PFERD'])
32+
Data0['RIND']=pd.to_numeric(Data0['RIND'])
33+
Data0['SALAMI_ROHWURST_AM_STUECK']=pd.to_numeric(Data0['SALAMI_ROHWURST_AM_STUECK'])
34+
Data0['SCHINKEN']=pd.to_numeric(Data0['SCHINKEN'])
35+
Data0['SCHWEIN']=pd.to_numeric(Data0['SCHWEIN'])
36+
Data0['UEBRIGE_BRUEHWURST_STUECK']=pd.to_numeric(Data0['UEBRIGE_BRUEHWURST_STUECK'])
37+
Data0['WIENERLI_KNACKERLI_FRANKFURTERLI']=pd.to_numeric(Data0['WIENERLI_KNACKERLI_FRANKFURTERLI'])
38+
corrmat=Data0.corr()
39+
corrmat.columns.name='CATEGORY'
40+
//PyRun_SimpleString("import sys
41+
//PyRun_SimpleString("orig_stdout=sys.stdout
42+
//PyRun_SimpleString("f=open('C:/IRIS+Python/IRIS+Python_output_model_001.txt','w')
43+
//PyRun_SimpleString("sys.stdout=f
44+
result=corrmat.to_string()
45+
//PyRun_SimpleString("sys.stdout=orig_stdout
46+
//PyRun_SimpleString("f.close()
47+
cnxn.close()
48+
]]></annotation>
49+
<request type='isc.py.ens.Request' >
50+
<assign property="callrequest.Variables" value="&quot;result&quot;" action="set" />
51+
<assign property="callrequest.Code" value="process.GetAnnotation(&quot;Correlation Matrix: Tabular&quot;)" action="set" />
52+
</request>
53+
<response type='isc.py.ens.Response' />
54+
</call>
55+
<sync name='Wait Correlation Matrix: Tabular' calls='Correlation Matrix: Tabular' type='all' xpos='200' ypos='350' />
56+
<call name='Correlation Matrix: Graph' target='isc.py.ens.Operation' async='1' xpos='200' ypos='450' >
57+
<annotation><![CDATA[import matplotlib
58+
import matplotlib.pyplot as plt
59+
import seaborn as sns
60+
f=plt.figure()
61+
sns.heatmap(corrmat,xticklabels=corrmat.columns,yticklabels=corrmat.columns)
62+
plt.title('Correlation analysis of category sales volumes (by year/month)')
63+
f.savefig(r'C:\InterSystems\Ensemble\mgr\Temp\SHOWCASE004USE02.png')
64+
plt.close(f)]]></annotation>
65+
<request type='isc.py.ens.Request' >
66+
<assign property="callrequest.Code" value="process.GetAnnotation(&quot;Correlation Matrix: Graph&quot;)" action="set" />
67+
</request>
68+
<response type='isc.py.ens.Response' />
69+
</call>
70+
<sync name='Wait Correlation Matrix: Graph' calls='Correlation Matrix: Graph' type='all' xpos='200' ypos='550' />
71+
</sequence>
72+
</process>
73+
}
74+
75+
Storage Default
76+
{
77+
<Type>%Library.CacheStorage</Type>
78+
}
79+
80+
}
81+

isc/py/test/Production.cls

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/// Sample production
2+
Class isc.py.test.Production Extends Ens.Production
3+
{
4+
5+
/// Register callout lib system-wide
6+
ClassMethod OnStart(pTimeStarted As %String) As %Status
7+
{
8+
do ##class(isc.py.Callout).Setup()
9+
quit $$$OK
10+
}
11+
12+
XData ProductionDefinition
13+
{
14+
<Production Name="isc.py.test.Production" TestingEnabled="true" LogGeneralTraceEvents="false">
15+
<Description></Description>
16+
<ActorPoolSize>2</ActorPoolSize>
17+
<Item Name="isc.py.ens.Operation" Category="" ClassName="isc.py.ens.Operation" PoolSize="1" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
18+
</Item>
19+
<Item Name="isc.py.test.Process" Category="" ClassName="isc.py.test.Process" PoolSize="1" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
20+
</Item>
21+
</Production>
22+
}
23+
24+
}
25+

0 commit comments

Comments
 (0)