├── .gitattributes
├── .gitignore
├── .dockerignore
├── docker-compose.yml
├── .github
└── workflows
│ ├── objectscript-quality.yml
│ └── build-push-gcr.yaml
├── irissession.sh
├── Dockerfile
├── .vscode
└── settings.json
├── iris.script
├── src
└── cls
│ ├── BI
│ ├── Model
│ │ ├── KPIs
│ │ │ ├── BPSystolic.cls
│ │ │ ├── BPDiastolic.cls
│ │ │ ├── Years.cls
│ │ │ ├── DemoMDXAutoFilters.cls
│ │ │ ├── DemoCrossjoin.cls
│ │ │ ├── DemoSQL.cls
│ │ │ ├── DemoInteroperability.cls
│ │ │ ├── DemoMDX.cls
│ │ │ ├── DemoTrendLines.cls
│ │ │ ├── PluginDemo.cls
│ │ │ ├── DemoDataChanges.cls
│ │ │ └── BubbleChartDemo.cls
│ │ ├── CompoundCube
│ │ │ ├── CompoundCube.cls
│ │ │ ├── CityRainfall.cls
│ │ │ ├── Doctors.cls
│ │ │ └── Patients.cls
│ │ ├── SubjectAreas
│ │ │ ├── AsthmaPatients.cls
│ │ │ ├── YoungPatients.cls
│ │ │ └── DemoMDX.cls
│ │ ├── SampleListingGroup.cls
│ │ ├── PatientsQuery.cls
│ │ ├── CityCube.cls
│ │ ├── RelCubes
│ │ │ ├── RAllergies.cls
│ │ │ ├── RCities.cls
│ │ │ ├── RCityRainfall.cls
│ │ │ ├── RDoctors.cls
│ │ │ └── RPatients.cls
│ │ ├── PatientsQueryCube.cls
│ │ ├── RainfallCube.cls
│ │ ├── ConnectorCube.cls
│ │ ├── ConnectorExample.cls
│ │ └── PortletDemo
│ │ │ ├── ClockPortlet.cls
│ │ │ └── svgClock.cls
│ ├── Study
│ │ ├── PatientDiagnosis.cls
│ │ ├── PatientDiagnosis1.cls
│ │ ├── PatientDiagnosis2.cls
│ │ ├── PatientAllergy1.cls
│ │ ├── AllergySeverity.cls
│ │ ├── Allergen.cls
│ │ ├── PatientAllergy.cls
│ │ ├── City.cls
│ │ ├── Profession.cls
│ │ ├── CityRainfall.cls
│ │ ├── Diagnosis.cls
│ │ ├── PatientDetails.cls
│ │ ├── PatientSet2.cls
│ │ ├── PatientEncounter.cls
│ │ └── Doctor.cls
│ ├── Utils
│ │ └── MDXAutoFiltersKPI.cls
│ └── APISamples.cls
│ └── HoleFoods
│ ├── SubjectAreaAsia.cls
│ ├── KPIYears.cls
│ ├── Region.cls
│ ├── CombinedCube.cls
│ ├── Country.cls
│ ├── Product.cls
│ ├── KPIAction.cls
│ ├── Outlet.cls
│ ├── BudgetCube.cls
│ ├── KPISQL.cls
│ ├── Transaction.cls
│ ├── KPISalesVsTarget.cls
│ ├── KPICFO.cls
│ └── Cube.cls
├── module.xml
├── LICENSE
├── Installer.cls
├── dev.md
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.sh eol=lf
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | ISC
3 |
4 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | **/.DS_Store
2 | .vscode/
3 | .github/
4 | buildsample/
5 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.6'
2 | services:
3 | iris:
4 | build:
5 | context: .
6 | dockerfile: ${DOCKERFILE:-Dockerfile}
7 | command: --check-caps false
8 | restart: always
9 | ports:
10 | - 1972
11 | - 52773
12 | - 53773
13 | volumes:
14 | - ~/iris.key:/usr/irissys/mgr/iris.key
15 | - ./:/irisdev/app
16 |
--------------------------------------------------------------------------------
/.github/workflows/objectscript-quality.yml:
--------------------------------------------------------------------------------
1 | name: objectscriptquality
2 | on: push
3 |
4 | jobs:
5 | linux:
6 | name: Linux build
7 | runs-on: ubuntu-latest
8 |
9 | steps:
10 | - name: Execute ObjectScript Quality Analysis
11 | run: wget https://raw.githubusercontent.com/litesolutions/objectscriptquality-jenkins-integration/master/iris-community-hook.sh && sh ./iris-community-hook.sh
12 |
13 |
--------------------------------------------------------------------------------
/irissession.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | iris start $ISC_PACKAGE_INSTANCENAME quietly
4 |
5 | cat << EOF | iris session $ISC_PACKAGE_INSTANCENAME -U %SYS
6 | do ##class(%SYSTEM.Process).CurrentDirectory("$PWD")
7 | $@
8 | if '\$Get(sc) do ##class(%SYSTEM.Process).Terminate(, 1)
9 | zn "%SYS"
10 | do ##class(SYS.Container).QuiesceForBundling()
11 | Do ##class(Security.Users).UnExpireUserPasswords("*")
12 | halt
13 | EOF
14 |
15 | exit=$?
16 |
17 | iris stop $ISC_PACKAGE_INSTANCENAME quietly
18 |
19 | exit $exit
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG IMAGE=intersystemsdc/iris-community:latest
2 | FROM $IMAGE
3 |
4 | USER root
5 | WORKDIR /opt/irisapp
6 | RUN chown ${ISC_PACKAGE_MGRUSER}:${ISC_PACKAGE_IRISGROUP} /opt/irisapp
7 |
8 | USER ${ISC_PACKAGE_MGRUSER}
9 |
10 | # copy files
11 | COPY Installer.cls .
12 | COPY src src
13 | COPY module.xml .
14 | COPY iris.script /tmp/iris.script
15 |
16 | # run iris and script
17 | RUN iris start IRIS \
18 | && iris session IRIS < /tmp/iris.script \
19 | && iris stop IRIS quietly
20 |
21 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.associations": {
3 |
4 | "Dockerfile*": "dockerfile",
5 | "iris.script": "objectscript"
6 | },
7 | "objectscript.conn" :{
8 | "ns": "IRISAPP",
9 | "active": false,
10 | "username": "_SYSTEM",
11 | "docker-compose": {
12 | "service": "iris",
13 | "internalPort": 52773
14 | },
15 | "links": {
16 | "SAMPLES BI in ZEN": "http://localhost:${port}/csp/irisapp/_DeepSee.UserPortal.DashboardViewer.zen"
17 | }
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/iris.script:
--------------------------------------------------------------------------------
1 | ; add a bit of standard docker comfort
2 | zn "%SYS"
3 | do ##class(Security.Users).UnExpireUserPasswords("*")
4 | ;; just a proposal
5 | ;; set user=##class(Security.Users).%OpenId("unknownuser")
6 | ;; do user.Roles.Insert("%All")
7 |
8 | ; run installer to create namespace
9 | do $SYSTEM.OBJ.Load("/opt/irisapp/Installer.cls", "ck")
10 | set sc = ##class(App.Installer).setup()
11 |
12 | zn "IRISAPP"
13 | zpm "install isc-dev"
14 | do ##class(dev.code).workdir("/irisdev/app/src")
15 | do EnableDeepSee^%SYS.cspServer("/csp/irisapp/")
16 | zpm "load /opt/irisapp/ -v -Dfolder=irisapp"
17 |
18 | halt
19 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/KPIs/BPSystolic.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// 1-row hardcoded KPI for use in demonstrating ranges and thresholds in a *meter*.
3 | Class BI.Model.KPIs.BPSystolic Extends %DeepSee.KPI
4 | {
5 |
6 | XData KPI [ XMLNamespace = "http://www.intersystems.com/deepsee/kpi" ]
7 | {
8 |
11 |
12 |
13 |
14 | }
15 |
16 | Method %OnLoadKPI() As %Status
17 | {
18 | set ..%rangeLower=70
19 | set ..%thresholdLower=90
20 | set ..%thresholdUpper=120
21 | set ..%rangeUpper=190
22 | quit $$$OK
23 | }
24 |
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/KPIs/BPDiastolic.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// 1-row hardcoded KPI for use in demonstrating ranges and thresholds in a *meter*.
3 | Class BI.Model.KPIs.BPDiastolic Extends %DeepSee.KPI
4 | {
5 |
6 | XData KPI [ XMLNamespace = "http://www.intersystems.com/deepsee/kpi" ]
7 | {
8 |
11 |
12 |
13 |
14 | }
15 |
16 | Method %OnLoadKPI() As %Status
17 | {
18 | set ..%rangeLower=40
19 | set ..%thresholdLower=60
20 | set ..%thresholdUpper=80
21 | set ..%rangeUpper=100
22 | quit $$$OK
23 | }
24 |
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/KPIs/Years.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This KPI class provides the list of values for the
3 | /// Years pivot variable of the Patients cube.
4 | Class BI.Model.KPIs.Years Extends %DeepSee.KPI
5 | {
6 |
7 | Parameter DOMAIN = "PATIENTSAMPLE";
8 |
9 | XData KPI [ XMLNamespace = "http://www.intersystems.com/deepsee/kpi" ]
10 | {
11 |
16 |
17 |
20 |
21 |
22 | }
23 |
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/src/cls/HoleFoods/SubjectAreaAsia.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// Example of a DeepSee Subject Area.
3 | /// This limits the data from the HOLEFOODS cube to data from ASIA only.
4 | Class HoleFoods.SubjectAreaAsia Extends %DeepSee.SubjectArea [ DependsOn = HoleFoods.Cube, ProcedureBlock ]
5 | {
6 |
7 | Parameter DOMAIN;
8 |
9 | /// SubjectArea definition from Architect.
10 | XData SubjectArea [ XMLNamespace = "http://www.intersystems.com/deepsee/subjectarea" ]
11 | {
12 |
13 |
14 | }
15 |
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/src/cls/HoleFoods/KPIYears.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This KPI class provides the list of values for the
3 | /// Years pivot variable of the HoleFoods cube.
4 | Class HoleFoods.KPIYears Extends %DeepSee.KPI
5 | {
6 |
7 | Parameter DOMAIN = "PATIENTSAMPLE";
8 |
9 | XData KPI [ XMLNamespace = "http://www.intersystems.com/deepsee/kpi" ]
10 | {
11 |
16 |
17 |
20 |
21 |
22 | }
23 |
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/CompoundCube/CompoundCube.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class defines a compound cube.
3 | /// To view the cube definition, open this class in Studio.
4 | Class BI.Model.CompoundCube.CompoundCube Extends %DeepSee.SubjectArea [ DependsOn = (BI.Model.CompoundCube.Patients, BI.Model.CompoundCube.Doctors, BI.Model.CompoundCube.CityRainfall) ]
5 | {
6 |
7 | /// This XData definition defines the SubjectArea.
8 | XData SubjectArea [ XMLNamespace = "http://www.intersystems.com/deepsee/subjectarea" ]
9 | {
10 |
12 |
13 | }
14 |
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/SubjectAreas/AsthmaPatients.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is for use with InterSystems IRIS BI.
3 | /// It contains a subject area based on the patients cube (BI.Model.PatientsCube).
4 | /// To view the subject area definition, open this class in Studio.
5 | ///
6 | Class BI.Model.SubjectAreas.AsthmaPatients Extends %DeepSee.SubjectArea [ DependsOn = BI.Model.PatientsCube ]
7 | {
8 |
9 | /// This XData definition defines the SubjectArea.
10 | XData SubjectArea [ XMLNamespace = "http://www.intersystems.com/deepsee/subjectarea" ]
11 | {
12 |
15 |
16 | }
17 |
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/SubjectAreas/YoungPatients.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is for use with InterSystems IRIS BI.
3 | /// It contains a subject area based on the patients cube (BI.Model.PatientsCube).
4 | /// To view the subject area definition, open this class in Studio.
5 | ///
6 | Class BI.Model.SubjectAreas.YoungPatients Extends %DeepSee.SubjectArea [ DependsOn = BI.Model.PatientsCube ]
7 | {
8 |
9 | /// This XData definition defines the SubjectArea.
10 | XData SubjectArea [ XMLNamespace = "http://www.intersystems.com/deepsee/subjectarea" ]
11 | {
12 |
15 |
16 | }
17 |
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/src/cls/HoleFoods/Region.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This specifies a geographic region within the HoleFoods demo.
3 | Class HoleFoods.Region Extends %Persistent
4 | {
5 |
6 | /// Name of this region.
7 | Property Name As %String(MAXLEN = 80);
8 |
9 | Storage Default
10 | {
11 |
12 |
13 | %%CLASSNAME
14 |
15 |
16 | Name
17 |
18 |
19 | ^HoleFoods.RegionD
20 | RegionDefaultData
21 | ^HoleFoods.RegionD
22 | ^HoleFoods.RegionI
23 | ^HoleFoods.RegionS
24 | %Storage.Persistent
25 | }
26 |
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/src/cls/BI/Study/PatientDiagnosis.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is part of the BI Patients sample, whose purpose is to provide
3 | /// sample data for use with InterSystems IRIS BI.
4 | /// See the comments for the Diagnoses property in BI.Study.Patient.
5 | Class BI.Study.PatientDiagnosis Extends %SerialObject
6 | {
7 |
8 | Property DiagnosisCode As %String;
9 |
10 | Property DiagnosedBy As BI.Study.Doctor;
11 |
12 | Storage Default
13 | {
14 |
15 |
16 | DiagnosisCode
17 |
18 |
19 | DiagnosedBy
20 |
21 |
22 | PatientDiagnosisState
23 | ^BI.Study.PatientDiagnosisS
24 | %Storage.Serial
25 | }
26 |
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/KPIs/DemoMDXAutoFilters.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | Class BI.Model.KPIs.DemoMDXAutoFilters Extends BI.Utils.MDXAutoFiltersKPI
3 | {
4 |
5 | Parameter CUBE = "PATIENTS";
6 |
7 | Parameter DOMAIN = "PATIENTSAMPLE";
8 |
9 | XData KPI [ XMLNamespace = "http://www.intersystems.com/deepsee/kpi" ]
10 | {
11 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | }
21 |
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/module.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | samples-bi
6 | 1.0.5
7 | Provides sample data for use with InterSystems IRIS Business Intelligence, as well as fully developed sample BI models and dashboards.
8 | module
9 | src
10 |
11 |
12 |
13 |
14 |
15 | ${namespace}
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/cls/HoleFoods/CombinedCube.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// Sample of a DeepSee compound cube.
3 | /// This combine the HoleFoods Sales data with the Holefoods budget data into one model.
4 | Class HoleFoods.CombinedCube Extends %DeepSee.SubjectArea [ DependsOn = (HoleFoods.Cube, HoleFoods.BudgetCube), ProcedureBlock ]
5 | {
6 |
7 | Parameter DOMAIN;
8 |
9 | /// SubjectArea definition from Architect.
10 | XData SubjectArea [ XMLNamespace = "http://www.intersystems.com/deepsee/subjectarea" ]
11 | {
12 |
13 |
14 |
15 |
16 |
17 | }
18 |
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/src/cls/HoleFoods/Country.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This specifies the country within the HoleFoods demo.
3 | Class HoleFoods.Country Extends %Persistent
4 | {
5 |
6 | /// Region in which this country is located.
7 | Property Region As Region;
8 |
9 | /// Name of this country.
10 | Property Name As %String(MAXLEN = 90);
11 |
12 | Storage Default
13 | {
14 |
15 |
16 | %%CLASSNAME
17 |
18 |
19 | Region
20 |
21 |
22 | Name
23 |
24 |
25 | ^HoleFoods.CountryD
26 | CountryDefaultData
27 | ^HoleFoods.CountryD
28 | ^HoleFoods.CountryI
29 | ^HoleFoods.CountryS
30 | %Storage.Persistent
31 | }
32 |
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 InterSystems Corporation
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/cls/HoleFoods/Product.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This represents a Product within the HoleFoods demo.
3 | Class HoleFoods.Product Extends %Persistent
4 | {
5 |
6 | Index KEY On SKU [ IdKey ];
7 |
8 | /// Category of this product.
9 | Property Category As %String(MAXLEN = 100);
10 |
11 | /// Name of this product.
12 | Property Name As %String(MAXLEN = 120);
13 |
14 | /// SKU for this product.
15 | Property SKU As %String(MAXLEN = 22);
16 |
17 | /// List price for this product.
18 | Property Price As %Numeric(MINVAL = 0);
19 |
20 | Storage Default
21 | {
22 |
23 |
24 | %%CLASSNAME
25 |
26 |
27 | Category
28 |
29 |
30 | Name
31 |
32 |
33 | Price
34 |
35 |
36 | ^HoleFoods.ProductD
37 | ProductDefaultData
38 | ^HoleFoods.ProductD
39 | ^HoleFoods.ProductI
40 | ^HoleFoods.ProductS
41 | %Storage.Persistent
42 | }
43 |
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/src/cls/HoleFoods/KPIAction.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// KPI class used to supply Actions for the HOLEFOODS cube.
3 | /// This is a demonstration and does not actually do anything!
4 | Class HoleFoods.KPIAction Extends %DeepSee.KPI
5 | {
6 |
7 | /// This XData definition defines the KPI.
8 | XData KPI [ XMLNamespace = "http://www.intersystems.com/deepsee/kpi" ]
9 | {
10 |
13 |
14 |
15 |
16 |
17 |
18 | }
19 |
20 | /// This callback is invoked from a dashboard when an action defined by this dashboard is invoked.
21 | ClassMethod %OnDashboardAction(pAction As %String, pContext As %ZEN.proxyObject) As %Status
22 | {
23 | // pAction is the name of the action (as defined in the XML list).
24 | // pContext contains information from the client
25 | // and can be used to return information.
26 |
27 | // Value associated with current item in widget.
28 | set tSelectedValue = pContext.currValue
29 |
30 | if (pAction="ActionA") {
31 | // Go to a new page
32 | set pContext.command = "navigate:http://www.intersystems.com"
33 | }
34 |
35 | quit $$$OK
36 | }
37 |
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/src/cls/BI/Study/PatientDiagnosis1.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is part of the BI Patients sample, whose purpose is to provide
3 | /// sample data for use with InterSystems IRIS BI.
4 | /// See the comments for the Diagnoses property in BI.Study.Patient.
5 | /// This table is populated only if you use the D option when running the
6 | /// GenerateData() method in BI.Populate.
7 | Class BI.Study.PatientDiagnosis1 Extends %Persistent
8 | {
9 |
10 | Relationship Patient As BI.Study.Patient [ Cardinality = parent, Inverse = DiagnosesAsChildren ];
11 |
12 | Property DiagnosisCode As %String;
13 |
14 | Property DiagnosedBy As BI.Study.Doctor;
15 |
16 | Index PatientIndex On Patient;
17 |
18 | Storage Default
19 | {
20 |
21 |
22 | %%CLASSNAME
23 |
24 |
25 | DiagnosisCode
26 |
27 |
28 | DiagnosedBy
29 |
30 |
31 | {%%PARENT}("DiagnosesAsChildren")
32 | PatientDiagnosis1DefaultData
33 | ^BI.Study.PatientC("DiagnosesAsChildren")
34 | ^BI.Study.PatientDiagnosis1I
35 | ^BI.Study.PatientDiagnosis1S
36 | %Storage.Persistent
37 | }
38 |
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/src/cls/BI/Study/PatientDiagnosis2.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is part of the BI Patients sample, whose purpose is to provide
3 | /// sample data for use with InterSystems IRIS BI.
4 | /// See the comments for the Diagnoses property in BI.Study.Patient.
5 | /// This table is populated only if you use the D option when running the
6 | /// GenerateData() method in BI.Populate.
7 | Class BI.Study.PatientDiagnosis2 Extends %Persistent
8 | {
9 |
10 | Relationship Patient As BI.Study.Patient [ Cardinality = one, Inverse = DiagnosesAsMany ];
11 |
12 | Property DiagnosisCode As %String;
13 |
14 | Property DiagnosedBy As BI.Study.Doctor;
15 |
16 | Index PatientIndex On Patient;
17 |
18 | Storage Default
19 | {
20 |
21 |
22 | %%CLASSNAME
23 |
24 |
25 | Patient
26 |
27 |
28 | DiagnosisCode
29 |
30 |
31 | DiagnosedBy
32 |
33 |
34 | ^BI.Study.PatientDiagnosis2D
35 | PatientDiagnosis2DefaultData
36 | ^BI.Study.PatientDiagnosis2D
37 | ^BI.Study.PatientDiagnosis2I
38 | ^BI.Study.PatientDiagnosis2S
39 | %Storage.Persistent
40 | }
41 |
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/src/cls/HoleFoods/Outlet.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This represents a Sales Outlet for the HoleFoods demo.
3 | Class HoleFoods.Outlet Extends %Persistent
4 | {
5 |
6 | /// Country in which this city is located.
7 | Property Country As Country;
8 |
9 | /// City name of this location.
10 | Property City As %String(MAXLEN = 100);
11 |
12 | /// Population of this city.
13 | Property Population As %Integer(MINVAL = 0);
14 |
15 | /// Type of outlet: "retail", "web", etc.
16 | Property Type As %String(MAXLEN = 50);
17 |
18 | /// Latitude of this location.
19 | Property Latitude As %Double;
20 |
21 | /// Longitude of this location.
22 | Property Longitude As %Double;
23 |
24 | Storage Default
25 | {
26 |
27 |
28 | %%CLASSNAME
29 |
30 |
31 | Country
32 |
33 |
34 | City
35 |
36 |
37 | Population
38 |
39 |
40 | Type
41 |
42 |
43 | Latitude
44 |
45 |
46 | Longitude
47 |
48 |
49 | ^HoleFoods.OutletD
50 | OutletDefaultData
51 | ^HoleFoods.OutletD
52 | ^HoleFoods.OutletI
53 | ^HoleFoods.OutletS
54 | %Storage.Persistent
55 | }
56 |
57 | }
58 |
59 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/SampleListingGroup.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class defines a listing group for the BI Patients sample.
3 | /// To see the definition of this listing group, use the BI > Tools > Listing Group Manager menu option
4 | /// or open this class in Studio.
5 | Class BI.Model.SampleListingGroup Extends %DeepSee.ListingGroupDefinition [ DependsOn = (BI.Model.PatientsCube, BI.Model.RelCubes.RPatients, BI.Model.SubjectAreas.AsthmaPatients, BI.Model.SubjectAreas.YoungPatients), Not ProcedureBlock ]
6 | {
7 |
8 | /// Need this because we have another listing group class with the same short class name.
9 | /// We use the XMLTYPE parameter to make sure these two classes project differently to XML.
10 | Parameter XMLTYPE = "PatientsSampleListingGroup";
11 |
12 | Parameter DOMAIN = "PATIENTSAMPLE";
13 |
14 | XData Listings [ XMLNamespace = "http://www.intersystems.com/deepsee/listinggroup" ]
15 | {
16 |
17 |
18 |
19 |
20 | }
21 |
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/PatientsQuery.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This Data Connector uses a UNION query that combines the main patient table with
3 | /// the "extra" patient set (BI.Study.PatientSet2).
4 | Class BI.Model.PatientsQuery Extends %DeepSee.DataConnector
5 | {
6 |
7 | XData SourceQuery [ XMLNamespace = "http://www.intersystems.com/deepsee/connector/query" ]
8 | {
9 |
10 | SELECT %ID,PatientID,Gender,Age,HomeCity->Name AS "HomeCity",
11 | PatientGroup,TestScore From BI_Study.Patient
12 | UNION
13 | SELECT %ID,PatientID,Gender,Age,HomeCity,
14 | PatientGroup,TestScore From BI_Study.PatientSet2
15 |
16 | }
17 |
18 | /// This XData definition defines the output of this connector.
19 | XData Output [ XMLNamespace = "http://www.intersystems.com/deepsee/connector/output" ]
20 | {
21 |
22 |
24 |
25 |
27 |
28 |
30 |
31 |
33 |
34 |
36 |
37 |
39 |
40 |
42 |
43 |
44 | }
45 |
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/src/cls/HoleFoods/BudgetCube.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This is a sample DeepSee data model.
3 | /// This represents budget values for the HoleFoods model.
4 | /// Refer to the HoleFoods.BudgetCube class for more details.
5 | Class HoleFoods.BudgetCube Extends %DeepSee.CubeDefinition [ DependsOn = (HoleFoods.Cube, HoleFoods.Transaction, HoleFoods.KPIAction) ]
6 | {
7 |
8 | Parameter DOMAIN = "HOLEFOODS";
9 |
10 | /// This xml document defines the HoleFoods model.
11 | XData Cube [ XMLNamespace = "http://www.intersystems.com/deepsee" ]
12 | {
13 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | }
35 |
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/CityCube.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class defines a cube based on BI.Study.City.
3 | /// Where applicable, the dimension, hierarchy, and level definitions here use the same names
4 | /// as in the Patients cube, so that these cubes can be used together.
5 | ///
6 | Class BI.Model.CityCube Extends %DeepSee.CubeDefinition [ DependsOn = BI.Study.City ]
7 | {
8 |
9 | Parameter DOMAIN = "PATIENTSAMPLE";
10 |
11 | XData Cube [ XMLNamespace = "http://www.intersystems.com/deepsee" ]
12 | {
13 |
19 |
20 |
23 |
24 |
27 |
28 |
31 |
32 |
34 |
35 |
37 |
39 |
41 |
43 |
44 |
45 |
46 |
47 |
49 |
50 |
51 |
52 | }
53 |
54 | }
55 |
56 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/SubjectAreas/DemoMDX.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is for use with InterSystems IRIS BI.
3 | /// It contains a subject area based on the patients cube (BI.Model.PatientsCube).
4 | /// To view the subject area definition, open this class in Studio.
5 | ///
6 | Class BI.Model.SubjectAreas.DemoMDX Extends %DeepSee.SubjectArea [ DependsOn = BI.Model.PatientsCube ]
7 | {
8 |
9 | /// This XData definition defines the SubjectArea.
10 | XData SubjectArea [ XMLNamespace = "http://www.intersystems.com/deepsee/subjectarea" ]
11 | {
12 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | }
54 |
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/Installer.cls:
--------------------------------------------------------------------------------
1 | Class App.Installer
2 | {
3 |
4 | XData setup
5 | {
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
27 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | }
40 |
41 | ClassMethod setup(ByRef pVars, pLogLevel As %Integer = 3, pInstaller As %Installer.Installer, pLogger As %Installer.AbstractLogger) As %Status [ CodeMode = objectgenerator, Internal ]
42 | {
43 | #; Let XGL document generate code for this method.
44 | Quit ##class(%Installer.Manifest).%Generate(%compiledclass, %code, "setup")
45 | }
46 |
47 | ClassMethod SetDispatchClass(pApp As %String, pClass As %String) As %Status
48 | {
49 | New $Namespace
50 | Set $Namespace = "%SYS"
51 | Set tSC = ##class(Security.Applications).Get(pApp, .webProperties)
52 | If $$$ISERR(tSC) {
53 | Quit tSC
54 | }
55 |
56 | Set webProperties("DispatchClass") = pClass
57 | Set tSC = ##class(Security.Applications).Modify(pApp, .webProperties)
58 | Quit tSC
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/RelCubes/RAllergies.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is for use with InterSystems IRIS BI.
3 | /// It contains a cube based on BI.Study.PatientAllergy1. To view the cube definition, open
4 | /// this class in Studio or the BI Architect.
5 | /// The RelatedCubes/* cubes (like this one) use cube-to-cube relationships.
6 | Class BI.Model.RelCubes.RAllergies Extends %DeepSee.CubeDefinition [ DependsOn = (BI.Study.PatientAllergy1, BI.Model.RelCubes.RPatients), ProcedureBlock ]
7 | {
8 |
9 | Parameter DOMAIN = "PATIENTSAMPLE";
10 |
11 | XData Cube [ XMLNamespace = "http://www.intersystems.com/deepsee" ]
12 | {
13 |
17 |
22 |
23 |
24 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | }
40 |
41 | }
42 |
43 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/RelCubes/RCities.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is for use with InterSystems IRIS BI.
3 | /// It contains a cube based on BI.Study.City. To view the cube definition, open
4 | /// this class in Studio or the BI Architect.
5 | /// The RelatedCubes/* cubes (like this one) use cube-to-cube relationships.
6 | Class BI.Model.RelCubes.RCities Extends %DeepSee.CubeDefinition [ DependsOn = BI.Study.City ]
7 | {
8 |
9 | Parameter DOMAIN = "PATIENTSAMPLE";
10 |
11 | XData Cube [ XMLNamespace = "http://www.intersystems.com/deepsee" ]
12 | {
13 |
18 |
19 |
24 |
25 |
26 |
30 |
31 |
33 |
35 |
37 |
39 |
40 |
41 |
42 |
43 |
47 |
48 |
52 |
53 |
55 |
56 |
57 |
58 | }
59 |
60 | }
61 |
62 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/RelCubes/RCityRainfall.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is for use with InterSystems IRIS BI.
3 | /// It contains a cube based on BI.Study.CityRainfall To view the cube definition, open
4 | /// this class in Studio or the BI Architect.
5 | /// The RelatedCubes/* cubes (like this one) use cube-to-cube relationships.
6 | Class BI.Model.RelCubes.RCityRainfall Extends %DeepSee.CubeDefinition [ DependsOn = (BI.Study.CityRainfall, BI.Model.RelCubes.RCities) ]
7 | {
8 |
9 | XData Cube [ XMLNamespace = "http://www.intersystems.com/deepsee" ]
10 | {
11 |
17 |
18 |
24 |
25 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
41 |
42 |
46 |
47 |
49 |
50 |
51 |
52 | }
53 |
54 | }
55 |
56 |
--------------------------------------------------------------------------------
/src/cls/BI/Study/PatientAllergy1.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is part of the BI Patients sample, whose purpose is to provide
3 | /// sample data for use with InterSystems IRIS BI.
4 | /// An allergy has multiple pieces of information,
5 | /// which you can use separately or in combination to create dimensions, depending
6 | /// on what you want to see.
7 | Class BI.Study.PatientAllergy1 Extends %Persistent
8 | {
9 |
10 | /// Patient who has this allergy
11 | Property Patient As BI.Study.Patient;
12 |
13 | /// A substance to which the patient is allergic.
14 | Property Allergen As BI.Study.Allergen;
15 |
16 | /// Severity of this allergic reaction.
17 | Property Severity As BI.Study.AllergySeverity;
18 |
19 | /// Doctor who recorded this allergic reaction.
20 | Property DiagnosedBy As BI.Study.Doctor;
21 |
22 | ClassMethod CreateOne(patient As BI.Study.Patient, allergen As BI.Study.Allergen = "", severity As BI.Study.AllergySeverity = "", diagnosedBy As BI.Study.Doctor = "") As %Status
23 | {
24 | set new=..%New()
25 | set new.Patient=patient
26 | if (allergen'="") {
27 | set new.Allergen=allergen
28 | }
29 | if (severity'="") {
30 | set new.Severity=severity
31 | }
32 | if (diagnosedBy'="") {
33 | set new.DiagnosedBy=diagnosedBy
34 | }
35 | set status=new.%Save()
36 | quit status
37 | }
38 |
39 | Storage Default
40 | {
41 |
42 |
43 | %%CLASSNAME
44 |
45 |
46 | Patient
47 |
48 |
49 | Allergen
50 |
51 |
52 | Severity
53 |
54 |
55 | DiagnosedBy
56 |
57 |
58 | ^BI.Study.PatientAllergy1D
59 | PatientAllergy1DefaultData
60 | ^BI.Study.PatientAllergy1D
61 | ^BI.Study.PatientAllergy1I
62 | ^BI.Study.PatientAllergy1S
63 | %Storage.Persistent
64 | }
65 |
66 | }
67 |
68 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/KPIs/DemoCrossjoin.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This KPI demonstrates how to use an MDX crossjoin query in a KPI.
3 | ///
4 | Class BI.Model.KPIs.DemoCrossjoin Extends %DeepSee.KPI
5 | {
6 |
7 | Parameter DOMAIN = "PATIENTSAMPLE";
8 |
9 | XData KPI [ XMLNamespace = "http://www.intersystems.com/deepsee/kpi" ]
10 | {
11 |
12 |
13 |
14 |
15 |
16 |
17 | }
18 |
19 | Method %OnExecute() As %Status
20 | {
21 | set tSC = $$$OK
22 | try
23 | {
24 | set MDX = "SELECT {[Measures].[%COUNT],[Measures].[Avg Test Score],"
25 | _"[Measures].[Avg Allergy Count]} ON 0,"
26 | _"NONEMPTYCROSSJOIN([AgeD].[Age Group].Members,[PatGrpD].[Patient Group].Members) ON 1 "
27 | _"FROM [Patients]"
28 |
29 | // Create a result set from the query
30 | set dsRS=##class(%DeepSee.ResultSet).%New()
31 | set status = dsRS.%PrepareMDX(MDX)
32 | set status = dsRS.%Execute()
33 |
34 | // Get the number of rows and columns
35 | set rowCount = dsRS.%GetRowCount()
36 | set colCount = dsRS.%GetColumnCount()
37 |
38 | set ..%seriesCount=rowCount
39 |
40 | // Iterate through rows
41 | for rows = 1:1:..%seriesCount
42 | {
43 | // Row dimensions are stored as labels. The second parameter is 2 for rows (columns would be 1)
44 | do dsRS.%GetOrdinalLabel(.label,2,rows)
45 |
46 | // Fetch the two labels and concatenate them to create name of series
47 | set ..%seriesNames(rows)=label(2)_" / "_label(1)
48 |
49 | // Iterate through the columns
50 | for col = 1:1:colCount
51 | {
52 | // Get value in cell
53 | set tValue= dsRS.%GetOrdinalValue(col,rows)
54 |
55 | // The measures can be taken out of the cells in the ResultSet
56 | Set:col=1 ..%data(rows,"Patient Count") = tValue
57 | Set:col=2 ..%data(rows,"Avg Test Score") = tValue
58 | Set:col=3 ..%data(rows,"Avg Allergy Count") = tValue
59 | }
60 | }
61 | }
62 | catch(ex) {
63 | Set tSC = ex.AsStatus()
64 | }
65 | quit tSC
66 | }
67 |
68 | }
69 |
70 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/KPIs/DemoSQL.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This KPI class uses an SQL query and defines one filter.
3 | Class BI.Model.KPIs.DemoSQL Extends %DeepSee.KPI
4 | {
5 |
6 | Parameter DOMAIN = "PATIENTSAMPLE";
7 |
8 | XData KPI [ XMLNamespace = "http://www.intersystems.com/deepsee/kpi" ]
9 | {
10 |
13 |
14 |
17 |
18 |
21 |
22 |
25 |
26 |
27 | }
28 |
29 | /// This callback defines the basic SQL query and also checks for the current values
30 | /// in the filter. The callback adds an SQL WHERE clause with one of the following forms,
31 | /// depending on the user's selections:
32 | /// WHERE HomeCity->PostalCode = zip_code_selected_by_user
33 | /// WHERE HomeCity->PostalCode IN (zip_code_1,zip_code_2,...)
34 | /// WHERE HomeCity->PostalCode <> zip_code_selected_by_user
35 | /// WHERE HomeCity->PostalCode NOT IN (zip_code_1,zip_code_2,...)
36 | Method %OnGetSQL(ByRef pSQL As %String) As %Status
37 | {
38 | // This is the start of the SQL query for this KPI
39 | set pSQL = "SELECT HomeCity->Name, Count(*),AVG(Age) FROM BI_Study.Patient "
40 |
41 | set where = ""
42 |
43 | // Look at %filterValues to see if a filter has been applied to this KPI instance
44 | if $IsObject(..%filterValues) {
45 | if (..%filterValues.ZipCode'="")
46 | {
47 | // Call utility method that returns filter data in convenient format
48 | set sqlstring=..%GetSQLForFilter("HomeCity->PostalCode","ZipCode")
49 | set where = "WHERE "_sqlstring
50 |
51 | // Old version -- this works but only if you disable multiselect for this fitler
52 | // set where = "WHERE HomeCity->PostalCode = '" _ ..%filterValues.ZipCode _ "' "
53 | }
54 | }
55 |
56 | set groupby="GROUP BY HomeCity "
57 | set orderby="ORDER BY HomeCity "
58 | // assemble the SQL statement
59 | set pSQL=pSQL_where_groupby_orderby
60 | quit $$$OK
61 | }
62 |
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/KPIs/DemoInteroperability.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | Class BI.Model.KPIs.DemoInteroperability Extends BI.Utils.MDXAutoFiltersKPI
3 | {
4 |
5 | Parameter CUBE = "PATIENTS";
6 |
7 | Parameter DOMAIN = "PATIENTSAMPLE";
8 |
9 | XData KPI [ XMLNamespace = "http://www.intersystems.com/deepsee/kpi" ]
10 | {
11 |
13 |
14 |
15 |
16 |
17 |
18 | }
19 |
20 | Method %OnGetMDX(ByRef pMDX As %String) As %Status
21 | {
22 | set yaxis=", NON EMPTY [profd].[h1].[profession].MEMBERS ON 1"
23 | // Check custom filter value
24 | if (..%filterValues."Yaxis"'="") {
25 | set yaxis=", NON EMPTY "_..%filterValues.Yaxis_".MEMBERS ON 1"
26 | }
27 | set pMDX="SELECT {MEASURES.[%COUNT],MEASURES.[avg age]} on 0"_yaxis_" FROM "_..#CUBE
28 |
29 | /// Append a %FILTER clause to handle any other filter values
30 | Set pMDX = pMDX _ ..FilterBuilder()
31 | Quit $$$OK
32 | }
33 |
34 | /// Implementation.
35 | ClassMethod %OnGetFilterList(ByRef pFilters As %List, pDataSourceName As %String = "") As %Status
36 | {
37 | // Call method in superclass so we can get filters of the associated cube
38 | set tSC=##super(.pFilters,pDataSourceName)
39 | quit:$$$ISERR(tSC) tSC
40 |
41 | // Update pFilters array to include the custom filter
42 | set pFilters($i(pFilters)) = $lb("Yaxis","Yaxis",,0)
43 |
44 | quit $$$OK
45 | }
46 |
47 | /// Implementation.
48 | ClassMethod %OnGetFilterMembers(pFilter As %String, Output pMembers As %List, pSearchKey As %String = "", pDataSourceName As %String = "") As %Status
49 | {
50 | set pMembers=""
51 | if (pFilter="Yaxis") {
52 | set pMembers($I(pMembers))=$LB("Home City","[homed].[h1].[city]")
53 | set pMembers($I(pMembers))=$LB("Favorite Color","[colord].[h1].[favorite color]")
54 | set pMembers($I(pMembers))=$LB("Profession","[profd].[h1].[profession]")
55 | set pMembers($I(pMembers))=$LB("Diagnoses","[diagd].[h1].[diagnoses]")
56 | } else {
57 | //call method in superclass so we can get filter members for the associated cube
58 | do ..%GetMembersForFilter(..#CUBE,pFilter,.pMembers,pSearchKey)
59 | }
60 | quit $$$OK
61 | }
62 |
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/dev.md:
--------------------------------------------------------------------------------
1 | # Developer Notes
2 |
3 | This file complements the [main README](README.md) with additional background on how this sample can be set up and what automation was added.
4 |
5 | ## Files used in this repository
6 |
7 | Sample code
8 | * `src/cls/`: This folder contains the main ObjectScript code for this sample and its contents is described in the [main README](README.md)
9 | * `src/gbl/ZipCodeData.xml` contains a global export with static data used in the sample
10 |
11 | Setup options
12 | * Manual setup:
13 | * `buildsample/Build.SampleBI.xml` has the ObjectScript code to manually configure and populate the sample, as explained in the [main README](README.md)
14 | * ZPM setup:
15 | * `module.xml` is the main descriptor file for setting up the sample through [ZPM](https://github.com/intersystems-community/zpm), as an alternative to the manual setup procedure
16 | * Docker setup:
17 | * `Dockerfile` has the build recipe for building an entire Docker image out of this sample repository
18 | * `iris.script` has ObjectScript code to set up the sample namespace and then invokes ZPM for setting up the actual sample as described above.
19 | * `Installer.cls` is an [installation manifest](https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=GCI_MANIFEST) called by `iris.script` to set up the sample namespace
20 | * `.dockerignore` is a standard Docker configuration file to leave some repository contents out of the Docker build scope
21 | * `docker-compose.xml` adds convenience by scripting how to launch a container based on that image.
22 |
23 | Miscellaneous
24 | * `.vscode` is a configuration file for [Visual Studio Code](https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=PAGE_vscode), the recommended editor for ObjectScript code on InterSystems IRIS
25 | * `.gitattributes` and `.gitignore` are configuration files for Git source control and otherwise don't impact the sample
26 | * `.github/workflows/` has a few scripts for automated CI/CD workflows, leveraging [GitHub Actions](https://github.com/features/actions)
27 |
28 | ## Useful commands
29 |
30 | ### Build container with no cache
31 | ```
32 | docker-compose build --no-cache --progress=plain
33 | ```
34 |
35 | ### Open terminal to docker in a NAMESPACE
36 | ```
37 | docker-compose exec iris iris session iris -U IRISAPP
38 | ```
39 |
40 | ### Clear docker fs
41 | ```
42 | docker system prune -f
43 | ```
44 |
45 | ### Open SQL shell
46 | ```ObjectScript
47 | d $System.SQL.Shell()
48 | ```
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/KPIs/DemoMDX.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This KPI class uses an MDX query and has three filters.
3 | /// For each filter, multiSelect is false, which simplifies the query construction.
4 | Class BI.Model.KPIs.DemoMDX Extends %DeepSee.KPI
5 | {
6 |
7 | Parameter DOMAIN = "PATIENTSAMPLE";
8 |
9 | XData KPI [ XMLNamespace = "http://www.intersystems.com/deepsee/kpi" ]
10 | {
11 |
16 |
17 |
20 |
21 |
24 |
25 |
28 |
29 |
32 |
33 |
36 |
37 |
38 | }
39 |
40 | /// In this implementation: Given a filter (in this case an MDX level identifier),
41 | /// this method returns the list of members in the internal form needed by the KPI.
42 | ClassMethod %OnGetFilterMembers(pFilter As %String, Output pMembers As %List) As %Status
43 | {
44 | set status = $$$OK
45 |
46 | try {
47 | do ..%GetMembersForFilter("Patients.cube",pFilter,.pMembers)
48 | }
49 | catch(ex) {
50 | set status = ex.AsStatus()
51 | }
52 |
53 | quit status
54 | }
55 |
56 | /// In this implementation: This method adds a %FILTER clause for each non-null
57 | /// filter value. Because multiselect is off, query construction is fairly simple.
58 | Method %OnGetMDX(ByRef pMDX As %String) As %Status
59 | {
60 | if (..%filterValues."[homed].[h1].[zip]"'="")
61 | {
62 | set pMDX = pMDX _ " %FILTER [homed].[h1].[zip]." _..%filterValues."[homed].[h1].[zip]"
63 | }
64 |
65 | if (..%filterValues."[gend].[h1].[gender]"'="")
66 | {
67 | set pMDX = pMDX _ " %FILTER [gend].[h1].[gender]." _..%filterValues."[gend].[h1].[gender]"
68 | }
69 |
70 | if (..%filterValues."[aged].[h1].[age group]"'="")
71 | {
72 | set pMDX = pMDX _ " %FILTER [aged].[h1].[age group]." _..%filterValues."[aged].[h1].[age group]"
73 | }
74 |
75 | quit $$$OK
76 | }
77 |
78 | }
79 |
80 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/KPIs/DemoTrendLines.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This KPI class uses an MDX query that uses %LIST to return a list of values
3 | /// for use as a trend line in a scorecard.
4 | /// For each filter, multiSelect is false, which simplifies the query construction.
5 | /// (The KPI query would be incorrectly formed if the user selected multiple values
6 | /// or used the EXCLUDE option.)
7 | /// The KPI will not work if a URL parameter specifies multiple values or %NOT.
8 | Class BI.Model.KPIs.DemoTrendLines Extends %DeepSee.KPI
9 | {
10 |
11 | Parameter DOMAIN = "PATIENTSAMPLE";
12 |
13 | XData KPI [ XMLNamespace = "http://www.intersystems.com/deepsee/kpi" ]
14 | {
15 |
20 |
21 |
24 |
25 |
28 |
29 |
32 |
33 |
36 |
37 |
38 | }
39 |
40 | /// In this implementation: Given a filter (in this case an MDX level identifier),
41 | /// this method returns the list of members in the internal form needed by the KPI.
42 | ClassMethod %OnGetFilterMembers(pFilter As %String, Output pMembers As %List) As %Status
43 | {
44 | set status = $$$OK
45 |
46 | try {
47 | do ..%GetMembersForFilter("Patients.cube",pFilter,.pMembers)
48 | }
49 | catch(ex) {
50 | set status = ex.AsStatus()
51 | }
52 |
53 | quit status
54 | }
55 |
56 | /// In this implementation: Given a filter (in this case an MDX level identifier),
57 | /// this method returns the list of members in the internal form needed by the KPI.
58 | Method %OnGetMDX(ByRef pMDX As %String) As %Status
59 | {
60 |
61 | if (..%filterValues."[gend].[h1].[gender]"'="")
62 | {
63 | set pMDX = pMDX _ " %FILTER [gend].[h1].[gender]." _..%filterValues."[gend].[h1].[gender]"
64 | }
65 |
66 | if (..%filterValues."[homed].[h1].[zip]"'="")
67 | {
68 | set pMDX = pMDX _ " %FILTER [homed].[h1].[zip]." _..%filterValues."[homed].[h1].[zip]"
69 | }
70 |
71 | quit $$$OK
72 | }
73 |
74 | }
75 |
76 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/KPIs/PluginDemo.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This simple plug-in demo provides two properties:
3 | /// PatientCount, which behaves the same as the %COUNT measure
4 | /// HighScoreCount, which counts the patients with TestScore greater than 95.
5 | Class BI.Model.KPIs.PluginDemo Extends %DeepSee.KPIPlugIn
6 | {
7 |
8 | /// Display this one in the Analyzer
9 | Parameter PUBLIC = 1;
10 |
11 | /// This plug-in works only with one cube
12 | Parameter BASECUBE = "Patients";
13 |
14 | /// Query the fact table rather than the source table
15 | Parameter LISTINGSOURCE = "FactTable";
16 |
17 | /// Display this plug-in in the Analyzer for drag & drop use
18 | Parameter PLUGINTYPE = "Pivot";
19 |
20 | /// Specifies the field list (RETURN clause) of the listing used to supply data for this
21 | /// plug-in.
22 | Parameter LISTINGFIELDS As STRING = "MxTestScore";
23 |
24 | XData KPI [ XMLNamespace = "http://www.intersystems.com/deepsee/kpi" ]
25 | {
26 |
27 |
28 |
29 |
31 |
32 |
33 | }
34 |
35 | /// Get the base query for this plug-in.
36 | Method %OnGetMDX(ByRef pMDX As %String) As %Status
37 | {
38 | set pMDX = "SELECT FROM "_..#BASECUBE
39 | quit $$$OK
40 | }
41 |
42 | /// As input, this method receives a statement result that is the result of a listing query
43 | Method %OnCompute(pSQLRS As %SQL.StatementResult, pFactCount As %Integer) As %Status
44 | {
45 | set tSC = $$$OK
46 | Try {
47 | // Place answer in KPI output
48 | set ..%seriesCount = 1
49 | set ..%seriesNames(1) = "PluginDemo"
50 |
51 | // Set Count property of KPI -- just use received pFactCount
52 | set ..%data(1,"PatientCount") = pFactCount
53 |
54 | // Iterate through result set to get HighScoreCount
55 | set n = 0
56 | set highcount = 0
57 | while (pSQLRS.%Next(.tSC)) {
58 | if $$$ISERR(tSC) Quit
59 | set n = n + 1
60 |
61 | set testscore = pSQLRS.MxTestScore
62 | if (testscore>95) {
63 | set highcount = highcount + 1
64 | }
65 |
66 | // Update pct complete
67 | if (n#100 = 0) {
68 | Do ..%SetPercentComplete(100*(n/pFactCount))
69 | }
70 | }
71 | set ..%data(1,"HighScoreCount") = highcount
72 |
73 | }
74 | catch(ex) {
75 | set tSC = ex.AsStatus()
76 | }
77 | quit tSC
78 | }
79 |
80 | }
81 |
82 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/CompoundCube/CityRainfall.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is for use in a compound cube (and can also be used on its own).
3 | /// To view the cube definition, open this class in Studio.
4 | Class BI.Model.CompoundCube.CityRainfall Extends %DeepSee.CubeDefinition [ DependsOn = (BI.Study.CityRainfall, BI.Model.CompoundCube.Patients) ]
5 | {
6 |
7 | XData Cube [ XMLNamespace = "http://www.intersystems.com/deepsee" ]
8 | {
9 |
17 |
18 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
36 |
37 |
39 |
41 |
43 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
55 |
56 |
60 |
61 |
63 |
64 |
65 |
67 |
68 |
69 |
70 | }
71 |
72 | }
73 |
74 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/RelCubes/RDoctors.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is for use with InterSystems IRIS BI.
3 | /// It contains a cube based on BI.Study.Doctors.
4 | /// To view the cube definition, open this class in Studio or the BI Architect.
5 | /// The RelatedCubes/* cubes (like this one) use cube-to-cube relationships.
6 | Class BI.Model.RelCubes.RDoctors Extends %DeepSee.CubeDefinition [ DependsOn = (BI.Study.Doctor, BI.Model.RelCubes.RCities) ]
7 | {
8 |
9 | Parameter DOMAIN = "PATIENTSAMPLE";
10 |
11 | XData Cube [ XMLNamespace = "http://www.intersystems.com/deepsee" ]
12 | {
13 |
19 |
20 |
26 |
27 |
34 |
35 |
37 |
38 |
41 |
44 |
49 |
50 |
51 |
52 |
53 |
55 |
56 |
59 |
60 |
61 |
62 |
66 |
67 |
71 |
72 |
74 |
75 |
76 |
77 | }
78 |
79 | }
80 |
81 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/PatientsQueryCube.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class contains a cube based on BI.Model.PatientsQuery.
3 | /// This cube is not built by default.
4 | Class BI.Model.PatientsQueryCube Extends %DeepSee.CubeDefinition [ DependsOn = BI.Model.PatientsQuery ]
5 | {
6 |
7 | Parameter DOMAIN = "PATIENTSAMPLE";
8 |
9 | XData Cube [ XMLNamespace = "http://www.intersystems.com/deepsee" ]
10 | {
11 |
17 |
18 |
21 |
22 |
25 |
28 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
40 |
41 |
42 |
43 |
44 |
45 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
57 |
58 |
59 |
60 |
63 |
64 |
68 |
69 |
72 |
73 |
76 |
77 |
80 |
81 |
82 | }
83 |
84 | }
85 |
86 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/RainfallCube.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class contains a cube based on BI.Study.CityRainfall.
3 | /// The dimension, hierarchy, and level definitions here use the same names
4 | /// as in the Patients cube, so that these cubes can be used together.
5 | Class BI.Model.RainfallCube Extends %DeepSee.CubeDefinition [ DependsOn = BI.Study.CityRainfall ]
6 | {
7 |
8 | Parameter DOMAIN = "PATIENTSAMPLE";
9 |
10 | XData Cube [ XMLNamespace = "http://www.intersystems.com/deepsee" ]
11 | {
12 |
18 |
19 |
21 |
22 |
24 |
26 |
28 |
30 |
34 |
35 |
36 |
37 |
38 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
60 |
61 |
64 |
65 |
67 |
68 |
69 |
70 | }
71 |
72 | }
73 |
74 |
--------------------------------------------------------------------------------
/src/cls/BI/Study/AllergySeverity.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is part of the BI Patients sample, whose purpose is to provide
3 | /// sample data for use with InterSystems IRIS BI.
4 | /// This class contains the allergy severity lookup table.
5 | /// You can extend or modify the data contained here by editing the XData block in this class.
6 | Class BI.Study.AllergySeverity Extends %Persistent
7 | {
8 |
9 | /// Unique code for the allergy severity
10 | Property Code As %String;
11 |
12 | /// Unique description (user-visible name) for the allergy severity
13 | Property Description As %String;
14 |
15 | XData LoadData
16 | {
17 |
24 | }
25 |
26 | /// This method reads the XData block in this class and uses it to populate the table.
27 | /// This method is called by BI.Populate:GenerateData().
28 | ClassMethod Setup() As %Status
29 | {
30 | set status=$$$OK
31 | // First kill extent
32 | // Never use %KillExtent() in a real application
33 | Do ..%KillExtent()
34 |
35 | // Get a stream of XML from the XData block contained in this class
36 | set tStream=##class(%Dictionary.CompiledXData).IDKEYOpen($CLASSNAME(),"LoadData").Data
37 | if '$IsObject(tStream) {set tSC=%objlasterror Quit}
38 |
39 | set status=##class(%XML.TextReader).ParseStream(tStream,.textreader)
40 |
41 | // Check status
42 | if $$$ISERR(status) {Do $System.Status.DisplayError(status) Quit}
43 |
44 | // Iterate through document, node by node
45 | while textreader.Read()
46 | {
47 | if (textreader.NodeType="chars")
48 | {
49 | set value=textreader.Value
50 | //write !, "value is: ", value
51 | set obj=..%New()
52 | set obj.Code=$Piece(value,"^",1)
53 | set obj.Description=$Piece(value,"^",2)
54 | set status=obj.%Save()
55 | if $$$ISERR(status) {Do $System.Status.DisplayError(status) Quit}
56 | }
57 | }
58 |
59 | set status=##class(BI.Populate).UpdateIdCache($CLASSNAME())
60 |
61 | quit status
62 | }
63 |
64 | Storage Default
65 | {
66 |
67 |
68 | %%CLASSNAME
69 |
70 |
71 | Code
72 |
73 |
74 | Description
75 |
76 |
77 | ^BI.Study.AllergySeverityD
78 | AllergySeverityDefaultData
79 | ^BI.Study.AllergySeverityD
80 | ^BI.Study.AllergySeverityI
81 | ^BI.Study.AllergySeverityS
82 | %Storage.Persistent
83 | }
84 |
85 | }
86 |
87 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/ConnectorCube.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class contains a cube based on BI.Model.ConnectorExample.
3 | Class BI.Model.ConnectorCube Extends %DeepSee.CubeDefinition [ DependsOn = BI.Model.ConnectorExample ]
4 | {
5 |
6 | Parameter DOMAIN = "PATIENTSAMPLE";
7 |
8 | XData Cube [ XMLNamespace = "http://www.intersystems.com/deepsee" ]
9 | {
10 |
16 |
17 |
20 |
21 |
24 |
27 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
39 |
40 |
41 |
42 |
43 |
44 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
56 |
57 |
58 |
59 |
62 |
63 |
67 |
68 |
71 |
72 |
75 |
76 |
79 |
80 |
83 |
84 |
85 |
86 | }
87 |
88 | }
89 |
90 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/KPIs/DemoDataChanges.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This KPI class is intended for use in a dashboard that demos real-time updates using
3 | /// the Patients sample. The actions in this class invoke methods in that sample
4 | /// that add, change, or delete data.
5 | /// The actions are defined in the %OnDashboardAction() callback. The XData block in
6 | /// this class contains one element for each action, to advertise these actions
7 | /// to the widget builder in the user interface.
8 | /// This KPI class also defines a simple one-cell KPI which is displayed in a text meter
9 | /// widget on that dashboard. (An alternative way to access these actions from ANY dashboard
10 | /// would be to use this class as the actionClass for the Patients cube.)
11 | /// To see the full KPI definition, open this class in Studio.
12 | Class BI.Model.KPIs.DemoDataChanges Extends %DeepSee.KPI
13 | {
14 |
15 | Parameter DOMAIN = "PATIENTSAMPLE";
16 |
17 | XData KPI [ XMLNamespace = "http://www.intersystems.com/deepsee/kpi" ]
18 | {
19 |
23 |
24 |
27 |
28 |
30 |
31 |
33 |
34 |
36 |
37 |
39 |
40 |
42 |
43 |
45 |
46 |
47 | }
48 |
49 | ClassMethod %OnDashboardAction(pAction As %String, pContext As %ZEN.proxyObject) As %Status
50 | {
51 | set sc = $$$OK
52 | try{
53 | if (pAction = "AddPatients") {
54 | job ##class(BI.Study.Patient).AddPatients()
55 | }
56 | elseif (pAction="ChangeFavoriteColors")
57 | {
58 | job ##class(BI.Study.PatientDetails).ChangePatientDetails()
59 | }
60 | elseif (pAction="ChangePatientGroups")
61 | {
62 | job ##class(BI.Study.Patient).ChangePatientGroups()
63 | }
64 | elseif (pAction="AddEncounters")
65 | {
66 | job ##class(BI.Study.PatientEncounter).AddEncounters()
67 | }
68 | elseif (pAction="DeleteSomePatients")
69 | {
70 | job ##class(BI.Study.Patient).DeleteSomePatients()
71 | }
72 | elseif (pAction="ChangeSomeDoctors")
73 | {
74 | job ##class(BI.Study.Doctor).ChangeSomeDoctors()
75 | }
76 | }
77 | Catch(ex) {
78 | set sc = ex.AsStatus()
79 | }
80 | quit sc
81 | }
82 |
83 | }
84 |
85 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/ConnectorExample.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class defines an example of a data connector.
3 | /// The query for this connector uses a local table.
4 | Class BI.Model.ConnectorExample Extends %DeepSee.DataConnector
5 | {
6 |
7 | /// This connector supports "idlist" mode
8 | Parameter SUPPORTSIDLIST = 1;
9 |
10 | /// This connector supports "single" mode
11 | Parameter SUPPORTSSINGLE = 1;
12 |
13 | /// This XData definition defines the output of this connector.
14 | XData Output [ XMLNamespace = "http://www.intersystems.com/deepsee/connector/output" ]
15 | {
16 |
17 |
20 |
21 |
23 |
24 |
26 |
27 |
29 |
30 |
32 |
33 |
36 |
37 |
39 |
40 |
41 | }
42 |
43 | /// Implementation
44 | Method %OnGetSourceResultSet(ByRef pParameters, Output pResultSet) As %Status
45 | {
46 | set tSC = $$$OK
47 | set pResultSet = ""
48 | try {
49 | // Write the basic SQL query
50 | set sql="SELECT %ID,PatientID,Gender,Age,HomeCity->Name AS ""HomeCity"""
51 | _",PatientGroup,TestScore From BI_Study.Patient "
52 |
53 | if (..%mode="single") {
54 | set sql=sql_"WHERE %ID = ?"
55 | } elseif (..%mode="idlist") {
56 | set sql = sql _ "WHERE %ID in (select _DSsourceId from "
57 | _ ..%listingTable _ " where _DSqueryKey = ?)"
58 | }
59 |
60 | set tStatement = ##class(%SQL.Statement).%New()
61 | set tSC = tStatement.%Prepare(.sql)
62 |
63 | if $$$ISERR(tSC) {
64 | set ex = ##class(%Exception.StatusException).CreateFromStatus(tSC)
65 | throw ex
66 | }
67 |
68 | if (..%mode="single") {
69 | // Pass the ID as a parameter
70 | set pResultSet = tStatement.%Execute(..%singleId)
71 | } elseif (..%mode="idlist") {
72 | // Pass in the listing key as a parameter
73 | set pResultSet = tStatement.%Execute(..%listingKey)
74 | } else {
75 | set pResultSet = tStatement.%Execute()
76 | }
77 |
78 | // Check %SQLCODE and report if there's an error
79 | if pResultSet.%SQLCODE {
80 | set sqlcode=pResultSet.%SQLCODE
81 | set message=pResultSet.%Message
82 | set ex = ##class(%Exception.SQL).CreateFromSQLCODE(sqlcode, message)
83 | throw ex
84 | }
85 |
86 | }
87 | catch(ex) {
88 | Set tSC = ex.AsStatus()
89 | }
90 |
91 | quit tSC
92 | }
93 |
94 | }
95 |
96 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/CompoundCube/Doctors.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is for use in a compound cube (and can also be used on its own).
3 | /// To view the cube definition, open this class in Studio.
4 | Class BI.Model.CompoundCube.Doctors Extends %DeepSee.CubeDefinition [ DependsOn = (BI.Study.Doctor, BI.Model.CompoundCube.Patients) ]
5 | {
6 |
7 | Parameter DOMAIN = "PATIENTSAMPLE";
8 |
9 | XData Cube [ XMLNamespace = "http://www.intersystems.com/deepsee" ]
10 | {
11 |
21 |
22 |
25 |
26 |
29 |
32 |
37 |
38 |
39 |
40 |
41 |
43 |
44 |
47 |
48 |
49 |
50 |
55 |
56 |
58 |
60 |
62 |
64 |
65 |
66 |
67 |
68 |
72 |
73 |
77 |
78 |
80 |
81 |
82 |
84 |
85 |
86 |
87 | }
88 |
89 | }
90 |
91 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/KPIs/BubbleChartDemo.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// Sample KPI for HoleFoods Demo.
3 | /// This KPI provides synthetic corporate data and defines some simple actions.
4 | Class BI.Model.KPIs.BubbleChartDemo Extends %DeepSee.KPI
5 | {
6 |
7 | /// This XData definition defines the KPI.
8 | XData KPI [ XMLNamespace = "http://www.intersystems.com/deepsee/kpi" ]
9 | {
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | }
19 |
20 | /// Notify subclass that KPI is has just be executed.
21 | /// This is a good place to override properties, such as range and threshold.
22 | Method %OnLoadKPI() As %Status
23 | {
24 | set n=1
25 | set ..%seriesNames(n)="Alpha"
26 | set ..%data(n,"x")=15
27 | set ..%data(n,"y")=327
28 | set ..%data(n,"radius")=$R(6)+4
29 | set ..%data(n,"color")=$R(3)
30 | set ..%data(n,"opacity")=$R(7)+4
31 |
32 | set n=2
33 | set ..%seriesNames(n)="Beta"
34 | set ..%data(n,"x")=10
35 | set ..%data(n,"y")=200
36 | set ..%data(n,"radius")=$R(6)+4
37 | set ..%data(n,"color")=$R(3)
38 | set ..%data(n,"opacity")=$R(7)+4
39 |
40 | set n=3
41 | set ..%seriesNames(n)="Gamma"
42 | set ..%data(n,"x")=22
43 | set ..%data(n,"y")=256
44 | set ..%data(n,"radius")=$R(6)+4
45 | set ..%data(n,"color")=$R(3)
46 | set ..%data(n,"opacity")=$R(7)+4
47 |
48 | set n=4
49 | set ..%seriesNames(n)="Delta"
50 | set ..%data(n,"x")=17
51 | set ..%data(n,"y")=193
52 | set ..%data(n,"radius")=$R(6)+4
53 | set ..%data(n,"color")=$R(3)
54 | set ..%data(n,"opacity")=$R(7)+4
55 |
56 | set n=5
57 | set ..%seriesNames(n)="Epsilon"
58 | set ..%data(n,"x")=27
59 | set ..%data(n,"y")=281
60 | set ..%data(n,"radius")=$R(6)+4
61 | set ..%data(n,"color")=$R(3)
62 | set ..%data(n,"opacity")=$R(7)+4
63 |
64 | set n=6
65 | set ..%seriesNames(n)="Zeta"
66 | set ..%data(n,"x")=33
67 | set ..%data(n,"y")=301
68 | set ..%data(n,"radius")=$R(6)+4
69 | set ..%data(n,"color")=$R(3)
70 | set ..%data(n,"opacity")=$R(7)+4
71 |
72 | set n=7
73 | set ..%seriesNames(n)="Eta"
74 | set ..%data(n,"x")=25
75 | set ..%data(n,"y")=310
76 | set ..%data(n,"radius")=$R(6)+4
77 | set ..%data(n,"color")=$R(3)
78 | set ..%data(n,"opacity")=$R(7)+4
79 |
80 | set n=8
81 | set ..%seriesNames(n)="Theta"
82 | set ..%data(n,"x")=17
83 | set ..%data(n,"y")=399
84 | set ..%data(n,"radius")=$R(6)+4
85 | set ..%data(n,"color")=$R(3)
86 | set ..%data(n,"opacity")=$R(7)+4
87 |
88 | set n=9
89 | set ..%seriesNames(n)="Iota"
90 | set ..%data(n,"x")=35
91 | set ..%data(n,"y")=175
92 | set ..%data(n,"radius")=$R(6)+4
93 | set ..%data(n,"color")=$R(3)
94 | set ..%data(n,"opacity")=$R(7)+4
95 |
96 | set n=10
97 | set ..%seriesNames(n)="Kappa"
98 | set ..%data(n,"x")=28
99 | set ..%data(n,"y")=255
100 | set ..%data(n,"radius")=$R(6)+4
101 | set ..%data(n,"color")=$R(3)
102 | set ..%data(n,"opacity")=$R(7)+4
103 |
104 | set ..%seriesCount=n
105 | quit $$$OK
106 | }
107 |
108 | }
109 |
110 |
--------------------------------------------------------------------------------
/src/cls/BI/Study/Allergen.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is part of the BI Patients sample, whose purpose is to provide
3 | /// sample data for use with InterSystems IRIS BI.
4 | /// This class contains the allergen code lookup table.
5 | /// You can extend or modify the data contained here by editing the XData block in this class.
6 | Class BI.Study.Allergen Extends %Persistent
7 | {
8 |
9 | /// Unique code for the allergen
10 | Property Code As %String;
11 |
12 | /// Unique description (user-visible name) for the allergen
13 | Property Description As %String;
14 |
15 | /// Format: code^description
16 | /// The first row is special: this is the "allergen" that represents no known allergies.
17 | /// We treat this one differently when creating patient allergens.
18 | XData LoadData
19 | {
20 |
38 | }
39 |
40 | /// This method reads the XData block in this class and uses it to populate the table.
41 | /// This method is called by BI.Populate:GenerateData().
42 | ClassMethod Setup() As %Status
43 | {
44 | set status=$$$OK
45 | // First kill extent
46 | // Never use %KillExtent() in a real application
47 | do ..%KillExtent()
48 |
49 | // Get a stream of XML from the XData block contained in this class
50 | set tStream=##class(%Dictionary.CompiledXData).IDKEYOpen($CLASSNAME(),"LoadData").Data
51 | if '$IsObject(tStream) {set tSC=%objlasterror quit}
52 |
53 | set status=##class(%XML.TextReader).ParseStream(tStream,.textreader)
54 |
55 | // Check status
56 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
57 |
58 | // Iterate through document, node by node
59 | while textreader.Read()
60 | {
61 | if (textreader.NodeType="chars")
62 | {
63 | set value=textreader.Value
64 | //write !, "value is: ", value
65 | set obj=..%New()
66 | set obj.Code=$Piece(value,"^",1)
67 | set obj.Description=$Piece(value,"^",2)
68 | set status=obj.%Save()
69 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
70 | }
71 | }
72 | quit status
73 | }
74 |
75 | Storage Default
76 | {
77 |
78 |
79 | %%CLASSNAME
80 |
81 |
82 | Code
83 |
84 |
85 | Description
86 |
87 |
88 | ^BI.Study.AllergenD
89 | AllergenDefaultData
90 | ^BI.Study.AllergenD
91 | ^BI.Study.AllergenI
92 | ^BI.Study.AllergenS
93 | %Storage.Persistent
94 | }
95 |
96 | }
97 |
98 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/PortletDemo/ClockPortlet.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | Class BI.Model.PortletDemo.ClockPortlet Extends %DeepSee.Component.Portlet.abstractPortlet
3 | {
4 |
5 | Property srcparams As %String;
6 |
7 | /// Static HTML display method: draw the BODY of this component as HTML.
8 | Method %DrawHTML()
9 | {
10 | set size=$G(..settings("SIZE"))
11 | set ..srcparams=""
12 | for val="LOGO","STEP","OFFSET","CIRCLE","UTC","SIZE" set ..srcparams=..srcparams_val_"="_$G(..settings(val))_"&"
13 |
14 | &html<
15 |
17 |
>
18 | }
19 |
20 | /// Return the URL of the icon to display for this portlet.
21 | /// This is displayed in the Widget Builder dialog.
22 | /// This should be overridden in subclasses.
23 | ClassMethod %OnGetPortletIcon() As %String
24 | {
25 | quit "../broker/deepsee/insert_table_clock_48.png"
26 | }
27 |
28 | /// Return the localized caption of this portlet.
29 | /// This is displayed in the Widget Builder dialog.
30 | /// This should be overridden in subclasses.
31 | ClassMethod %OnGetPortletName() As %String
32 | {
33 | quit "AnalogClock"
34 | }
35 |
36 | /// Return an optional array of "settings" values for this portlet.
37 | /// The list of settings is displayed in the Widget Builder where the user can view and
38 | /// edit them.
39 | /// When the portlet is rendered, the values of all settings is made available to the
40 | /// portlet's %DrawHTML method via the settings--a
41 | /// multidimensional array subscripted by setting name.
42 | /// On return, pInfo can contain a list of settings in the form:
43 | /// pInfo(n) = $LB(name,value,type,caption,title)
44 | /// name is the logical name of the setting.
45 | /// value is the default value of the setting.
46 | /// type indicates the type of the setting. This determines the control
47 | /// displayed to get the value of the setting. If omitted the type is assumed to be a string.
48 | /// The type can be: "%Integer", "%Boolean", or "ENUM^caption1:value1,caption2:value2".
49 | /// caption is the localized caption of the setting.
50 | /// title is an optional tooltip displayed for the setting.
51 | ClassMethod %OnGetPortletSettings(Output pInfo As %List, ByRef pSettings) As %Status
52 | {
53 | kill pInfo
54 | set pInfo($I(pInfo)) = $LB("LOGO",$G(pSettings("LOGO")),"","Clock logo","Logo displayed on top of clock")
55 | set pInfo($I(pInfo)) = $LB("STEP",$G(pSettings("STEP"),"10"),"%Integer","Second hand redraw interval (msec)","milliseconds steps of second hand")
56 | set pInfo($I(pInfo)) = $LB("OFFSET",$G(pSettings("OFFSET"),"0"),"%Integer","Offset from base time (min)","minutes difference from base time (Local or UTC)")
57 | set pInfo($I(pInfo)) = $LB("UTC",$G(pSettings("UTC"),"0"),"%Boolean","UTC","Time Base: local (default) or UTC")
58 | set pInfo($I(pInfo)) = $LB("CIRCLE",$G(pSettings("CIRCLE"),"1"),"%Boolean","Circle","Shape: square (default) or circle")
59 | set pInfo($I(pInfo)) = $LB("SIZE",$G(pSettings("SIZE"),"150"),"%Integer","Size","Size of the clock")
60 |
61 | quit pInfo
62 | }
63 |
64 | }
65 |
66 |
--------------------------------------------------------------------------------
/src/cls/HoleFoods/KPISQL.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// Example KPI definition using SQL statements against the HoleFoods transaction data.
3 | Class HoleFoods.KPISQL Extends %DeepSee.KPI [ DependsOn = HoleFoods.Transaction ]
4 | {
5 |
6 | /// This XData definition defines the KPI.
7 | XData KPI [ XMLNamespace = "http://www.intersystems.com/deepsee/kpi" ]
8 | {
9 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | }
25 |
26 | /// This callback, if implements, lets a subclass provide an SQL statement to fetch data for this KPI.
27 | Method %OnGetSQL(ByRef pSQL As %String) As %Status
28 | {
29 | if $IsObject(..%filterValues) {
30 | set tWHERE = ""
31 | if (..%filterValues.City'="") {
32 | set tWHERE = tWHERE _ $S(tWHERE="":"",1:" AND ") _ " Outlet->City = '" _ ..%filterValues.City _"'"
33 | }
34 | if (..%filterValues.Product'="") {
35 | set tWHERE = tWHERE _ $S(tWHERE="":"",1:" AND ") _ " Product = '" _ ..%filterValues.Product _"'"
36 | }
37 |
38 | if (tWHERE'="") {
39 | // insert WHERE clase within query
40 | set tSQL1 = $P(pSQL,"GROUP BY",1)
41 | set tSQL2 = $P(pSQL,"GROUP BY",2)
42 | set pSQL = tSQL1 _ " WHERE " _ tWHERE
43 | if (tSQL2 '= "") {
44 | set pSQL = pSQL _ " GROUP BY" _ tSQL2
45 | }
46 | }
47 | }
48 | quit $$$OK
49 | }
50 |
51 | /// This callback, if implemented, returns the text of an SQL query used to provide
52 | /// a "detail listing" for this KPI.
53 | /// pFilters is an array of current filter values: pFilters(name)=value.
54 | /// pSelection is an array containing information about the current selected items in the pivot.
55 | /// It contains 2 values:
56 | /// pSelection("selectedRange") contains the current selected cells in the pivot as a string in the form
57 | /// "startRow,startCol,endRow,endCol" (1-based). "" if no cells are selected.
58 | /// pSelection("rowValues") contains a csv-list of "row" values for the selected rows in the pivot (similar
59 | /// to the $$$VALUELIST value used for OpenWindow URLs. This may contain "\," for "," within the data values.
60 | /// pListingName is the name of the listing to display. This is reserved for future use.
61 | /// This method is simply a convenient alternative to the %OnGetListingResultSet method.
62 | /// It takes precedence over the %OnGetListingResultSet method.
63 | ClassMethod %OnGetListingSQL(ByRef pFilters As %String, ByRef pSelection As %String, pListingName As %String = "") As %String
64 | {
65 | set tSQL = "SELECT TOP 1000 %ID,DateOfSale,Product FROM HoleFoods.SalesTransaction"
66 |
67 | // Apply sorting, if aksed for
68 | if (+$G(pSelection("sortColumn"))>0) {
69 | set tSQL = tSQL _ " ORDER BY " _ pSelection("sortColumn") _ " " _ $G(pSelection("sortDir"))
70 | }
71 |
72 | quit tSQL
73 | }
74 |
75 | }
76 |
77 |
--------------------------------------------------------------------------------
/src/cls/BI/Study/PatientAllergy.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is part of the BI Patients sample, whose purpose is to provide
3 | /// sample data for use with InterSystems IRIS BI.
4 | /// An allergy has multiple pieces of information,
5 | /// which you can use separately or in combination to create dimensions, depending
6 | /// on what you want to see.
7 | Class BI.Study.PatientAllergy Extends %SerialObject
8 | {
9 |
10 | /// A substance to which the patient is allergic.
11 | Property Allergen As BI.Study.Allergen;
12 |
13 | /// Severity of this allergic reaction.
14 | Property Severity As BI.Study.AllergySeverity;
15 |
16 | /// Doctor who recorded this allergic reaction.
17 | Property DiagnosedBy As BI.Study.Doctor;
18 |
19 | /// Called by BI.Study.Patient:GenerateData() or by BI.Study.PatientSet2:GenerateData().
20 | /// Pat argument could be either BI.Study.Patient or BI.Study.PatientSet2.
21 | ClassMethod GenerateAllergies(pat, genNulls As %Boolean) As %Status
22 | {
23 | set status=$$$OK
24 |
25 | // First decide if patient has no known allergies
26 | if ##class(BI.Populate).RandomTrue(15) {
27 | // Assume ID 1 is the nil allergen
28 | set allergen=##class(BI.Study.Allergen).%OpenId(1,0)
29 | set status=..AddAllergy(pat,allergen,genNulls)
30 | quit status
31 | }
32 |
33 | // Iterate through remaining allergens and randomly assign to patient
34 | set allergencount=##class(BI.Populate).Count("BI.Study.Allergen")
35 | for i=2:1:allergencount {
36 | if ##class(BI.Populate).RandomTrue(5) {
37 | set allergen=##class(BI.Study.Allergen).%OpenId(i,0)
38 | set status=..AddAllergy(pat,allergen,genNulls)
39 | }
40 | }
41 |
42 | quit status
43 | }
44 |
45 | /// Adds the given allergen to the patient and returns the patient by reference
46 | ClassMethod AddAllergy(ByRef pat, allergen As BI.Study.Allergen, genNulls As %Boolean) As %Status
47 | {
48 | set status=$$$OK
49 |
50 | set allergy=..%New()
51 | set allergy.Allergen=allergen
52 |
53 | if (allergen.Code'="000") {
54 |
55 | set sevid=##class(BI.Populate).GetRandomId("BI.Study.AllergySeverity")
56 | set allergy.Severity=##class(BI.Study.AllergySeverity).%OpenId(sevid,0)
57 |
58 | set docid=##class(BI.Populate).GetRandomId("BI.Study.Doctor")
59 | set allergy.DiagnosedBy=##class(BI.Study.Doctor).%OpenId(docid,0)
60 | }
61 |
62 | if genNulls {
63 | // For some percent of allergies, severity is not recorded
64 | if ##class(BI.Populate).RandomTrue(2){
65 | set allergy.Severity=""
66 | }
67 | // For some percent of allergies, diagnosing doctor is not recorded
68 | if ##class(BI.Populate).RandomTrue(8){
69 | set allergy.DiagnosedBy=""
70 | }
71 | }
72 |
73 | // Now add this to the patient
74 | set status=pat.Allergies.Insert(allergy)
75 |
76 | // Create the same data in the PatientAllergy1 table
77 | set status=##class(BI.Study.PatientAllergy1).CreateOne(pat,allergen,allergy.Severity,allergy.DiagnosedBy)
78 |
79 | quit status
80 | }
81 |
82 | Storage Default
83 | {
84 |
85 |
86 | Allergen
87 |
88 |
89 | Severity
90 |
91 |
92 | DiagnosedBy
93 |
94 |
95 | PatientAllergyState
96 | ^BI.Study.PatientAllergyS
97 | %Storage.Serial
98 | }
99 |
100 | }
101 |
102 |
--------------------------------------------------------------------------------
/src/cls/BI/Study/City.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is part of the BI Patients sample, whose purpose is to provide
3 | /// sample data for use with InterSystems IRIS BI.
4 | /// This class contains the cities and the ZIP codes to which they belong, as
5 | /// well as city-specific properties to use as level properties in BI.
6 | /// You can extend or modify the data contained here by editing the XData block in this class.
7 | Class BI.Study.City Extends %Persistent
8 | {
9 |
10 | Property PostalCode As %String;
11 |
12 | Property Name As %String;
13 |
14 | Property Population As %Integer;
15 |
16 | Property PrincipalExport As %String;
17 |
18 | /// Fields: postal code^city^city population^principal export
19 | /// There are multiple cities in most postal codes
20 | XData LoadData
21 | {
22 |
33 | }
34 |
35 | /// This method reads the XData block in this class and uses it to populate the table.
36 | /// This method is called by BI.Populate:GenerateData().
37 | ClassMethod Setup() As %Status
38 | {
39 | set status=$$$OK
40 | // First kill extent and child extent
41 | // Never use %KillExtent() in a real application
42 | do ..%KillExtent()
43 |
44 | // Get a stream of XML from the XData block contained in this class
45 | set tStream=##class(%Dictionary.CompiledXData).IDKEYOpen($CLASSNAME(),"LoadData").Data
46 | if '$IsObject(tStream) {set tSC=%objlasterror quit}
47 |
48 | set status=##class(%XML.TextReader).ParseStream(tStream,.textreader)
49 |
50 | // Check status
51 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
52 |
53 | // Iterate through document, node by node
54 | while textreader.Read()
55 | {
56 | if (textreader.NodeType="chars")
57 | {
58 | set value=textreader.Value
59 | // Write !, "value is: ", value
60 | set obj=..%New()
61 | set obj.PostalCode=$Piece(value,"^",1)
62 | set obj.Name=$Piece(value,"^",2)
63 | set obj.Population=$Piece(value,"^",3)
64 | set obj.PrincipalExport=$Piece(value,"^",4)
65 | set status=obj.%Save()
66 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
67 | }
68 | }
69 |
70 | // Create an "extent set" from which we can later get random IDs
71 | set status=##class(BI.Populate).UpdateIdCache($CLASSNAME())
72 |
73 | quit status
74 | }
75 |
76 | Storage Default
77 | {
78 |
79 |
80 | %%CLASSNAME
81 |
82 |
83 | PostalCode
84 |
85 |
86 | Name
87 |
88 |
89 | Population
90 |
91 |
92 | PrincipalExport
93 |
94 |
95 | ^BI.Study.CityD
96 | CityDefaultData
97 | ^BI.Study.CityD
98 | ^BI.Study.CityI
99 | ^BI.Study.CityS
100 | %Storage.Persistent
101 | }
102 |
103 | }
104 |
105 |
--------------------------------------------------------------------------------
/src/cls/HoleFoods/Transaction.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// Instances of this class represent specific transactions within
3 | /// the HoleFoods demo.
4 | /// This table combines both "actual" data and "budget" data so that the sample cube
5 | /// can show comparisons between the two.
6 | /// Actual records will have a true value for the Actual property.
7 | /// Budget records will have a false value for the Actual property. The budget value will
8 | /// be stored in the TargetAmount property. Budget values are set for each city, product, and
9 | /// month (using the first day of the month).
10 | Class HoleFoods.Transaction Extends %Persistent [ SqlTableName = SalesTransaction ]
11 | {
12 |
13 | /// Track changes to this class.
14 | Parameter DSTIME = "auto";
15 |
16 | Index DateOfSale On DateOfSale;
17 |
18 | Index Product On Product [ Type = bitmap ];
19 |
20 | Index Outlet On Outlet [ Type = bitmap ];
21 |
22 | /// If true, this represents an actual sale
23 | /// otherwise this represents a sales target.
24 | Property Actual As %Boolean;
25 |
26 | /// Date of this sale.
27 | Property DateOfSale As %Date;
28 |
29 | /// Product sold.
30 | Property Product As Product;
31 |
32 | /// Store or other outlet in which the sale occurred.
33 | Property Outlet As Outlet;
34 |
35 | /// Channel product was sold through: "Retail" or "Online".
36 | Property Channel As %String(DISPLAYLIST = ",Retail,Online", VALUELIST = ",1,2");
37 |
38 | /// Actual amount of this sale.
39 | Property AmountOfSale As %Numeric(SCALE = 2);
40 |
41 | /// Units sold.
42 | Property UnitsSold As %Integer;
43 |
44 | /// Discount amount.
45 | Property Discount As %Numeric(SCALE = 2);
46 |
47 | /// For budget items, this is the target value for a period,region, and product.
48 | Property TargetAmount As %Numeric(SCALE = 2);
49 |
50 | /// Customer comment on this transaction (if any).
51 | Property Comment As %String(MAXLEN = 500);
52 |
53 | /// US Zipcode of customer (if provided).
54 | Property ZipCode As %String(MAXLEN = 25);
55 |
56 | /// Latitude of customer (determined from zip code).
57 | Property Latitude As %Double;
58 |
59 | /// Longitude of customer (determined from zip code).
60 | Property Longitude As %Double;
61 |
62 | Storage Default
63 | {
64 |
65 |
66 | %%CLASSNAME
67 |
68 |
69 | Actual
70 |
71 |
72 | DateOfSale
73 |
74 |
75 | Product
76 |
77 |
78 | Outlet
79 |
80 |
81 | Channel
82 |
83 |
84 | AmountOfSale
85 |
86 |
87 | UnitsSold
88 |
89 |
90 | Discount
91 |
92 |
93 | TargetAmount
94 |
95 |
96 | Comment
97 |
98 |
99 | ZipCode
100 |
101 |
102 | Latitude
103 |
104 |
105 | Longitude
106 |
107 |
108 | ^HoleFoods.TransactionD
109 | TransactionDefaultData
110 | ^HoleFoods.TransactionD
111 | ^HoleFoods.TransactionI
112 | ^HoleFoods.TransactionS
113 | %Storage.Persistent
114 | }
115 |
116 | }
117 |
118 |
--------------------------------------------------------------------------------
/.github/workflows/build-push-gcr.yaml:
--------------------------------------------------------------------------------
1 | name: Cloud Run Deploy
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | - main
8 |
9 | env:
10 | # Change this section according to your needs
11 | IMAGE_NAME: samples-bi-demo
12 | SERVICE: samples-bi
13 | DOMAIN_NAME: samples-bi.demo.community.intersystems.com
14 |
15 | # Leave this section untouched
16 | PROJECT_ID: iris-community-demos
17 | CLUSTER_NAME: demo
18 | GITHUB_SHA: ${{ github.sha }}
19 | GCR_LOCATION: eu.gcr.io
20 | REGION: europe-west2
21 | NAMESPACE: demo
22 |
23 | jobs:
24 | deploy-cloud-run:
25 | name: Deploy to Cloud Run
26 | runs-on: ubuntu-20.04
27 | steps:
28 | - name: Checkout
29 | uses: actions/checkout@v2
30 |
31 | - name: Setup Cloud SDK
32 | uses: google-github-actions/setup-gcloud@v0.2.0
33 | with:
34 | version: '327.0.0'
35 | service_account_key: ${{ secrets.SERVICE_ACCOUNT_KEY }}
36 |
37 | - name: Authorize Docker push
38 | run: gcloud auth configure-docker
39 |
40 | - name: Build and Push image
41 | run: |
42 | docker build -t ${GCR_LOCATION}/${PROJECT_ID}/${IMAGE_NAME}:${GITHUB_SHA} .
43 | docker push ${GCR_LOCATION}/${PROJECT_ID}/${IMAGE_NAME}:${GITHUB_SHA}
44 |
45 | - name: Deploy to Cloud Run
46 | run: |
47 | echo "[INFO] Set google project..."
48 | gcloud config set project ${PROJECT_ID}
49 |
50 | echo "[INFO] Deploy service..."
51 | gcloud run deploy ${SERVICE} \
52 | --platform gke \
53 | --cluster ${CLUSTER_NAME} \
54 | --cluster-location ${REGION} \
55 | --namespace ${NAMESPACE} \
56 | --port 52773 \
57 | --min-instances 1 \
58 | --memory 512Mi \
59 | --timeout 300 \
60 | --verbosity debug \
61 | --image ${GCR_LOCATION}/${PROJECT_ID}/${IMAGE_NAME}:${GITHUB_SHA}
62 |
63 | echo "[INFO] Create domain mappings..."
64 | if [[ $(gcloud run domain-mappings list --platform gke --cluster ${CLUSTER_NAME} --cluster-location ${REGION} --namespace ${NAMESPACE} --filter "DOMAIN=${DOMAIN_NAME}" | grep -v DOMAIN | wc -l) == 0 ]]; then
65 | gcloud run domain-mappings create \
66 | --service ${SERVICE} \
67 | --platform gke \
68 | --cluster ${CLUSTER_NAME} \
69 | --cluster-location ${REGION} \
70 | --namespace ${NAMESPACE} \
71 | --verbosity debug \
72 | --domain ${DOMAIN_NAME}
73 | fi
74 |
75 | - name: Create domain name
76 | run: |
77 | gcloud container clusters get-credentials ${CLUSTER_NAME} --region ${REGION} --project ${PROJECT_ID}
78 | kubectl version
79 | echo "[INFO] Checking if [${DOMAIN_NAME}] is in the existing Ingress annotation..."
80 | CURRENT_DOMAINS_LIST=$(kubectl -n gke-system get svc istio-ingress -o jsonpath="{.metadata.annotations['external-dns\.alpha\.kubernetes\.io/hostname']}")
81 | if [[ $(echo ${CURRENT_DOMAINS_LIST} | grep -w "${DOMAIN_NAME}" | wc -c) -eq 0 ]]; then \
82 | echo "[INFO] Domain [${DOMAIN_NAME}] is ABSENT in the domains list. Adding..."; \
83 | kubectl -n gke-system annotate --overwrite svc istio-ingress external-dns\.alpha\.kubernetes\.io/hostname=${CURRENT_DOMAINS_LIST},${DOMAIN_NAME}; \
84 | echo -n "[INFO] Resulting domain names: "
85 | kubectl -n gke-system get svc istio-ingress -o jsonpath="{.metadata.annotations['external-dns\.alpha\.kubernetes\.io/hostname']}"
86 | else
87 | echo "[INFO] Domain [${DOMAIN_NAME}] is in the domains list. Leave untouched..."; \
88 | fi
89 |
90 | - name: Enable TLS-access
91 | run: |
92 | gcloud container clusters get-credentials ${CLUSTER_NAME} --region ${REGION} --project ${PROJECT_ID}
93 | kubectl version
94 | kubectl patch configmap config-domainmapping -n knative-serving -p '{"data":{"autoTLS":"Enabled"}}'
95 |
--------------------------------------------------------------------------------
/src/cls/BI/Study/Profession.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is part of the BI Patients sample, whose purpose is to provide
3 | /// sample data for use with InterSystems IRIS BI.
4 | /// This class contains the professions and their industries.
5 | Class BI.Study.Profession Extends %Persistent
6 | {
7 |
8 | Property Profession As %String;
9 |
10 | Property Industry As %String;
11 |
12 | /// Used by Setup method. The format of is:
13 | /// industry^profession
14 | /// Industries taken from http://www.census.gov/epcd/susb/latest/us/US--.HTM
15 | /// Only a few industries and professions are included.
16 | XData LoadData
17 | {
18 |
19 | Accommodation and Food Services^Baker
20 | Accommodation and Food Services^Cook
21 | Construction^Electrician
22 | Construction^Carpenter
23 | Construction^Plumber
24 | Educational Services^Teacher
25 | Educational Services^Corporate Trainer
26 | Finance and Insurance^Insurance Agent
27 | Finance and Insurance^Bank Teller
28 | Finance and Insurance^Benefits Coordinator
29 | Health Care and Social Assistance^Doctor
30 | Health Care and Social Assistance^Nurse
31 | Professional, Scientific, and Technical Services^Veterinarian
32 | Professional, Scientific, and Technical Services^Programmer
33 | Professional, Scientific, and Technical Services^Architect
34 | Professional, Scientific, and Technical Services^Accountant
35 | Real Estate and Leasing^Real Estate Agent
36 | Retail Trade^Retail Clerk
37 | Retail Trade^Store Manager
38 | Transportation and Warehousing^Truck Driver
39 | Transportation and Warehousing^Warehouse Manager
40 | Other Services^Appliance Repair Specialist
41 | Other Services^Other
42 |
43 | }
44 |
45 | /// This method reads the XData block in this class and uses it to populate the table.
46 | /// This method is called by BI.Populate:GenerateData().
47 | ClassMethod Setup() As %Status
48 | {
49 | set status=$$$OK
50 |
51 | // First kill extent
52 | // Never use %KillExtent() in a real application
53 | do ..%KillExtent()
54 |
55 | // Get a stream of XML from the XData block contained in this class
56 | set tStream=##class(%Dictionary.CompiledXData).IDKEYOpen($CLASSNAME(),"LoadData").Data
57 | if '$IsObject(tStream) {set tSC=%objlasterror Quit}
58 |
59 | set status=##class(%XML.TextReader).ParseStream(tStream,.textreader)
60 |
61 | // Check status
62 | if $$$ISERR(status) {do $System.Status.DisplayError(status) Quit}
63 |
64 | set count=0
65 |
66 | // Iterate through document, node by node
67 | while textreader.Read()
68 | {
69 | if (textreader.NodeType="chars")
70 | {
71 | set value=textreader.Value
72 | // write !, "value is: ", value
73 | set obj=..%New()
74 | set obj.Industry=$Piece(value,"^",1)
75 | set obj.Profession=$Piece(value,"^",2)
76 | set status=obj.%Save()
77 | if $$$ISERR(status) {do $System.Status.DisplayError(status) Quit}
78 | set count=count+1
79 | }
80 | }
81 |
82 | // Create an "extent set" from which we can later get random IDs
83 | set status=##class(BI.Populate).UpdateIdCache($CLASSNAME())
84 |
85 | quit status
86 | }
87 |
88 | Storage Default
89 | {
90 |
91 |
92 | %%CLASSNAME
93 |
94 |
95 | Profession
96 |
97 |
98 | Industry
99 |
100 |
101 | ^BI.Study.ProfessionD
102 | ProfessionDefaultData
103 | ^BI.Study.ProfessionD
104 | ^BI.Study.ProfessionI
105 | ^BI.Study.ProfessionS
106 | %Storage.Persistent
107 | }
108 |
109 | }
110 |
111 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/CompoundCube/Patients.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is for use in a compound cube (and can also be used on its own).
3 | /// To view the cube definition, open this class in Studio.
4 | Class BI.Model.CompoundCube.Patients Extends %DeepSee.CubeDefinition [ DependsOn = BI.Study.Patient ]
5 | {
6 |
7 | Parameter DOMAIN = "PATIENTSAMPLE";
8 |
9 | XData Cube [ XMLNamespace = "http://www.intersystems.com/deepsee" ]
10 | {
11 |
21 |
22 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
37 |
38 |
41 |
44 |
49 |
50 |
51 |
52 |
53 |
55 |
56 |
59 |
60 |
61 |
62 |
64 |
65 |
69 |
73 |
76 |
79 |
80 |
81 |
82 |
83 |
87 |
88 |
91 |
92 |
95 |
96 |
98 |
99 |
100 | }
101 |
102 | }
103 |
104 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/PortletDemo/svgClock.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | Class BI.Model.PortletDemo.svgClock Extends %CSP.Page
3 | {
4 |
5 | ClassMethod OnPreHTTP() As %Boolean [ ServerOnly = 1 ]
6 | {
7 | set %response.ContentType="image/svg+xml"
8 | quit $$$OK
9 | }
10 |
11 | ClassMethod OnPage() As %Status
12 | {
13 | set size=$G(%request.Data("SIZE",1),200)
14 | set uri="?"
15 | for par="LOGO","CIRCLE","UTC","OFFSET","STEP" {
16 | if $d(%request.Data(par,1),val) set uri=uri_par_"="_val_"&"
17 | }
18 | &html<
123 | >
124 | quit $$$OK
125 | }
126 |
127 | }
128 |
129 |
--------------------------------------------------------------------------------
/src/cls/BI/Model/RelCubes/RPatients.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is for use with InterSystems IRIS BI.
3 | /// It contains a cube based on BI.Study.Patients.
4 | /// To view the cube definition, open this class in Studio or the BI Architect.
5 | /// The RelatedCubes/* cubes (like this one) use cube-to-cube relationships.
6 | Class BI.Model.RelCubes.RPatients Extends %DeepSee.CubeDefinition [ DependsOn = (BI.Study.Patient, BI.Model.RelCubes.RDoctors, BI.Model.RelCubes.RCities) ]
7 | {
8 |
9 | Parameter DOMAIN = "PATIENTSAMPLE";
10 |
11 | XData Cube [ XMLNamespace = "http://www.intersystems.com/deepsee" ]
12 | {
13 |
20 |
21 |
25 |
26 |
30 |
31 |
35 |
36 |
38 |
39 |
43 |
46 |
49 |
53 |
54 |
55 |
56 |
57 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
84 |
85 |
86 |
87 |
88 |
89 |
92 |
93 |
94 |
95 |
96 |
97 |
100 |
103 |
104 |
105 |
106 |
109 |
110 |
114 |
115 |
118 |
119 |
122 |
123 |
124 | }
125 |
126 | }
127 |
128 |
--------------------------------------------------------------------------------
/src/cls/BI/Study/CityRainfall.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is part of the BI Patients sample, whose purpose is to provide
3 | /// sample data for use with InterSystems IRIS BI.
4 | /// This class contains the rainfall for the cities, by year and month, and is meant
5 | /// for use as an additional BI model/cube.
6 | /// This table is populated only if you use the R option when running the
7 | /// GenerateData() method in BI.Populate. You can also use
8 | /// the GenerateData() method in this class if you have already populated the main
9 | /// sample.
10 | /// You can extend or modify the data contained here by editing the XData block in this class.
11 | Class BI.Study.CityRainfall Extends %Persistent
12 | {
13 |
14 | /// This parameter setting enables the DSTIME feature for InterSystems IRIS BI
15 | Parameter DSTIME = "AUTO";
16 |
17 | Property City As BI.Study.City;
18 |
19 | Property MonthAndYear As %Date;
20 |
21 | Property InchesOfRain As %Numeric;
22 |
23 | /// Fields: month number^average rainfall in inches^variance in inches
24 | XData LoadData
25 | {
26 |
40 | }
41 |
42 | /// Call this after the cities have been set up; this means we reopen each city once.
43 | ClassMethod GenerateData() As %Status
44 | {
45 | write !, "Creating rainfall data for the cities..."
46 |
47 | // Never use %KillExtent() in a real application
48 | do ..%KillExtent()
49 |
50 | // Get a stream of XML from the XData block contained in this class
51 | set tStream=##class(%Dictionary.CompiledXData).IDKEYOpen($CLASSNAME(),"LoadData").Data
52 | if '$IsObject(tStream) {set tSC=%objlasterror quit}
53 |
54 | set status=##class(%XML.TextReader).ParseStream(tStream,.textreader)
55 | //check status
56 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
57 |
58 | //iterate through document, node by node
59 | while textreader.Read()
60 | {
61 | if (textreader.NodeType="chars")
62 | {
63 | set value=textreader.Value
64 |
65 | set month=$Piece(value,"^",1)
66 | set avgrainfall=$Piece(value,"^",2)
67 | set var=$Piece(value,"^",3)
68 | set ^||myvar("rainfall",month,"min")=avgrainfall-var
69 | set ^||myvar("rainfall",month,"max")=avgrainfall+var
70 | }
71 | }
72 |
73 | set myquery="select ID from BI_Study.City"
74 | set rset=##class(%ResultSet).%New("%DynamicQuery:SQL")
75 | set status=rset.Prepare(myquery)
76 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
77 | set status=rset.Execute()
78 |
79 | while (rset.Next(.status)) {
80 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
81 | set cityid=rset.Data("ID")
82 | set city=##class(BI.Study.City).%OpenId(cityid,0)
83 |
84 | //we have rainfall data for a particular span of years
85 | set separator=##class(%SYS.NLS.Format).GetFormatItem("DateSeparator")
86 | for year=1900:1:$Piece($Zdate($h,1),separator,3) {
87 | for month=1:1:12 {
88 | set record=..%New()
89 | set record.City=city
90 | if (month<10) {
91 | set monthstring="0"_month
92 | }
93 | else {
94 | set monthstring=month
95 | }
96 | set datestring=year_"-"_monthstring_"-01"
97 | set min=^||myvar("rainfall",month,"min")
98 | set max=^||myvar("rainfall",month,"max")
99 | set rainfall=min + ($RANdoM(max*100)+1)/100
100 |
101 |
102 | set record.MonthAndYear=$ZDATEH(datestring,3)
103 | set record.InchesOfRain=rainfall
104 | set status=record.%Save()
105 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
106 | }
107 | }
108 |
109 | }
110 |
111 | do ##class(%DeepSee.Utils).%SynchronizeCube("cityrainfall")
112 |
113 | quit status
114 | }
115 |
116 | Storage Default
117 | {
118 |
119 |
120 | %%CLASSNAME
121 |
122 |
123 | City
124 |
125 |
126 | MonthAndYear
127 |
128 |
129 | InchesOfRain
130 |
131 |
132 | ^BI.Study.CityRainfallD
133 | CityRainfallDefaultData
134 | ^BI.Study.CityRainfallD
135 | ^BI.Study.CityRainfallI
136 | ^BI.Study.CityRainfallS
137 | %Storage.Persistent
138 | }
139 |
140 | }
141 |
142 |
--------------------------------------------------------------------------------
/src/cls/HoleFoods/KPISalesVsTarget.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// Sample KPI for HoleFoods Demo.
3 | /// This KPI provides real sales data compared with budget targets.
4 | Class HoleFoods.KPISalesVsTarget Extends %DeepSee.KPI
5 | {
6 |
7 | /// Used to pass ROWS clause among methods.
8 | Property RowClause As %String;
9 |
10 | /// Used to pass filter clause among methods.
11 | Property FilterClause As %String;
12 |
13 | /// This XData definition defines the KPI.
14 | XData KPI [ XMLNamespace = "http://www.intersystems.com/deepsee/kpi" ]
15 | {
16 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | }
29 |
30 | /// Notification that this KPI is being executed.
31 | /// This is a good place to override properties, such as range and threshold.
32 | Method %OnLoadKPI() As %Status
33 | {
34 | set tSC = $$$OK
35 |
36 | // Compute additional values
37 | set tFilters = ..%filterValues
38 |
39 | // Compute recent history using query
40 | if ((tFilters.Year'="")&&(tFilters.Year'="*")&&(tFilters.Year'="&[NOW]")) {
41 | // Take &[] off of Year value!
42 | set tStartMonth = "Jan-"_$E(tFilters.Year,3,6)
43 | set tEndMonth = "Dec-"_$E(tFilters.Year,3,6)
44 | }
45 | else {
46 | set tStartMonth = "NOW-12"
47 | set tEndMonth = "NOW"
48 | }
49 |
50 | set tROWS = ..RowsClause
51 | set tMDX = "SELECT "_tROWS_"%LIST(DateOfSale.[MonthSold].["_tStartMonth_"]:["_tEndMonth_"]) ON COLUMNS FROM HOLEFOODSCOMBINED WHERE Measures.[Amount Sold] " _ ..FilterClause
52 | set tRS = ##class(%DeepSee.ResultSet).%New()
53 | set tSC = tRS.%PrepareMDX(tMDX)
54 | if $$$ISERR(tSC) quit tSC
55 | set tSC = tRS.%Execute()
56 | if $$$ISERR(tSC) quit tSC
57 |
58 | for n = 1:1:..%seriesCount {
59 | set tValue = tRS.%GetOrdinalValue(1,n)
60 | set ..%data(n,"History") = tValue
61 | }
62 | quit tSC
63 | }
64 |
65 | /// Return an MDX statement to execute.
66 | Method %OnGetMDX(ByRef pMDX As %String) As %Status
67 | {
68 | set tFilters = ..%filterValues
69 |
70 | // Construct an MDX query based on the current filter values
71 | set tROWS = ""
72 | set tFILTER = ""
73 |
74 | // Show by
75 | if (tFilters.ShowBy="Year") {
76 | set tROWS = "[DateOfSale].[YearSold].Members"
77 | }
78 | elseif (tFilters.ShowBy="Month") {
79 | set tROWS = "[DateOfSale].[MonthSold].Members"
80 | }
81 | elseif ((tFilters.ShowBy="ProductCategory")) {
82 | set tROWS = "[Product].[Product Category].Members"
83 | }
84 | elseif ((tFilters.ShowBy="ProductName")||(tFilters.ShowBy="")) {
85 | set tROWS = "[Product].[Product Name].Members"
86 | }
87 | elseif (tFilters.ShowBy="Country") {
88 | set tROWS = "[Outlet].[Country].Members"
89 | }
90 | elseif (tFilters.ShowBy="City") {
91 | set tROWS = "[Outlet].[City].Members"
92 | }
93 |
94 | if (tROWS'="") {
95 | set tROWS = "NON EMPTY "_tROWS_" ON ROWS,"
96 | }
97 |
98 | // Filters
99 | if ((tFilters.Year'="")&&(tFilters.Year'="*")) {
100 | set tFILTER = tFILTER_" %FILTER [DateOfSale].[YearSold]."_tFilters.Year
101 | }
102 | if ((tFilters.Product'="")&&(tFilters.Product'="*")) {
103 | set tFILTER = tFILTER_" %FILTER [Product].[Product Category]."_tFilters.Product
104 | }
105 | if ((tFilters.Country'="")&&(tFilters.Country'="*")) {
106 | set tFILTER = tFILTER_" %FILTER [Outlet].[Country]."_tFilters.Country
107 | }
108 |
109 | set ..FilterClause = tFILTER
110 | set ..RowsClause = tROWS
111 |
112 | set pMDX = "SELECT "_tROWS_"{Measures.[Amount Sold],Measures.[Target]} ON Columns FROM HOLEFOODSCOMBINED "_tFILTER
113 | quit $$$OK
114 | }
115 |
116 | /// Callback to get additional members for a KPI filter.
117 | /// This takes the form:
118 | /// pMembers($I(pMembers))=$LB(text,value)
119 | ClassMethod %OnGetFilterMembers(pFilter As %String, Output pMembers As %List, pSearchKey As %String) As %Status
120 | {
121 | set tSC = $$$OK
122 | try {
123 | // Get member list from cube
124 | if (pFilter = "Year") {
125 | set tSC = ..%GetMembersForFilter("HOLEFOODSCOMBINED","[DateOfSale].[Actual].[YearSold]",.pMembers,pSearchKey)
126 | if $$$ISERR(tSC) quit
127 | }
128 | elseif (pFilter = "Product") {
129 | set tSC = ..%GetMembersForFilter("HOLEFOODSCOMBINED","[Product].[P1].[Product Name]",.pMembers,pSearchKey)
130 | if $$$ISERR(tSC) quit
131 | }
132 | elseif (pFilter = "Country") {
133 | set tSC = ..%GetMembersForFilter("HOLEFOODSCOMBINED","[Outlet].[H1].[Country]",.pMembers,pSearchKey)
134 | if $$$ISERR(tSC) quit
135 | }
136 | }
137 | catch(ex) {
138 | set tSC = ex.AsStatus()
139 | }
140 | quit tSC
141 | }
142 |
143 | }
144 |
145 |
--------------------------------------------------------------------------------
/src/cls/HoleFoods/KPICFO.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// Sample KPI for HoleFoods Demo.
3 | /// This KPI provides synthetic corporate data and defines some simple actions.
4 | Class HoleFoods.KPICFO Extends %DeepSee.KPI
5 | {
6 |
7 | /// This XData definition defines the KPI.
8 | XData KPI [ XMLNamespace = "http://www.intersystems.com/deepsee/kpi" ]
9 | {
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | }
22 |
23 | /// Notify subclass that KPI is has just be executed.
24 | /// This is a good place to override properties, such as range and threshold.
25 | Method %OnLoadKPI() As %Status
26 | {
27 | // Define list of metrics we will calculate
28 | // all are percentage of target, so are 0-1.5 typically.
29 |
30 | set tMetrics(1) = "EBIT"
31 | set tMetrics(2) = "Share Price"
32 | set tMetrics(3) = "A/Payable"
33 | set tMetrics(4) = "A/Receivable"
34 | set tMetrics(5) = "Long-term Debt"
35 | set tMetrics(6) = "Inventory"
36 | set tMetrics(7) = "Market Share"
37 |
38 | set ..%seriesCount = 0
39 | set n = $O(tMetrics(""))
40 | while (n'="") {
41 | set ..%seriesCount = ..%seriesCount + 1
42 | set ..%seriesNames(n) = $G(tMetrics(n))
43 | set ..%data(n,"Metric") = $G(^HoleFoods.CFO(n))
44 | set tDelta = $G(^HoleFoods.CFO(n,"delta"))
45 | set ..%data(n,"Trend") = $S(tDelta>0.05:tDelta,tDelta<-0.05:tDelta,1:0)
46 |
47 | set tLow = 0.5
48 | set tHigh = 0.8
49 | if (n=2) {
50 | // Special case for share price
51 | set tLow = 0.8
52 | set tHigh = 1.2
53 | }
54 |
55 | if (..%data(n,"Metric") < tLow) {
56 | set ..%data(n,"Alarm") = (tLow-..%data(n,"Metric"))*-100
57 | }
58 | elseif (..%data(n,"Metric") > tHigh) {
59 | set ..%data(n,"Alarm") = (..%data(n,"Metric")-tHigh)*100
60 | }
61 | else {
62 | set ..%data(n,"Alarm") = 0
63 | }
64 | set n = $O(tMetrics(n))
65 | }
66 | quit $$$OK
67 | }
68 |
69 | /// This callback is invoked from a dashboard when an action defined by this dashboard is invoked.
70 | ClassMethod %OnDashboardAction(pAction As %String, pContext As %ZEN.proxyObject) As %Status
71 | {
72 | #define EBIT 1
73 | #define SHARE 2
74 | #define AR 3
75 | #define AP 4
76 | #define DEBT 5
77 | #define INV 6
78 | #define MKT 7
79 |
80 | #define INCREASE(%n,%amt) set ^HoleFoods.CFO(%n) = ($G(^HoleFoods.CFO(%n)) * (1 + (($R(%amt)-(%amt*0.25))/100)))
81 | #define DECREASE(%n,%amt) set ^HoleFoods.CFO(%n) = ($G(^HoleFoods.CFO(%n)) * (1 + (($R(%amt)-(%amt*0.75))/100)))
82 |
83 | // Remember prior value so we can compute delta
84 | merge tPrior = ^HoleFoods.CFO
85 |
86 | if (pAction = "Spend") {
87 | $$$DECREASE($$$EBIT,40)
88 | $$$INCREASE($$$AP,40)
89 | $$$DECREASE($$$AR,5)
90 | $$$INCREASE($$$DEBT,30)
91 | $$$INCREASE($$$INV,20)
92 | $$$INCREASE($$$MKT,5)
93 | set pContext.command = "refresh"
94 | }
95 | elseif (pAction = "Cut Costs") {
96 | $$$INCREASE($$$EBIT,40)
97 | $$$DECREASE($$$AP,30)
98 | $$$INCREASE($$$AR,5)
99 | $$$DECREASE($$$DEBT,5)
100 | $$$DECREASE($$$INV,10)
101 | $$$DECREASE($$$MKT,5)
102 | set pContext.command = "refresh"
103 | }
104 | elseif (pAction = "Raise Prices") {
105 | $$$INCREASE($$$EBIT,20)
106 | $$$INCREASE($$$AR,30)
107 | $$$DECREASE($$$DEBT,10)
108 | $$$INCREASE($$$INV,10)
109 | $$$DECREASE($$$MKT,10)
110 | set pContext.command = "refresh"
111 | }
112 | elseif (pAction = "Cut Prices") {
113 | $$$DECREASE($$$EBIT,40)
114 | $$$DECREASE($$$AR,30)
115 | $$$INCREASE($$$DEBT,10)
116 | $$$DECREASE($$$INV,30)
117 | $$$INCREASE($$$MKT,10)
118 | set pContext.command = "refresh"
119 | }
120 | elseif (pAction = "Reset") {
121 | kill ^HoleFoods.CFO
122 | set ^HoleFoods.CFO(1) = 0.8
123 | set ^HoleFoods.CFO(2) = 0.6
124 | set ^HoleFoods.CFO(3) = 0.8
125 | set ^HoleFoods.CFO(4) = 0.8
126 | set ^HoleFoods.CFO(5) = 0.8
127 | set ^HoleFoods.CFO(6) = 0.8
128 | set ^HoleFoods.CFO(7) = 0.5
129 |
130 | // Send refresh command to client
131 | set pContext.command = "refresh"
132 | }
133 |
134 | if ($G(^HoleFoods.CFO($$$MKT)) > 0.95) {
135 | // No monopolies
136 | set ^HoleFoods.CFO($$$MKT) = 0.95
137 | }
138 |
139 |
140 | // Share price is average of all!
141 | // but each "zero" takes away points
142 | set tTotal = 0
143 | set tCount = 0
144 | set tZeroes = 0
145 | set n = $O(^HoleFoods.CFO(""))
146 | while (n'="") {
147 | set tValue = $G(^HoleFoods.CFO(n))
148 | if (tValue <= 0) {
149 | set ^HoleFoods.CFO(n) = 0
150 | }
151 | if (tValue < 0.2) {
152 | set tZeroes = tZeroes + 1
153 | }
154 | if (tValue >= 1.5) {
155 | set ^HoleFoods.CFO(n) = 1.5
156 | }
157 | set tCount = tCount + 1
158 | set tTotal = tTotal + tValue
159 | set n = $O(^HoleFoods.CFO(n))
160 | }
161 | if (tCount>0) {
162 | set ^HoleFoods.CFO($$$SHARE) = (tTotal/tCount) / (tZeroes+1)
163 | if (^HoleFoods.CFO($$$SHARE)<=0) {
164 | // Out of business
165 | set ^HoleFoods.CFO($$$SHARE) = 0
166 | }
167 | }
168 |
169 | // Compute deltas, if any
170 | set n = $O(tPrior(""))
171 | while (n'="") {
172 | set tOld = $G(tPrior(n))
173 | if (tOld'="") {
174 | set ^HoleFoods.CFO(n,"delta") = $G(^HoleFoods.CFO(n)) - tOld
175 | }
176 | set n = $O(tPrior(n))
177 | }
178 |
179 | quit $$$OK
180 | }
181 |
182 | }
183 |
184 |
--------------------------------------------------------------------------------
/src/cls/BI/Study/Diagnosis.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | ///
This class is part of the BI Patients sample, whose purpose is to provide
3 | /// sample data for use with InterSystems IRIS BI.
4 | /// This class contains the diagnosis code lookup table, with a small set of possible
5 | /// diagnoses. It also defines the incidence rates for these diagnoses, by age and gender.
6 | /// You can extend or modify the data contained here by editing the XData block in this class.
7 | /// Use the GetPercentChance() method to retrieve the chance of having
8 | /// a specific diagnosis, given an age and gender.
9 | Class BI.Study.Diagnosis Extends %Persistent
10 | {
11 |
12 | /// Unique code for the diagnosis;
13 | Property Code As %String;
14 |
15 | /// Unique description (user-visible name) for the diagnosis
16 | Property Description As %String;
17 |
18 | /// A row element is a pieced string with the following format:
19 | ///
23 | /// Each bucket represents an age bucket and the number of current (not lifetime)
24 | /// diagnoses of this type per hundred patients of this age and gender.
25 | /// Each bucket has the following format:
26 | ///
27 | /// Each row must have data for all ages for patients of either gender.
28 | /// Asthma source: ASTHMA06FINAL.PDF from www.lungusa.org/atf/cf/
29 | /// CHD: www.heartstats.org (used numbers for 1998)
30 | /// Diabetes: www.mchd.com/data_reports/mccha/12_Morbidity_and_Hospitalizations.html (Used U.S. values)
31 | /// Osteoporosis source: http://www.surgeongeneral.gov/library/bonehealth/ (No data for patients under 65)
32 | /// Epilepsy: wikipedia (55 cases per 100000 people)
33 | XData LoadData
34 | {
35 |
57 | }
58 |
59 | /// This method reads the XData block in this class and uses it to populate the table.
60 | /// This method is called by BI.Populate:GenerateData().
61 | /// It also writes related data to a global for use when creating patients.
62 | /// The diagnosis incidence rates are deliberately NOT put into a table where
63 | /// BI can access them. The idea of the sample is to simulate real-life
64 | /// patterns.
65 | ClassMethod Setup() As %Status
66 | {
67 | set status=$$$OK
68 |
69 | // First kill extent and related global
70 | // Never use %KillExtent() in a real application
71 | do ..%KillExtent()
72 | kill ^BI.Study.SetupData("diagnoses")
73 |
74 | // Get a stream of XML from the XData block contained in this class
75 | set tStream=##class(%Dictionary.CompiledXData).IDKEYOpen($CLASSNAME(),"LoadData").Data
76 | if '$IsObject(tStream) {set tSC=%objlasterror quit}
77 |
78 | set status=##class(%XML.TextReader).ParseStream(tStream,.textreader)
79 |
80 | // Check status
81 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
82 |
83 | // Iterate through document, node by node
84 | while textreader.Read()
85 | {
86 | if (textreader.NodeType="chars")
87 | {
88 | set value=textreader.Value
89 | set obj=..%New()
90 | set diagcode=$Piece(value,"^",1) ;use this below in multiple places
91 | set obj.Code=diagcode
92 | set obj.Description=$Piece(value,"^",2)
93 | set status=obj.%Save()
94 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
95 |
96 | // Now set global to contain occurrence rates by gender and age
97 | set fpiece=$ZSTRIP($Piece(value,"^",3),"*CW") ; strip out line feed & white space
98 | set mpiece=$ZSTRIP($Piece(value,"^",4),"*CW") ; strip out line feed & white space
99 |
100 | set ^BI.Study.SetupData("diagnoses",diagcode,"F")=fpiece
101 | set ^BI.Study.SetupData("diagnoses",diagcode,"M")=mpiece
102 | }
103 |
104 | }
105 |
106 | quit status
107 | }
108 |
109 | /// For use when generating data; called by Setup method.
110 | /// Can also use this at the command line for testing purposes.
111 | ClassMethod GetPercentChance(code As %String, gender As %String, age As %Numeric) As %Numeric
112 | {
113 | // Get appropriate global node & convert it to a list
114 | set list=$LISTFROMSTRING(^BI.Study.SetupData("diagnoses",code,gender))
115 |
116 | set chance=0
117 | // Iterate through list and find appropriate bucket
118 | for i=1:1:$LISTLENGTH(list) {
119 | // Get list item and its upper and lower ages
120 | set item=$LISTGET(list,i)
121 | set itemlowerage=+$Piece(item,"_",1)
122 | set itemupperage=+$Piece(item,"_",2)
123 |
124 | if ((age>itemlowerage) && (age<=itemupperage)) {
125 | set chance=$Piece(item,"_",3)
126 | }
127 | }
128 |
129 | quit chance
130 | }
131 |
132 | Storage Default
133 | {
134 |
135 |
136 | %%CLASSNAME
137 |
138 |
139 | Code
140 |
141 |
142 | Description
143 |
144 |
145 | ^BI.Study.DiagnosisD
146 | DiagnosisDefaultData
147 | ^BI.Study.DiagnosisD
148 | ^BI.Study.DiagnosisI
149 | ^BI.Study.DiagnosisS
150 | %Storage.Persistent
151 | }
152 |
153 | }
154 |
155 |
--------------------------------------------------------------------------------
/src/cls/BI/Study/PatientDetails.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is part of the BI Patients sample, whose purpose is to provide
3 | /// sample data for use with InterSystems IRIS BI.
4 | /// It represents an additional table of data,
5 | /// perhaps entered by a separate research team, and its only connection to
6 | /// BI.Study.Patient is that both tables have the same PatientID field. Thus to use
7 | /// fields of this table as BI dimensions/levels, it is necessary to use an SQL query
8 | /// in the dimension definition.
9 | /// This table is populated only if you use the T option when running the
10 | /// GenerateData() method in BI.Populate.
11 | Class BI.Study.PatientDetails Extends %Persistent
12 | {
13 |
14 | Property PatientID As %String;
15 |
16 | Property Profession As BI.Study.Profession;
17 |
18 | Property FavoriteColor As %String;
19 |
20 | /// This index is meant to improve performance when the BI indices are built.
21 | /// The BI data model for BI.Study.Patient uses an SQL query that refers
22 | /// to PatientID.
23 | Index PatientIDIndex On PatientID [ Unique ];
24 |
25 | /// Called by BI.Study.Patient:AddPatients().
26 | ClassMethod CreatePatientDetails(PatientID As %String, age As %Numeric = 35, genNulls As %Boolean) As %Status
27 | {
28 | set status=$$$OK
29 | set patdetails=##class(PatientDetails).%New()
30 | set patdetails.PatientID=PatientID
31 |
32 | // Get random color
33 | set colorlist=$LB("Red","Blue","Green","Purple","Yellow","Orange")
34 | set colorid=$RANDOM($LISTLENGTH(colorlist))+1
35 | set patdetails.FavoriteColor=$LI(colorlist,colorid)
36 |
37 | if ((age>17) && (age<70))
38 | {
39 | // Not everyone in this age range is employed
40 | if ##class(BI.Populate).RandomTrue(87){
41 | // Get random profession
42 | set profid=##class(BI.Populate).GetRandomId("BI.Study.Profession")
43 | set patdetails.Profession=##class(BI.Study.Profession).%OpenId(profid,0)
44 | }
45 | }
46 |
47 | if 'genNulls
48 | {
49 | // If genNulls is off, save details in all cases
50 | set status=patdetails.%Save()
51 | if $$$ISERR(status) {Do $System.Status.DisplayError(status) Write !, "Details error"}
52 | }
53 | Else
54 | {
55 | // If genNulls is on, roll the dice and
56 | // save the details only some of the time
57 | if ##class(BI.Populate).RandomTrue(76)
58 | {
59 | set status=patdetails.%Save()
60 | if $$$ISERR(status) {Do $System.Status.DisplayError(status) Write !, "Patient details save error"}
61 | }
62 | }
63 |
64 | quit status
65 | }
66 |
67 | /// Iterate through patient extent and change color for some percentage of patients.
68 | /// If rebuild is 1, this method updates the BI indices for each patient
69 | /// affected by these changes.
70 | ClassMethod ChangePatientDetails(percent As %Numeric = 10, rebuild As %Boolean = 1)
71 | {
72 | set ^BI.Study.Log($I(^BI.Study.Log))=$zdatetime($h,2,3)_" Changing some patient details..."
73 |
74 | // Create or update the "ID extent sets" from which we can later get random IDs
75 | set status=##class(BI.Populate).UpdateIdCache($CLASSNAME())
76 |
77 | set recordcount=##class(BI.Populate).Count($CLASSNAME())
78 | set changecount=0
79 |
80 | set colorlist=$LB("Red","Blue","Green","Purple","Yellow","Orange")
81 |
82 | for i=1:1:recordcount
83 | {
84 | if ##class(BI.Populate).RandomTrue(percent)
85 | {
86 | set colorid=$RANDOM($LISTLENGTH(colorlist))+1
87 |
88 | set randomid=##class(BI.Populate).GetRandomId($CLASSNAME())
89 | set patdetails=..%OpenId(randomid)
90 | set patdetails.FavoriteColor=$LI(colorlist,colorid)
91 | do patdetails.%Save()
92 | set changecount=changecount+1
93 |
94 | if rebuild {
95 | // Because the BI.Study.Patient table is unaware of the BI.Study.PatientDetails
96 | // table, changing info in PatientDetails does NOT fire any triggers for
97 | // the patients, so it is necessary to figure out which patients are
98 | // affected and update the indices for those patients
99 |
100 | set patID=patdetails.PatientID
101 |
102 | set myquery="SELECT ID FROM BI_Study.Patient WHERE PatientID=?"
103 | set rset=##class(%ResultSet).%New("%DynamicQuery:SQL")
104 | set status=rset.Prepare(myquery)
105 | if $$$ISERR(status) {Do $System.Status.DisplayError(status) quit}
106 | set status=rset.Execute(patID)
107 | if $$$ISERR(status) {Do $System.Status.DisplayError(status) quit}
108 | while rset.Next() {
109 | set id=rset.Data("ID")
110 |
111 | do ##class(%DeepSee.Utils).%ProcessFact("patients",id)
112 |
113 | }
114 | kill rset
115 |
116 | }
117 | }
118 | }
119 | if rebuild {kill %this} ; needed because zzBuildOne doesn't clean this up
120 | set ^BI.Study.Log($I(^BI.Study.Log))=$zdatetime($h,2,3)_" Details changed for "_ changecount _" patients"
121 | }
122 |
123 | /// Clear out patient details
124 | ClassMethod DeletePatientDetails(PatientID As %String) As %Status
125 | {
126 |
127 | set myquery="DELETE FROM BI_Study.PatientDetails WHERE PatientID=?"
128 | set rset=##class(%ResultSet).%New("%DynamicQuery:SQL")
129 | set status=rset.Prepare(myquery)
130 | if $$$ISERR(status) {Do $System.Status.DisplayError(status) quit}
131 | set status=rset.Execute(PatientID)
132 | quit status
133 | }
134 |
135 | Storage Default
136 | {
137 |
138 |
139 | %%CLASSNAME
140 |
141 |
142 | PatientID
143 |
144 |
145 | Profession
146 |
147 |
148 | FavoriteColor
149 |
150 |
151 | ^BI.Study.PatientDetailsD
152 | PatientDetailsDefaultData
153 | ^BI.Study.PatientDetailsD
154 | ^BI.Study.PatientDetailsI
155 | ^BI.Study.PatientDetailsS
156 | %Storage.Persistent
157 | }
158 |
159 | }
160 |
161 |
--------------------------------------------------------------------------------
/src/cls/BI/Utils/MDXAutoFiltersKPI.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// Use this superclass to create an MDX-based KPI that automatically
3 | /// adds a %FILTER clause to your MDX query. The %FILTER clause includes
4 | /// any selections in any filters that use levels from the appropriate cube.
5 | /// To use this superclass:
6 | /// Specify sourceType="mdx" in <kpi>.
7 | /// Specify a query within the mdx attribute of <kpi>
8 | /// Specify the CUBE parameter so that we can automatically fetch the members
9 | /// of the levels for use as filters.
10 | /// Instead, all levels of the associated cube are automatically available as filters.
11 | /// Or, if you want more control over the form of the query, override %OnGetMDX() as usual
12 | /// and include the following line after creating your basic MDX query:
13 | /// set pMDX=pMDX_..FilterBuilder()
14 | /// This method gets the current filter state, creates the %FILTER clause,
15 | /// and tacks it on to the end of your query.
16 | /// If you want more control over the members of one or more filters, override
17 | /// %OnGetFilterMembers() as usual. To get all the members for a given level/filter,
18 | /// use this: set sc=..%GetMembersForFilter(..#CUBE,pFilter,.pMembers)
19 | /// And then do something different as needed in other scenarios.
20 | /// To add additional filters (to be used in a different way):
21 | /// Within , declare the filters that you want to make available.
22 | /// The logical name for each filter must be of the form of an MDX level specifier, e.g.,
23 | /// [dimension].[hierarchy].[level]. This is needed so that we can retrieve the
24 | /// level members.
25 | /// Override %OnGetFilters(). In your implementation, get the filters from the
26 | /// cube by calling #super() and then add your custom filters to the array.
27 | Class BI.Utils.MDXAutoFiltersKPI Extends %DeepSee.KPI [ Abstract ]
28 | {
29 |
30 | /// Specifies the cube that this KPI uses. Specify the logical cube name.
31 | Parameter CUBE As %String;
32 |
33 | /// Implementation; can be overridden.
34 | ClassMethod %OnGetFilterMembers(pFilter As %String, Output pMembers As %List, pSearchKey As %String = "", pDataSourceName As %String = "") As %Status
35 | {
36 | set sc=..%GetMembersForFilter(..#CUBE_".cube",pFilter,.pMembers)
37 | quit sc
38 | }
39 |
40 | /// Implementation; can be overridden.
41 | Method %OnGetMDX(ByRef pMDX As %String) As %Status
42 | {
43 | set pMDX=pMDX_..FilterBuilder()
44 | quit $$$OK
45 | }
46 |
47 | /// Examines the filters defined in the cube, determines the current value of each,
48 | /// returns a string that can be used as the %FILTER clause.
49 | Method FilterBuilder() As %String [ Internal, Private ]
50 | {
51 | set tFilters=""
52 | set tSC = ##class(%DeepSee.Dashboard.Utils).%GetFiltersForDataSource(..#CUBE_".cube",.tFilters)
53 | quit:$$$ISERR(tSC) ""
54 |
55 | // Iterate through defined filters and build up usedFilters array
56 | set i = "",usedFilters=0
57 | for {
58 | set i = $order(tFilters(i))
59 | quit:i=""
60 |
61 | set filter=tFilters(i)
62 | set filterName=$LI(filter,2)
63 | set filterValue=$PROPERTY(..%filterValues,filterName)
64 |
65 | if filterValue'="" {
66 | set usedFilters=usedFilters+1
67 | do ..ParseFilterValue(filterValue,.FilterStateArray)
68 | // create usedFilters array
69 | //used FilterStateArray and build the string for this filter
70 | set string=..BuildString(filterName,.FilterStateArray)
71 | set usedFilters(usedFilters)=string
72 | } ; end of looking at non-null filters
73 |
74 | } ; end of looking at defined filters
75 |
76 | set where=""
77 | if usedFilters>=1 {
78 | set where=..CombineFilterStrings(.usedFilters)
79 | }
80 | quit where
81 | }
82 |
83 | /// Uses usedFilters array and returns a string that can be used
84 | /// as the %FILTER clause of a MDX query.
85 | ClassMethod CombineFilterStrings(ByRef usedFilters) As %String [ Private ]
86 | {
87 | set where=""
88 | if (usedFilters=1) {
89 | set where=" %FILTER "_usedFilters(1)
90 | } elseif (usedFilters>1) {
91 | set where=usedFilters(1)
92 | for i=2:1:usedFilters {
93 | set where="NONEMPTYCROSSJOIN("_usedFilters(i)_","_where_")"
94 | }
95 | set where=" %FILTER "_where
96 | }
97 | quit where
98 | }
99 |
100 | /// Given a filter value, returns, by reference, a FilterStateArray,
101 | /// which describes the filter state.
102 | ClassMethod ParseFilterValue(filterValue As %String, Output FilterStateArray) As %Status [ Private ]
103 | {
104 | // Initialize this node
105 | kill FilterStateArray
106 | set FilterStateArray("not")=0
107 |
108 | Set filterValue = $ZSTRIP(filterValue,"<>W")
109 | set firstbit=$EXTRACT(filterValue,1,4)
110 | if firstbit="%NOT" {
111 | set FilterStateArray("not")=1
112 | set filterValue=$EXTRACT(filterValue,6,*)
113 | }
114 |
115 | // Now check if we have a set
116 | set nextbit=$EXTRACT(filterValue)
117 | if nextbit="{" {
118 | // Take off { from the start and } from the end
119 | set filterValue=$EXTRACT(filterValue,2,*-1)
120 |
121 | // Parse the list of values the same way that Joe does
122 | Set valueCount=..%SplitList(filterValue,.tList)
123 | set FilterStateArray=valueCount
124 | for i=1:1:valueCount {
125 | set FilterStateArray(i)=tList(i)
126 | }
127 |
128 | } else {
129 | // List has only 1 item; put it into the array
130 | set FilterStateArray=1
131 | set FilterStateArray(1)=filterValue
132 | }
133 |
134 | quit $$$OK
135 | }
136 |
137 | /// Given a filter name and a FilterStateArray,
138 | /// returns a string that can be used as an MDX set.
139 | ClassMethod BuildString(filterName, ByRef FilterStateArray) As %String [ Private ]
140 | {
141 | if (FilterStateArray = 1) {
142 | set string=filterName_"."_FilterStateArray(1)
143 | if (FilterStateArray("not")=1) {
144 | set string=string_".%NOT"
145 | }
146 | } else {
147 | set string="%OR({"
148 | for i=1:1:FilterStateArray{
149 | set string=string_filterName_"."_FilterStateArray(i)_","
150 | }
151 | // Remove trailing comma and close set (which is wrapped in %OR)
152 | set string=$EXTRACT(string,1,*-1)
153 | set string=string_"})"
154 |
155 | // Deal with NOT case
156 | if FilterStateArray("not")=1 {
157 | set string="EXCEPT("_filterName_".MEMBERS,"_string_")"
158 | }
159 | }
160 | quit string
161 | }
162 |
163 | ClassMethod %OnGetFilterList(Output pFilters As %List, pDataSourceName As %String = "") As %Status
164 | {
165 | set tSC = ##class(%DeepSee.Dashboard.Utils).%GetFiltersForDataSource(..#CUBE_".cube",.tFilters)
166 | quit:$$$ISERR(tSC)
167 |
168 | set i = ""
169 | for {
170 | set i = $order(tFilters(i), 1, data)
171 | quit:i=""
172 |
173 | set pFilters($i(pFilters)) = $lb($lg(data,2), $lg(data,1),,1)
174 | }
175 | quit $$$OK
176 | }
177 |
178 | }
179 |
180 |
--------------------------------------------------------------------------------
/src/cls/BI/Study/PatientSet2.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is part of the BI Patients sample, whose purpose is to provide
3 | /// sample data for use with InterSystems IRIS BI.
4 | /// This class represents an additional set of patients collected
5 | /// by a separate research team and put into a separate table. It does
6 | /// not have all the properties that BI.Study.Patient has.
7 | /// For information on these properties and methods, see the corresponding
8 | /// comments in BI.Study.Patient.
9 | /// This table is populated only if you use the X option when running the
10 | /// GenerateData() method in BI.Populate.
11 | Class BI.Study.PatientSet2 Extends %Persistent
12 | {
13 |
14 | Property PatientID As %String;
15 |
16 | Property Gender As %String;
17 |
18 | Property Age As %Integer;
19 |
20 | Property PrimaryCarePhysician As BI.Study.Doctor;
21 |
22 | Property Allergies As list Of BI.Study.PatientAllergy;
23 |
24 | Property Diagnoses As list Of BI.Study.PatientDiagnosis;
25 |
26 | Property HomeCity As %String;
27 |
28 | Property PatientGroup As %String;
29 |
30 | Property TestScore As %Numeric;
31 |
32 | /// Called by BI.Populate:GenerateData(); see the comments for that method.
33 | ClassMethod GenerateData(patCount As %Integer = 500, options As %String = "ADT", genNulls As %Boolean = 1) As %Status
34 | {
35 | set status=$$$OK
36 | //first kill extent and kill extents of child tables
37 | //never use %KillExtent() in a real application
38 | do ..%KillExtent()
39 | set status=..AddPatients(patCount,options,genNulls)
40 | quit status
41 | }
42 |
43 | /// Called by BI.Populate:GenerateData(); see the comments for that method.
44 | /// Can also be called directly to add patients after the initial setup.
45 | ClassMethod AddPatients(patCount As %Integer = 500, options As %String = "AD", genNulls = 1) As %Status
46 | {
47 | set status=$$$OK
48 |
49 | // Check options; what do we need to generate?
50 | if ($FIND(options,"A")) {set generateallergies=1}
51 | else {set generateallergies=0}
52 | if ($FIND(options,"D")) {set generatediagnoses=1}
53 | else {set generatediagnoses=0}
54 |
55 | set dcount=##class(BI.Populate).Count("BI.Study.Diagnosis")
56 | set currentpatcount=##class(BI.Populate).Count($CLASSNAME())
57 | if (currentpatcount=0) {set initPat=5000}
58 | else {set initPat=patCount+1}
59 | set idnumber=initPat
60 |
61 | for n = 1:1:patCount {
62 | set pat=##class(BI.Study.PatientSet2).%New()
63 | set idnumber=idnumber+1 ; increment without any gaps
64 | set patid="SET2_"_idnumber
65 | set pat.PatientID=patid
66 |
67 | // Get age+gender combination
68 | set agegender=##class(BI.Populate).RandomGenderAndAge()
69 | set pat.Gender=$Piece(agegender,",",1)
70 | set pat.Age=$Piece(agegender,",",2)
71 |
72 | // Assign a doctor
73 | set docid=##class(BI.Populate).GetRandomId("BI.Study.Doctor")
74 | set doctor=##class(BI.Study.Doctor).%OpenId(docid,0)
75 | set pat.PrimaryCarePhysician=doctor
76 |
77 | // Null out this property randomly to simulate missing data
78 | if genNulls &#class(BI.Populate).RandomTrue(15){
79 | set pat.PrimaryCarePhysician=""
80 | }
81 |
82 | // Assign to a patient group
83 | set grouplist=$LB("Group A","Group B")
84 | set groupID=$RANDOM($LISTLENGTH(grouplist))+1
85 | set pat.PatientGroup=$LI(grouplist,groupID)
86 |
87 | // Set TestScore property and assign a test version
88 | set pat.TestScore=50+$RANDOM(50)
89 |
90 | // Null out the previous two properties in some cases
91 | // score can be null but won't be 0 (see above)
92 | // this lets us see how measures treat null values
93 | if (genNulls && ##class(BI.Populate).RandomTrue(20)){
94 | set pat.TestScore=""
95 | set pat.PatientGroup=""
96 | }
97 |
98 | // Select a city
99 | set cityid=##class(BI.Populate).GetRandomId("BI.Study.City")
100 | set city=##class(BI.Study.City).%OpenId(cityid,0)
101 | set pat.HomeCity=city.Name
102 |
103 | // If asked, generate some allergies
104 | if generateallergies {
105 | set status=##class(BI.Study.PatientAllergy).GenerateAllergies(pat,genNulls)
106 | if $$$ISERR(status) {do $System.Status.DisplayError(status) write !, "Allergies insert error"}
107 | }
108 |
109 | // If asked, generate some diagnoses
110 | if generatediagnoses {
111 | // Iterate through available diagnoses, look up chance of patient's
112 | // receiving this diagnosis, based on gender & age
113 | // save diagnosis data in all diagnosis properties
114 | set diagnosiscount=0 ; initialize this so we know if we're on the first one
115 | set diaglist=""
116 | for k=1:1:dcount{
117 | set potentialdiagnosis=##class(BI.Study.Diagnosis).%OpenId(k,0)
118 |
119 | // Get the code
120 | set code=potentialdiagnosis.Code
121 |
122 | // Look up how likely this patient is to have this diagnosis
123 | set chance=##class(BI.Study.Diagnosis).GetPercentChance(code,pat.Gender,pat.Age)
124 |
125 | if ##class(BI.Populate).RandomTrue(chance) {
126 | set diagnosiscount=diagnosiscount+1
127 | set desc=potentialdiagnosis.Description
128 | set diagdocid=##class(BI.Populate).GetRandomId("BI.Study.Doctor")
129 | set diagdoc=##class(BI.Study.Doctor).%OpenId(diagdocid,0)
130 |
131 | // Populate Diagnoses property
132 | set patdiag=##class(BI.Study.PatientDiagnosis).%New() ; this object is serial
133 | set patdiag.DiagnosisCode=code
134 | set patdiag.DiagnosedBy=diagdoc
135 | set status=pat.Diagnoses.Insert(patdiag)
136 | if $$$ISERR(status) {do $System.Status.DisplayError(status) write !, "Diagnoses error"}
137 | }
138 | }
139 |
140 | }
141 |
142 | set status=pat.%Save()
143 | if $$$ISERR(status) {do $System.Status.DisplayError(status) write !, "Patient save error"}
144 | if ('(n#1000)) {write $C(13,27)_"[0J"_$FN(n,",",0)_" patients created in BI.Study.Patient"}
145 |
146 |
147 | // Create an "extent set" from which we can later get random IDs
148 | set status=##class(BI.Populate).UpdateIdCache($CLASSNAME())
149 |
150 | write !
151 | write $C(13,27)_"[0J"_$FN(+$G(n),",",0)_" patient(s) created in BI.Study.PatientSet2"
152 | quit status
153 | }
154 | }
155 |
156 | Storage Default
157 | {
158 |
159 |
160 | %%CLASSNAME
161 |
162 |
163 | PatientID
164 |
165 |
166 | Gender
167 |
168 |
169 | Age
170 |
171 |
172 | PrimaryCarePhysician
173 |
174 |
175 | Allergies
176 |
177 |
178 | Diagnoses
179 |
180 |
181 | HomeCity
182 |
183 |
184 | PatientGroup
185 |
186 |
187 | TestScore
188 |
189 |
190 | ^BI.Study.PatientSet2D
191 | PatientSet2DefaultData
192 | ^BI.Study.PatientSet2D
193 | ^BI.Study.PatientSet2I
194 | ^BI.Study.PatientSet2S
195 | %Storage.Persistent
196 | }
197 |
198 | }
199 |
200 |
--------------------------------------------------------------------------------
/src/cls/BI/Study/PatientEncounter.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is part of the BI Patients sample, whose purpose is to provide
3 | /// sample data for use with InterSystems IRIS BI.
4 | /// A patient can have multiple encounters
5 | /// (interactions with a medical professional). The encounter data here is minimal, but you
6 | /// can create dimensions/levels based on the number of encounters a patient has, as well as
7 | /// on the attending physician for those encounters.
8 | /// This table is populated only if you use the E option when running the GenerateData()
9 | /// method in BI.Populate. You can also use the AddEncounters() method
10 | /// of this class to add encounters to existing patients.
11 | Class BI.Study.PatientEncounter Extends %Persistent
12 | {
13 |
14 | Property Patient As BI.Study.Patient;
15 |
16 | Property EncounterNumber As %String;
17 |
18 | Property PrimaryDoctor As BI.Study.Doctor;
19 |
20 | Property EncounterType As %String;
21 |
22 | /// Called by BI.Study.Patient:AddPatients().
23 | ClassMethod CreateEncounters(pat As BI.Study.Patient) As %Status
24 | {
25 |
26 | set encNo=100 ; starting value
27 |
28 | set encountercount=..GetRandomEncounterCount(pat.Age)
29 |
30 | set patnumber=$PIECE(pat.PatientID,"_",2) ; get number part from this string
31 | for i=1:1:encountercount {
32 | set encounter=##class(BI.Study.PatientEncounter).%New()
33 | set encounter.Patient=pat
34 | set encounter.EncounterNumber=patnumber_"-"_encNo
35 |
36 | set docid=##class(BI.Populate).GetRandomId("BI.Study.Doctor")
37 | set encounter.PrimaryDoctor=##class(BI.Study.Doctor).%OpenId(docid,0)
38 | set encounter.EncounterType=..GetRandomEncounterType()
39 |
40 | set status=encounter.%Save()
41 | set encNo=encNo+1
42 | }
43 | quit status
44 | }
45 |
46 | /// Iterate through patients and add encounters randomly to some percentage.
47 | /// if rebuild is 1, this method updates the BI indices for each patient
48 | /// affectedby these changes.
49 | ClassMethod AddEncounters(percent As %Numeric = 20, rebuild As %Boolean = 1) As %Status
50 | {
51 | set ^BI.Study.Log($I(^BI.Study.Log))=$zdatetime($h,2,3)_" Adding encounters..."
52 |
53 | // Create or update the "ID extent sets" from which we can later get random IDs
54 | set status=##class(BI.Populate).UpdateIdCache("BI.Study.Patient")
55 | set status=##class(BI.Populate).UpdateIdCache("BI.Study.Doctor")
56 |
57 | set patcount=##class(BI.Populate).Count("BI.Study.Patient")
58 | set changecount=0
59 |
60 | // First check to see if we have any encounter data; if we don't, we can add
61 | // encounters more quickly
62 | set myquery="SELECT Count(*) as ENCCOUNT FROM BI_Study.PatientEncounter"
63 | set rset=##class(%ResultSet).%New("%DynamicQuery:SQL")
64 | set status=rset.Prepare(myquery)
65 | if $$$ISERR(status) {Do $System.Status.DisplayError(status) Quit}
66 | set status=rset.Execute()
67 | if $$$ISERR(status) {Do $System.Status.DisplayError(status) Quit}
68 | set enccount=0
69 | while rset.Next() {
70 | set enccount=rset.Data("ENCCOUNT")
71 | }
72 |
73 | // Roll the dice as many times as we have patients; this is not the same
74 | // as iterating through the patients but does provide similar coverage
75 | for i=1:1:patcount
76 | {
77 | if ##class(BI.Populate).RandomTrue(percent)
78 | {
79 | set changecount=changecount+1
80 | set id=##class(BI.Populate).GetRandomId("BI.Study.Patient")
81 | set pat=##class(BI.Study.Patient).%OpenId(id,0)
82 | set patID=pat.%Id() ; use when querying extent
83 |
84 | // If we already have encounter data, we must
85 | // get highest number encounter for this patient, if any
86 | if (enccount>0) {
87 | set myquery="SELECT EncounterNumber FROM BI_Study.PatientEncounter WHERE Patient=? ORDER BY EncounterNumber"
88 | set rset=##class(%ResultSet).%New("%DynamicQuery:SQL")
89 | set status=rset.Prepare(myquery)
90 | if $$$ISERR(status) {Do $System.Status.DisplayError(status) Quit}
91 | set status=rset.Execute(patID)
92 | if $$$ISERR(status) {Do $System.Status.DisplayError(status) Quit}
93 | set result=""
94 | while rset.Next() {
95 | set result=rset.Data("EncounterNumber")
96 | }
97 | if (result'="") {
98 | set highestencno=result
99 | set encNo=$PIECE(highestencno,"-",2) + 1 ; increment by 1 from what's there
100 | } else {
101 | // This patient has no encounters yet
102 | set encNo=100
103 | }
104 | } else {
105 | set encNo=100
106 | }
107 |
108 | // Number of encounters to add
109 | set encountercount=$RANDOM(2)+1 ; ADD 1 or 2 encounters
110 |
111 | // Base part for encounter number
112 | set patnumber=$PIECE(pat.PatientID,"_",2) ; get number part from this string
113 |
114 | for j=1:1:encountercount {
115 | set encounter=##class(BI.Study.PatientEncounter).%New()
116 | set encounter.Patient=pat
117 | set encounter.EncounterNumber=patnumber_"-"_encNo
118 | set docid=##class(BI.Populate).GetRandomId("BI.Study.Doctor")
119 | set encounter.PrimaryDoctor=##class(BI.Study.Doctor).%OpenId(docid,0)
120 | set encounter.EncounterType=..GetRandomEncounterType()
121 |
122 | set status=encounter.%Save()
123 | set encNo=encNo+1
124 | }
125 |
126 | if rebuild {
127 | // Because the BI.Study.Patient table is unaware of the BI.Study.PatientEncounter
128 | // table, changing info in BI.Study.PatientEncounter does NOT fire any triggers for
129 | // the patients, so it is necessary to update the indices for those patients
130 | set id=pat.%Id()
131 |
132 | Do ##class(%DeepSee.Utils).%ProcessFact("patients",id)
133 | }
134 | }
135 | }
136 | set ^BI.Study.Log($I(^BI.Study.Log))=$zdatetime($h,2,3)_" Added encounters for "_changecount_" patients"
137 | // If rebuild {Kill %this} ; needed because zzBuildOne doesn't clean this up
138 | quit $$$OK
139 | }
140 |
141 | /// Clear out records in PatientEncounter; called when you delete patients.
142 | ClassMethod DeleteEncounters(pat As BI.Study.Patient) As %Status
143 | {
144 | set patid=pat.%Id()
145 | set myquery="DELETE FROM BI_Study.PatientEncounter WHERE Patient=?"
146 | set rset=##class(%ResultSet).%New("%DynamicQuery:SQL")
147 | set status=rset.Prepare(myquery)
148 | if $$$ISERR(status) {Do $System.Status.DisplayError(status) Quit}
149 | set status=rset.Execute(patid)
150 | quit status
151 | }
152 |
153 | ClassMethod GetRandomEncounterType() As %String
154 | {
155 | if ##class(BI.Populate).RandomTrue(5) {
156 | quit "Emergency"
157 | } elseif ##class(BI.Populate).RandomTrue(30) {
158 | quit "Outpatient"
159 | } else {
160 | quit "Inpatient"
161 | }
162 | }
163 |
164 | ClassMethod GetRandomEncounterCount(age As %Numeric) As %Integer
165 | {
166 | set factor=(age+1)*1.5
167 | set count=3 + $RANDOM(20) + $RANDOM(factor)
168 | quit count
169 | }
170 |
171 | Index PatientIndex On Patient;
172 |
173 | Storage Default
174 | {
175 |
176 |
177 | %%CLASSNAME
178 |
179 |
180 | Patient
181 |
182 |
183 | EncounterNumber
184 |
185 |
186 | PrimaryDoctor
187 |
188 |
189 | EncounterType
190 |
191 |
192 | ^BI.Study.PatientEncounterD
193 | PatientEncounterDefaultData
194 | ^BI.Study.PatientEncounterD
195 | ^BI.Study.PatientEncounterI
196 | ^BI.Study.PatientEncounterS
197 | %Storage.Persistent
198 | }
199 |
200 | }
201 |
202 |
--------------------------------------------------------------------------------
/src/cls/HoleFoods/Cube.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This is a sample DeepSee data model.
3 | /// This cube represents a model for the fictional "HoleFoods" corporation.
4 | /// It is based on the classes within the HoleFoods package.
5 | /// To create data for this model, the easiest thing to do is to
6 | /// use the BuildData method within the HoleFoods.Utils class:
7 | /// From the command line:
8 | ///
9 | /// Do ##class(HoleFoods.Utils).BuildData(1000000,1,1)
10 | ///
11 | /// The first argument is the number of records to create,
12 | /// the second argument indicates that index building should be done in parallel,
13 | /// the third is a verbose flag; if true, then progress is displayed as the data is built.
14 | Class HoleFoods.Cube Extends %DeepSee.CubeDefinition [ DependsOn = (HoleFoods.Transaction, HoleFoods.KPIAction) ]
15 | {
16 |
17 | Parameter DOMAIN = "HOLEFOODS";
18 |
19 | /// This xml document defines the HoleFoods model.
20 | XData Cube [ XMLNamespace = "http://www.intersystems.com/deepsee" ]
21 | {
22 |
29 |
30 |
32 |
33 |
36 |
37 |
40 |
41 |
44 |
45 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
88 |
91 |
94 |
95 |
100 |
101 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 | }
173 |
174 | }
175 |
176 |
--------------------------------------------------------------------------------
/src/cls/BI/Study/Doctor.cls:
--------------------------------------------------------------------------------
1 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
2 | /// This class is part of the BI Patients sample, whose purpose is to provide
3 | /// sample data for use with InterSystems IRIS BI.
4 | /// This class contains the doctors.
5 | Class BI.Study.Doctor Extends %Persistent
6 | {
7 |
8 | Property FirstName As %String(MAXLEN = 100);
9 |
10 | Property LastName As %String(MAXLEN = 100);
11 |
12 | /// City where this doctor primarily works;
13 | Property MainCity As BI.Study.City;
14 |
15 | /// Group into which this "study" places this doctor
16 | Property DoctorGroup As %String;
17 |
18 | /// Primary focus of this doctor's work;
19 | Property DoctorType As %String;
20 |
21 | /// Average number of patients that this doctor sees per week
22 | /// (included to provide a numeric value in this table)
23 | Property PatientsPerWeek As %Numeric;
24 |
25 | /// This method reads the XData block in this class and uses it to populate the table.
26 | /// This method is called by BI.Populate:GenerateData().
27 | ClassMethod GenerateData(count As %Integer = 100, genNulls = 1) As %Status
28 | {
29 | set status=$$$OK
30 | //first kill extent
31 | //never use %KillExtent() in a real application
32 | do ..%KillExtent()
33 | set ^BI.Study.SetupData("Pediatricians")=""
34 | set ^BI.Study.SetupData("OBGYNs")=""
35 | set ^BI.Study.SetupData("OtherDoctors")=""
36 |
37 |
38 | For n = 1:1:count {
39 | set doc = ##class(BI.Study.Doctor).%New()
40 | set doc.FirstName = ##class(%PopulateUtils).FirstName()
41 | set doc.LastName = ##class(%PopulateUtils).LastName()
42 |
43 | // Assign to a doctor group
44 | set grouplist=$LB("I","II","III")
45 | set groupID=$RANDOM($LISTLENGTH(grouplist))+1
46 | set doc.DoctorGroup=$LI(grouplist,groupID)
47 |
48 | // Set PatientsPerWeek property
49 | set doc.PatientsPerWeek=130+$RANDOM(40)
50 |
51 | // Null out the previous two properties in some cases
52 | if (genNulls && ##class(BI.Populate).RandomTrue(20)){
53 | set doc.PatientsPerWeek=""
54 | set doc.DoctorGroup=""
55 | }
56 |
57 |
58 | // Select a city
59 | set cityid=##class(BI.Populate).GetRandomId("BI.Study.City")
60 | set doc.MainCity=##class(BI.Study.City).%OpenId(cityid,0)
61 |
62 | // Specify the doctor type; these are assigned somewhat randomly
63 | if ##class(BI.Populate).RandomTrue(70) {
64 | set typelist=$LB("General Physician","Internist","Pediatrician","OB/GYN")
65 | set typeid=$RANDOM($LISTLENGTH(typelist))+1
66 | set doc.DoctorType=$LI(typelist,typeid)
67 | }
68 | else {
69 | set typelist=$LB("Anesthesiologist","Allergist","Cardiologist","Dermatologist",
70 | "Emergency Physician","Gastroenterologist","Radiologist","Surgeon")
71 | set typeid=$RANDOM($LISTLENGTH(typelist))+1
72 | set doc.DoctorType=$LI(typelist,typeid)
73 | }
74 | if (doc.DoctorType="Pediatrician") {
75 | set ^BI.Study.SetupData("Pediatricians")=^BI.Study.SetupData("Pediatricians")_","_n
76 | } elseif (doc.DoctorType="OB/GYN") {
77 | set ^BI.Study.SetupData("OBGYNs")=^BI.Study.SetupData("OBGYNs")_","_n
78 | } else {
79 | set ^BI.Study.SetupData("OtherDoctors")=^BI.Study.SetupData("OtherDoctors")_","_n
80 | }
81 |
82 | set status=doc.%Save()
83 | if $$$ISERR(status) {do $System.Status.DisplayError(status)}
84 |
85 | }
86 | set ^BI.Study.SetupData("Pediatricians")=$ZSTRIP(^BI.Study.SetupData("Pediatricians"),"<",",")
87 | set ^BI.Study.SetupData("OBGYNs")=$ZSTRIP(^BI.Study.SetupData("OBGYNs"),"<",",")
88 |
89 | // Create an "extent set" from which we can later get random IDs
90 | set status=##class(BI.Populate).UpdateIdCache($CLASSNAME())
91 | quit status
92 | }
93 |
94 | /// Randomly change doctor group and patients per week for some doctors.
95 | /// if rebuild is 1, this method updates the BI indices for each patient affected
96 | /// by these changes.
97 | ClassMethod ChangeSomeDoctors(percent As %Numeric = 20, rebuild As %Boolean = 1)
98 | {
99 | set ^BI.Study.Log($I(^BI.Study.Log))=$zdatetime($h,2,3)_" Changing some doctor data..."
100 |
101 | // Create an "extent set" from which we can later get random IDs
102 | set status=##class(BI.Populate).UpdateIdCache($CLASSNAME())
103 |
104 | set changecount=0
105 | set listLength=##class(BI.Populate).Count($CLASSNAME())
106 |
107 | // Throw the dice once as many times as we have doctors; not the same as
108 | // looping through doctors but close in overall effect
109 | for i=1:1:listLength {
110 | if ##class(BI.Populate).RandomTrue(percent)
111 | {
112 | set docid=##class(BI.Populate).GetRandomId($CLASSNAME())
113 | set doc=..%OpenId(docid)
114 |
115 | // Assign to a doctor group
116 | set grouplist=$LB("I","II","III")
117 | set groupID=$RANDOM($LISTLENGTH(grouplist))+1
118 | set doc.DoctorGroup=$LI(grouplist,groupID)
119 |
120 | // Set PatientsPerWeek property
121 | set doc.PatientsPerWeek=130+$RANDOM(40)
122 | do doc.%Save()
123 |
124 | if rebuild {
125 | // Because doctors are in a separate table, changing info for a
126 | // doctor does NOT fire any triggers for the patients,
127 | // so it is necessary to figure out which patients are affected
128 | // and update the indices for those patients
129 |
130 | set myquery="SELECT ID FROM BI_Study.Patient WHERE PrimaryCarePhysician=?"
131 | set rset=##class(%ResultSet).%New("%DynamicQuery:SQL")
132 | set status=rset.Prepare(myquery)
133 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
134 | set status=rset.Execute(docid)
135 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
136 | while rset.Next() {
137 | set patid=rset.Data("ID")
138 |
139 | do ##class(%DeepSee.Utils).%ProcessFact("patients",patid)
140 |
141 | }
142 | }
143 | set changecount=changecount+1
144 | }
145 | }
146 |
147 | // If rebuild {Kill %this} ; needed because zzBuildone doesn't clean this up
148 | set ^BI.Study.Log($I(^BI.Study.Log))=$zdatetime($h,2,3)_" "_changecount_" doctors changed"
149 | }
150 |
151 | /// Based on patient age (in years) and gender ("F" or "M"), return the ID of a suitable doctor
152 | ClassMethod GetDoctorId(patientAge As %Integer = "", patientGender As %String = "") As %Integer
153 | {
154 | if (patientAge="") {
155 | quit ..GetRandomOtherDoctor()
156 | } elseif (patientAge<12) {
157 | if ##class(BI.Populate).RandomTrue(90) {
158 | quit ..GetRandomPediatrician()
159 | } else {
160 | quit ..GetRandomOtherDoctor()
161 | }
162 | }
163 |
164 | if (patientGender="") {
165 | quit ..GetRandomOtherDoctor()
166 | } elseif (patientGender="F") {
167 | if ##class(BI.Populate).RandomTrue(70) {
168 | quit ..GetRandomOBGYN()
169 | } else {
170 | quit ..GetRandomOtherDoctor()
171 | }
172 | } else {
173 | quit ..GetRandomOtherDoctor()
174 | }
175 | }
176 |
177 | ClassMethod GetRandomPediatrician() As %Integer
178 | {
179 | set choosefrom=^BI.Study.SetupData("Pediatricians")
180 | set choosenumber=$L(choosefrom,",")
181 | set randomnumber=$RANDOM(choosenumber)+1
182 | set randomdoc=$P(choosefrom,",",randomnumber)
183 | quit randomdoc
184 | }
185 |
186 | ClassMethod GetRandomOBGYN()
187 | {
188 | set choosefrom=^BI.Study.SetupData("OBGYNs")
189 | set choosenumber=$L(choosefrom,",")
190 | set randomnumber=$RANDOM(choosenumber)+1
191 | set randomdoc=$P(choosefrom,",",randomnumber)
192 | quit randomdoc
193 | }
194 |
195 | ClassMethod GetRandomOtherDoctor()
196 | {
197 | set choosefrom=^BI.Study.SetupData("OtherDoctors")
198 | set choosenumber=$L(choosefrom,",")
199 | set randomnumber=$RANDOM(choosenumber)+1
200 | set randomdoc=$P(choosefrom,",",randomnumber)
201 | quit randomdoc
202 | }
203 |
204 | Storage Default
205 | {
206 |
207 |
208 | %%CLASSNAME
209 |
210 |
211 | FirstName
212 |
213 |
214 | LastName
215 |
216 |
217 | MainCity
218 |
219 |
220 | DoctorGroup
221 |
222 |
223 | DoctorType
224 |
225 |
226 | PatientsPerWeek
227 |
228 |
229 | ^BI.Study.DoctorD
230 | DoctorDefaultData
231 | ^BI.Study.DoctorD
232 | ^BI.Study.DoctorI
233 | ^BI.Study.DoctorS
234 | %Storage.Persistent
235 | }
236 |
237 | }
238 |
239 |
--------------------------------------------------------------------------------
/src/cls/BI/APISamples.cls:
--------------------------------------------------------------------------------
1 | Include %occInclude
2 |
3 | /// Use or operation of this code is subject to acceptance of the license available in the code repository for this code.
4 | Class BI.APISamples
5 | {
6 |
7 | /// Executes a hardcoded query and prints the results.
8 | /// Returns the result set as output.
9 | ClassMethod RunQuery1(Output result As %DeepSee.ResultSet) As %Status
10 | {
11 | set rset=##class(%DeepSee.ResultSet).%New()
12 | set query="SELECT MEASURES.[%COUNT] ON 0, diagd.MEMBERS ON 1 FROM patients"
13 | set status=rset.%PrepareMDX(query)
14 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit status}
15 |
16 | set status=rset.%Execute()
17 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit status}
18 |
19 | write !, "Full results are as follows ***************",!
20 | do rset.%Print()
21 | quit $$$OK
22 | }
23 |
24 | /// Executes a query that uses a named parameter and prints the results.
25 | /// Returns the result set as output.
26 | ClassMethod RunQuery2(city As %String = "Magnolia", Output result As %DeepSee.ResultSet) As %Status
27 | {
28 | set rset=##class(%DeepSee.ResultSet).%New()
29 | set query="WITH %PARM c AS 'value:Magnolia'"
30 | _"SELECT homed.[city].@c ON 0 FROM patients"
31 | set status=rset.%PrepareMDX(query)
32 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit status}
33 |
34 | set myparms("c")=city
35 | set status=rset.%Execute(.myparms)
36 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit status}
37 |
38 | write !, "Full results are as follows ***************",!
39 | do rset.%Print()
40 | quit $$$OK
41 | }
42 |
43 | /// Executes a query that does a detail listing and prints the results.
44 | /// Returns the result set as output.
45 | ClassMethod RunQuery3()
46 | {
47 | set rset=##class(%DeepSee.ResultSet).%New()
48 |
49 | set query="DRILLTHROUGH SELECT gend.female ON 0,birthd.[1913] ON 1 "
50 | _"FROM patients RETURN PatientID,PrimaryCarePhysician->LastName"
51 |
52 | set status=rset.%PrepareMDX(query)
53 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
54 |
55 | set status=rset.%Execute()
56 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
57 |
58 | write !, "Listing details for the first cell are as follows ***************",!
59 | do rset.%PrintListing()
60 | }
61 |
62 | /// Executes a query and prints the results.
63 | /// Then for comparison, displays a specific cell.
64 | ClassMethod ShowCell() As %Status
65 | {
66 | set rset=##class(%DeepSee.ResultSet).%New()
67 | set query="SELECT MEASURES.[avg age] ON 0, homed.[city].MEMBERS ON 1 "
68 | _"FROM patients"
69 | set status=rset.%PrepareMDX(query)
70 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit status}
71 |
72 | set status=rset.%Execute()
73 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit status}
74 |
75 | write !, "Full results are as follows ***************",!
76 | do rset.%Print()
77 |
78 | write !, "Cell 1,5 is as follows ***************",!
79 | write rset.%GetOrdinalValue(1,5)
80 | quit status
81 | }
82 |
83 | /// Executes a query and prints the results.
84 | /// Then for comparison, displays information about the row labels.
85 | ClassMethod ShowRowLabels() As %Status
86 | {
87 | set rset=##class(%DeepSee.ResultSet).%New()
88 | set query="SELECT CROSSJOIN(aged.[age group].MEMBERS,"
89 | _"gend.gender.MEMBERS) ON 1 FROM patients"
90 | set status=rset.%PrepareMDX(query)
91 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit status}
92 |
93 | set status=rset.%Execute()
94 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit status}
95 |
96 | write !, "Full results are as follows ***************",!
97 | do rset.%Print()
98 |
99 | write !, "Labels used on the rows are as follows ***************",!
100 | for j=1:1:rset.%GetRowCount() {
101 | write !, "Row ",j
102 | set labelcount=rset.%GetOrdinalLabel(.pLabel,2,j)
103 | For i=1:1:labelcount {
104 | write !, " label("_i_") is "_pLabel(i)
105 | }
106 | }
107 |
108 | quit $$$OK
109 | }
110 |
111 | /// Given a result set as input, this method generates a report on
112 | /// the query metadata.
113 | ClassMethod ShowQueryMetadata(rset As %DeepSee.ResultSet) As %Status
114 | {
115 | set cubename=rset.%GetCubeName()
116 | write !, "This result set comes from the following cube: ",cubename,!
117 |
118 | set status=rset.%GetParameterInfo(.pParms)
119 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit status}
120 | if $DATA(pParms) {
121 | write "The query uses the following parameters:",!
122 | set p = $ORDER(pParms(""))
123 | While (p '= "") {
124 | write $$$UPPER(p), " = " ,$GET(pParms(p,"VALUE")),!
125 | set p = $ORDER(pParms(p))
126 | }
127 | }
128 | set query=rset.%GetQueryText()
129 | write "The query is as follows:",!, query,!
130 |
131 | set isdrill=rset.%IsDrillThrough()
132 | if isdrill {
133 | set listingsql=rset.%GetListingSQL()
134 | write !!, "It uses the following SQL to drill into the source table:"
135 | write !, listingsql
136 | }
137 | }
138 |
139 | /// Given a result set as input, this method generates a report on
140 | /// the result metadata.
141 | ClassMethod ShowResultMetadata(rset As %DeepSee.ResultSet)
142 | {
143 | set cubename=rset.%GetCubeName()
144 | write !, "This result set comes from the cube ",cubename
145 |
146 | set querykey=rset.%GetQueryKey()
147 | set cellcount=##class(%DeepSee.ResultSet).%GetCellCount(cubename,querykey)
148 | write !, "It has ", cellcount, " cells"
149 |
150 | //For i=1:1:cellcount{
151 | // write !, "cell number ",i," has the value ",rset.%GetOrdinalValue(i)
152 | //}
153 | }
154 |
155 | /// Given a result set as input, this method generates a report on
156 | /// the slicer statement for a given cell range.
157 | ClassMethod ShowSlicerStatement(rset As %DeepSee.ResultSet, Row1 As %Integer = 1, Col1 As %Integer = 1, Row2 As %Integer, Col2 As %Integer) As %Status
158 | {
159 | if '$DATA(Row2) {set Row2=Row1}
160 | if '$DATA(Col2) {set Col2=Col1}
161 |
162 | set status=rset.%GetSlicerForCellRange(.slicer,Row1,Col1,Row2,Col2)
163 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit status}
164 |
165 | write !, "The requested cell range:"
166 | write !, " Columns ",Col1, " through ", Col2
167 | write !, " Rows ",Row1, " through ", Row2
168 |
169 | write !, "The slicer statement for the given cell range is as follows:"
170 | write !, slicer
171 |
172 | if 'rset.%IsDrillThrough(){
173 | write !!, "For comparison, the query results are as follows:",!
174 | do rset.%Print()
175 | }
176 | Else {
177 | write !!, "This is a drillthrough query and %Print "
178 | _"does not provide a useful basis of comparison"
179 | }
180 | }
181 |
182 | /// Executes a hardcoded query and returns a result set.
183 | ClassMethod GetResultSet1() As %DeepSee.ResultSet
184 | {
185 | set rset=##class(%DeepSee.ResultSet).%New()
186 | set query="SELECT {MEASURES.[avg test score],MEASURES.[%COUNT]} ON 0, "
187 | _"diagd.h1.diagnoses.MEMBERS ON 1 FROM patients"
188 | set status=rset.%PrepareMDX(query)
189 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit $$$NULLOREF}
190 |
191 | set status=rset.%Execute()
192 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit $$$NULLOREF}
193 |
194 | quit rset
195 | }
196 |
197 | /// Executes a hardcoded query and returns a result set.
198 | ClassMethod GetResultSet2(city As %String = "Magnolia") As %DeepSee.ResultSet
199 | {
200 | set rset=##class(%DeepSee.ResultSet).%New()
201 | set query="WITH %PARM c AS 'value:Magnolia'"
202 | _"SELECT homed.h1.[city].@c ON 0 FROM patients"
203 |
204 | set status=rset.%PrepareMDX(query)
205 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit $$$NULLOREF}
206 |
207 | set myparms("c")=city
208 | set status=rset.%Execute(.myparms)
209 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit $$$NULLOREF}
210 |
211 | quit rset
212 | }
213 |
214 | /// executes a hardcoded query and returns a result set
215 | ClassMethod GetResultSet3() As %DeepSee.ResultSet
216 | {
217 | set rset=##class(%DeepSee.ResultSet).%New()
218 | set query="DRILLTHROUGH SELECT gend.h1.gender.female ON 0,birthd.h1.year.[1913] ON 1 "
219 | _"FROM patients RETURN PatientID,PrimaryCarePhysician->LastName"
220 |
221 | set status=rset.%PrepareMDX(query)
222 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit $$$NULLOREF}
223 |
224 | set status=rset.%Execute()
225 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit $$$NULLOREF}
226 |
227 | quit rset
228 | }
229 |
230 | /// Executes a hardcoded query and returns a result set.
231 | ClassMethod GetResultSet4() As %DeepSee.ResultSet
232 | {
233 | set rset=##class(%DeepSee.ResultSet).%New()
234 | set query="SELECT CROSSJOIN(gend.h1.gender.MEMBERS,MEASURES.[%COUNT]) ON 0, "
235 | _"aged.h1.[age bucket].MEMBERS ON 1 FROM patients"
236 | set status=rset.%PrepareMDX(query)
237 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit $$$NULLOREF}
238 |
239 | set status=rset.%Execute()
240 | if $$$ISERR(status) {do $System.Status.DisplayError(status) quit $$$NULLOREF}
241 |
242 | quit rset
243 | }
244 |
245 | }
246 |
247 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Samples-BI
2 | This is the README file for SAMPLES-BI.
3 | The end of the file has setup instructions.
4 |
5 | - [Samples-BI](#samples-bi)
6 | - [Overview](#overview)
7 | - [Contents of the BI package](#contents-of-the-bi-package)
8 | - [Contents of the HoleFoods package](#contents-of-the-holefoods-package)
9 | - [Setup instructions](#setup-instructions)
10 | - [Setup with ZPM](#setup-with-zpm)
11 | - [Step-by-step Installation](#step-by-step-installation)
12 |
13 | ---
14 | Use or operation of this code is subject to acceptance of the license available in the code
15 | repository for this code.
16 |
17 | ---
18 |
19 | ## Overview
20 |
21 | Samples-BI is meant for use with the InterSystems IRIS Business Intelligence capabilities.
22 | In order to use this sample, you must have an InterSystems IRIS license that includes these capabilities.
23 |
24 | These classes provide sample data that you can use to explore the capabilities of InterSystems IRIS BI.
25 | They also demonstrate ways to create BI models using InterSystems IRIS BI.
26 |
27 | This sample contains two packages:
28 | * The `BI` package, which provides simple data representing a fictitious medical study, and also provides
29 | an InterSystems IRIS BI model that uses that data. See details below.
30 | * The `HoleFoods` package, which provides simple data representing sales of food products, and also provides
31 | an InterSystems IRIS BI model that uses that data. See details below.
32 |
33 | The documentation for InterSystems IRIS Business Intelligence refers extensively to these samples.
34 | The HoleFoods model provides a quick and easy introduction to BI, and the BI model demonstrates
35 | null handling, list-based levels, and other features not included in HoleFoods. The BI package also
36 | explicitly demonstrates how to address more difficult modeling scenarios.
37 |
38 | After setup:
39 | * You can use the Analyzer to explore these BI models; for information, go [here](http://docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls?KEY=D2ANLY_ch_intro)
40 | * You can open the InterSystems IRIS dashboard and explore the sample dashboards and pivot
41 | tables. For information, see [this](http://docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls?KEY=D2DASH)
42 | * You can work through the steps of creating a BI model, pivot tables, and dashboards.
43 | See [this](http://docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls?KEY=D2DT_ch_setup)
44 |
45 | The repository also includes a number of configuration files and scripts that are not part of the sample itself.
46 | Please refer to [dev.md] for more about the role of these files.
47 |
48 | ### Contents of the BI package
49 |
50 | This package provides simple data representing a fictitious medical study, and also provides
51 | an InterSystems IRIS BI model that uses that data.
52 |
53 | * `BI.Model` package contains the classes that demonstrate BI model capability.
54 | - `BI.Model.PatientsCube` is the primary model; this defines the PATIENTS cube that is
55 | used in the MDX reference documentation and for most of the sample queries in the documentation.
56 | Other classes in BI.Model demonstrate special cases of various kinds; see the BI modeling guides.
57 | - `BI.Model.CompoundCube` package contains multiple cube definitions that collectively
58 | demonstrate how to create a compound cube. The Advanced Modeling guide discusses these cubes.
59 | - `BI.Model.KPIs` package contains sample InterSystems IRIS BI KPIs (key performance indicators).
60 | All of these KPIs are either discussed in the modeling guides or are used in the sample dashboards,
61 | to demonstrate different kinds of widgets.
62 | - `BI.Model.Portlet` package demonstrates a sample custom portlet. For details, see the
63 | Advanced Modeling guide.
64 | - `BI.Model.RelCube` package contains multiple cube definitions that collectively
65 | demonstrate how to create a set of related cubes. For details, see the Advanced Modeling guide.
66 | - `BI.Model.SubjectAreas` package contains multiple class definitions that that define
67 | subject areas, which are filtered cube definitions. The documentation refers to these in several
68 | places. The subject area DEMOMDX (`DeepSee.Model.DemoMDX`) is meant for use in getting familiar
69 | with MDX.
70 |
71 | * `BI.Study` package contains the classes that generate the data used by these models. The most
72 | important classes are these:
73 | - `BI.Study.Patient` is the central class and provides the source table for the PATIENTS cube.
74 | The patients are generated in an age-sex distribution that follows the 2010 US Census data.
75 | - `BI.Diagnosis` generates the diagnosis data used when generating patients. This diagnosis
76 | data consists of a small set of diagnoses for chronic conditions, along with morbidity data
77 | for these conditions (that is, chance of having this condition, based on age & sex). When data
78 | for a patient is generated, the patient is assigned zero or more diagnoses, based on the
79 | patient's age and sex, using this data.
80 | - `BI.Allergen` generates a common set of allergens, and BI.AllergySeverity generates a
81 | common set of allergy severities. When data for a patient is generated, the patient is assigned
82 | zero or more allergies, each to an allergen, with a specific severity. This enables BI modelers to
83 | explore multiple list-based levels and see how they relate to each other.
84 | - `BI.Study.Profession` generates a set of professions, to which the working-age patients are
85 | assigned.
86 |
87 | * `BI.Utils.MDXAutoFiltersKPI` is a sample class that adds cube-based filters to a KPI, when used
88 | as a superclass for that KPI. This class is discussed in the advanced modeling guide.
89 |
90 | * `BI.APISamples` demonstrates how to execute BI queries programmatically on the server. For details,
91 | see the BI implementation guide.
92 |
93 | * `BI.DashboardsEtc` contains the pivot table and dashboard definitions based on the models in
94 | the BI.Model package.
95 |
96 | * `BI.Populate` contains the wrapper code used to generate the data for this part of the BI sample.
97 |
98 | ### Contents of the HoleFoods package
99 |
100 | This package provides simple data representing sales of food products, and also provides
101 | an InterSystems IRIS BI model that uses that data.
102 | * `HoleFoods.Transaction`, `HoleFoods.Country`, `HoleFoods.Outlet`, `HoleFoods.Product`, and `HoleFoods.Region`
103 | generate the data. `HoleFoods.Transation` provides the source table used by the cube definitions
104 | for this part of the sample.
105 | * `HoleFoods.Cube` defines the HOLEFOODS cube, which is meant as a quick and easy introduction to BI
106 | in InterSystems IRIS. The documentation refers to this cube in numerous places.
107 | * `HoleFoods.BudgetCube` and `HoleFoods.CombinedCube` demonstrate a compound cube.
108 | * `HoleFoods.KPI*` classes define sample InterSystems IRIS BI KPIs (key performance indicators).
109 | For details, see the advanced modeling guide.
110 | * `HoleFoods.SampleListingGroup` is a sample listing group class. Via listing groups, you can define
111 | detail listings without modifying the cube definition. For details, see the modeling guides.
112 | * `HoleFoods.SubjectAreaAsia` is a sample subject area. For details, see the modeling guides.
113 | * `HoleFoods.Utils` contains the code used to generate data for the HoleFoods part of the BI sample.
114 | It also contains methods you can use to add or delete data, thus exercising techniques for
115 | keeping the cube contents synchronized with the source data.
116 |
117 | ## Setup instructions
118 |
119 | ### Setup with ZPM
120 |
121 | ZPM stands for ObjectScript Package Manager. It provides a simple and unified way to install ObjectScript modules [Learn More](https://community.intersystems.com/post/introducing-intersystems-objectscript-package-manager). You can either install ZPM on an existing InterSystems IRIS instance based on [these instructions](https://github.com/intersystems-community/zpm), or use one of the prebuilt Community Edition Docker images that have it pre-installed. The instructions below are for the latter option. If you already have ZPM installed, you can immediately proceed to jump to step 4.
122 |
123 | 0. Make sure you have [Docker-desktop](https://www.docker.com/products/docker-desktop) installed.
124 |
125 | 1. Pull the latest IRIS Community Edition image with zpm:
126 | ```Shell
127 | $ docker pull intersystemsdc/iris-community:latest
128 | ```
129 | You can take the latest tag of IRIS or IRIS for Health Community Edition with ZPM [here](https://hub.docker.com/r/intersystemsdc/iris-community)
130 |
131 | 2. Run IRIS container with ZPM:
132 | ```Shell
133 | $ docker run --name irisce -d --publish 52773:52773 intersystemsdc/iris-community:latest
134 | ```
135 | 3. RUN IRIS terminal
136 | ```Shell
137 | docker exec -it irisce iris session iris
138 | Node: c6e0f00b8d42, Instance: IRIS
139 |
140 | USER>
141 | ```
142 |
143 | 4. From the IRIS terminal, start ZPM and install Samples-BI:
144 | ```
145 | USER>zpm
146 | zpm: USER>install samples-bi
147 |
148 | [samples-bi] Reload START
149 | [samples-bi] Reload SUCCESS
150 | [samples-bi] Module object refreshed.
151 | [samples-bi] Validate START
152 | [samples-bi] Validate SUCCESS
153 | [samples-bi] Compile START
154 | [samples-bi] Compile SUCCESS
155 | [samples-bi] Activate START
156 | 2,187 row(s) created
157 | Building cube [HOLEFOODS]
158 | ...
159 | Complete
160 | Elapsed time: 0.009120s
161 | Source expression time: 0.000307s
162 | Defining term list Patients Pivots...
163 | Defining term list Patients RowSpecs...
164 | Defining YEAR pivot variable in PATIENTS cube
165 |
166 | [samples-bi] Configure SUCCESS
167 | [samples-bi] Activate SUCCESS
168 | ```
169 | 5. Open IRIS analytics portal and work with Samples-BI:
170 | http://localhost:52773/csp/user/_DeepSee.UserPortal.Home.zen?$NAMESPACE=USER
171 |
172 | ### Step-by-step Installation
173 |
174 | 1. Clone or [download](http://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=asamples) the repository. If you downloaded a ZIP, extract the files to a directory on the server. You will need to refer to these files' location in step 8.
175 | 2. If you have not yet created a namespace in InterSystems IRIS, follow the [detailed instructions](http://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=ASAMPLES_createns) to do so.
176 | 3. In the Management Portal, click System Administration > Security > Applications > Web Applications.
177 | 4. Click the link in the first column of the row /csp/mynamespace where `mynamespace` is the namespace from step 2.
178 | 5. Click the Analytics checkbox and then click Save.
179 |
180 | 6. Open the InterSystems IRIS Terminal.
181 | 7. Enter the following command (replacing `mynamespace` with the namespace from step 2):
182 | ```ObjectScript
183 | ZN "mynamespace"
184 | ```
185 | 8. Enter the following commands (replacing `full-path-to-Build.SampleBI.cls` with the full path of the `buildsample/Build.SampleBI.cls` file):
186 |
187 | ```ObjectScript
188 | do $system.OBJ.Load("full-path-to-Build.SampleBI.cls","ck")
189 |
190 | do ##class(Build.SampleBI).Build()
191 | ```
192 | 9. When prompted, enter the full path of the directory to which you downloaded this sample. The method then loads and compiles the code and performs other needed setup steps.
193 |
194 | Now, when you access the Analytics submenu of the Management Portal, this namespace will be listed. For example, you can now use the Analyzer with the cubes that are included within this sample.
195 |
196 | IMPORTANT: If the namespace is not listed when you access the Analytics submenu of the Management Portal, see [Setting Up the Web Application](https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=D2IMP_ch_setup#D2IMP_setup_web_app) in the book [Implementing InterSystems IRIS Business Intelligence](https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=D2IMP_ch_setup).
197 |
198 |
199 |
--------------------------------------------------------------------------------