tricc-oo 1.5.13__py3-none-any.whl → 1.6.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. tests/build.py +20 -28
  2. tests/test_build.py +260 -0
  3. tests/test_cql.py +48 -109
  4. tests/to_ocl.py +15 -17
  5. tricc_oo/__init__.py +0 -6
  6. tricc_oo/converters/codesystem_to_ocl.py +51 -40
  7. tricc_oo/converters/cql/cqlLexer.py +1 -0
  8. tricc_oo/converters/cql/cqlListener.py +1 -0
  9. tricc_oo/converters/cql/cqlParser.py +1 -0
  10. tricc_oo/converters/cql/cqlVisitor.py +1 -0
  11. tricc_oo/converters/cql_to_operation.py +129 -123
  12. tricc_oo/converters/datadictionnary.py +45 -54
  13. tricc_oo/converters/drawio_type_map.py +146 -65
  14. tricc_oo/converters/tricc_to_xls_form.py +58 -28
  15. tricc_oo/converters/utils.py +4 -4
  16. tricc_oo/converters/xml_to_tricc.py +296 -235
  17. tricc_oo/models/__init__.py +2 -1
  18. tricc_oo/models/base.py +333 -305
  19. tricc_oo/models/calculate.py +66 -51
  20. tricc_oo/models/lang.py +26 -27
  21. tricc_oo/models/ocl.py +146 -161
  22. tricc_oo/models/ordered_set.py +15 -19
  23. tricc_oo/models/tricc.py +149 -89
  24. tricc_oo/parsers/xml.py +15 -30
  25. tricc_oo/serializers/planuml.py +4 -6
  26. tricc_oo/serializers/xls_form.py +110 -153
  27. tricc_oo/strategies/input/base_input_strategy.py +28 -32
  28. tricc_oo/strategies/input/drawio.py +59 -71
  29. tricc_oo/strategies/output/base_output_strategy.py +151 -65
  30. tricc_oo/strategies/output/dhis2_form.py +908 -0
  31. tricc_oo/strategies/output/fhir_form.py +377 -0
  32. tricc_oo/strategies/output/html_form.py +224 -0
  33. tricc_oo/strategies/output/openmrs_form.py +694 -0
  34. tricc_oo/strategies/output/spice.py +106 -127
  35. tricc_oo/strategies/output/xls_form.py +322 -244
  36. tricc_oo/strategies/output/xlsform_cdss.py +627 -142
  37. tricc_oo/strategies/output/xlsform_cht.py +252 -125
  38. tricc_oo/strategies/output/xlsform_cht_hf.py +13 -24
  39. tricc_oo/visitors/tricc.py +1424 -1033
  40. tricc_oo/visitors/utils.py +16 -16
  41. tricc_oo/visitors/xform_pd.py +91 -89
  42. {tricc_oo-1.5.13.dist-info → tricc_oo-1.6.8.dist-info}/METADATA +128 -84
  43. tricc_oo-1.6.8.dist-info/RECORD +52 -0
  44. tricc_oo-1.6.8.dist-info/licenses/LICENSE +373 -0
  45. {tricc_oo-1.5.13.dist-info → tricc_oo-1.6.8.dist-info}/top_level.txt +0 -0
  46. tricc_oo-1.5.13.dist-info/RECORD +0 -46
  47. {tricc_oo-1.5.13.dist-info → tricc_oo-1.6.8.dist-info}/WHEEL +0 -0
@@ -1,17 +1,17 @@
1
1
  PROCESSES = [
2
- "triage",
3
- "emergency-care",
4
- "registration",
5
- "history-and-physical",
6
- "local-urgent-care",
7
- "acute-tertiary-care",
8
- "diagnostic-testing",
9
- "determine-diagnosis",
10
- "provide-counseling",
11
- "dispense-medications",
12
- "monitor-and-follow-up-of-patient",
13
- "alerts-reminders-education",
14
- "discharge-referral-of-patient",
15
- "charge-for-service",
16
- "record-and-report",
17
- ]
2
+ "triage",
3
+ "emergency-care",
4
+ "registration",
5
+ "history-and-physical",
6
+ "local-urgent-care",
7
+ "acute-tertiary-care",
8
+ "diagnostic-testing",
9
+ "determine-diagnosis",
10
+ "provide-counseling",
11
+ "dispense-medications",
12
+ "monitor-and-follow-up-of-patient",
13
+ "alerts-reminders-education",
14
+ "discharge-referral-of-patient",
15
+ "charge-for-service",
16
+ "record-and-report",
17
+ ]
@@ -4,15 +4,16 @@ Created on Thu Sep 1 11:21:39 2022
4
4
 
5
5
  @author: kluera
6
6
 
7
- Make subforms that allow to be releoaded seperately as a 'task' in CHT,
8
- allowing to simulate a pause functionality.
7
+ Make subforms that allow to be releoaded seperately as a 'task' in CHT,
8
+ allowing to simulate a pause functionality.
9
9
  """
10
10
 
11
11
  import pandas as pd
12
- import json
12
+
13
13
 
14
14
  def remove_dots(s):
15
- return s.replace('.','_')
15
+ return s.replace(".", "_")
16
+
16
17
 
17
18
  def chf_clean_name(s, remove_dots=False):
18
19
  # Check if there is a dot in the string
@@ -24,159 +25,161 @@ def chf_clean_name(s, remove_dots=False):
24
25
  # If no dot is present, return None or handle it as needed
25
26
  return s
26
27
 
28
+
27
29
  # df is the dataframe to be split
28
30
  # pausepoint is the index of the row after which the form should pause
29
31
  def make_breakpoints(df, pausepoint, calculate_name=None, replace_dots=False):
30
32
  """
31
33
  Creates a dataframe for a follow-up questionnaire while preserving previous inputs.
32
-
34
+
33
35
  Args:
34
36
  df: Input dataframe containing the questionnaire
35
37
  pausepoint: Point where the questionnaire should pause
36
38
  calculate_name: Optional name for calculation fields
37
39
  """
38
-
40
+
39
41
  # Get data points collected before break
40
- if 'input end' not in df['name'].values:
42
+ if "input end" not in df["name"].values:
41
43
  raise ValueError("input end field not found in input dataframe")
42
- end_inputs_loc = df.index[df['name'] == 'input end'][0]
43
- next_begin_group_loc = min([i for i in df.index[df['type'] == 'begin group'] if i > end_inputs_loc])
44
- next_pause_point_begin_group_loc = min([i for i in df.index[df['type'] == 'begin group'] if i > pausepoint])
45
-
44
+ end_inputs_loc = df.index[df["name"] == "input end"][0]
45
+ next_begin_group_loc = min([i for i in df.index[df["type"] == "begin group"] if i > end_inputs_loc])
46
+ next_pause_point_begin_group_loc = min([i for i in df.index[df["type"] == "begin group"] if i > pausepoint])
47
+
46
48
  df_input = df.loc[next_begin_group_loc:next_pause_point_begin_group_loc]
47
-
49
+
48
50
  # Define field types to handle
49
- typesconvert = ['integer', 'decimal', 'select_', 'text']
50
- typeskeep = ['hidden', 'calculate', 'string']
51
-
51
+ typesconvert = ["integer", "decimal", "select_", "text"]
52
+ typeskeep = ["hidden", "calculate", "string"]
53
+
52
54
  # Create masks for filtering
53
- type_mask = df_input['type'].str.contains('|'.join(typeskeep + typesconvert))
54
- optin_mask = ~df_input['name'].str.contains('more_info_optin', na=False)
55
-
55
+ type_mask = df_input["type"].str.contains("|".join(typeskeep + typesconvert))
56
+ optin_mask = ~df_input["name"].str.contains("more_info_optin", na=False)
57
+
56
58
  # Filter dataframe keeping important fields
57
59
  df_input = df_input.loc[type_mask & optin_mask]
58
-
60
+
59
61
  # Preserve existing hidden fields and their calculations
60
- existing_hidden = df_input[df_input['type'] == 'hidden'].copy()
61
-
62
+ existing_hidden = df_input[df_input["type"] == "hidden"].copy()
63
+
62
64
  # Convert specified types to hidden while preserving their data
63
- mask_indices = df_input.index[df_input['type'].str.contains('|'.join(typesconvert))]
65
+ mask_indices = df_input.index[df_input["type"].str.contains("|".join(typesconvert))]
64
66
  # Get hidden field names
65
67
 
66
- df_input.loc[mask_indices, 'type'] = 'hidden'
67
- df_input.loc[mask_indices, 'appearance'] = 'hidden'
68
+ df_input.loc[mask_indices, "type"] = "hidden"
69
+ df_input.loc[mask_indices, "appearance"] = "hidden"
68
70
 
69
71
  # Handle label columns while preserving existing labels where needed
70
- label_cols = [col for col in df.columns if 'label' in col]
71
- df_input.loc[mask_indices, label_cols] = 'NO_LABEL'
72
-
72
+ label_cols = [col for col in df.columns if "label" in col]
73
+ df_input.loc[mask_indices, label_cols] = "NO_LABEL"
74
+
73
75
  # Clear non-essential columns while preserving crucial data
74
- essential_cols = ['name', 'type', 'calculation'] + label_cols
76
+ essential_cols = ["name", "type", "calculation"] + label_cols
75
77
  other_cols = df_input.columns.drop(essential_cols)
76
- df_input[other_cols] = ''
77
-
78
+ df_input[other_cols] = ""
79
+
78
80
  # Preserve calculations for existing hidden fields
79
- df_input.update(existing_hidden[['calculation']])
81
+ df_input.update(existing_hidden[["calculation"]])
80
82
  # SAVE THE INPUT NAMES
81
- hidden_names = list(df_input.loc[df_input['type']=='hidden', 'name'])
83
+ hidden_names = list(df_input.loc[df_input["type"] == "hidden", "name"])
82
84
  if replace_dots:
83
- df_input['name'] = df_input['name'].map(remove_dots)
85
+ df_input["name"] = df_input["name"].map(remove_dots)
84
86
  # Handle indexing and grouping
85
87
  df_input.index = df_input.index.map(str)
86
- hidden_ids = df_input.loc[df_input['type']=='hidden'].index
87
- inputs_group_index = '0'
88
- new_hidden_ids = inputs_group_index + '.' + hidden_ids
89
-
88
+ hidden_ids = df_input.loc[df_input["type"] == "hidden"].index
89
+ inputs_group_index = "0"
90
+ new_hidden_ids = inputs_group_index + "." + hidden_ids
91
+
90
92
  # Update indices
91
93
  index_map = dict(zip(hidden_ids, new_hidden_ids))
92
94
  df_input.rename(index=index_map, inplace=True)
93
95
  df_input.sort_index(inplace=True)
94
96
  df_input.reset_index(drop=True, inplace=True)
95
-
97
+
96
98
  if remove_dots:
97
99
  # Precompute replacement dictionary
98
- replacement_dict = {f'${old_name}': f'${remove_dots(old_name)}' for old_name in hidden_names if '.' in old_name}
100
+ replacement_dict = {f"${old_name}": f"${remove_dots(old_name)}" for old_name in hidden_names if "." in old_name}
99
101
 
100
102
  # Apply replacements to entire DataFrame
101
103
  df_input = df_input.astype(str).replace(replacement_dict, regex=False)
102
-
103
104
 
104
-
105
-
106
-
107
- # put all together
108
- if 'data_load' not in df['name'].values:
105
+ # put all together
106
+ if "data_load" not in df["name"].values:
109
107
  raise ValueError("data_load field not found in input dataframe")
110
- data_load_loc = df.index[df['name'] == 'data_load'][0]
111
-
108
+ data_load_loc = df.index[df["name"] == "data_load"][0]
109
+
112
110
  # Split the dataframe into three parts
113
111
  df_before_data_load = df.loc[:data_load_loc] # Everything up to data_load
114
- df_until_begin_group = df.loc[data_load_loc+1:next_begin_group_loc-1] # From data_load to next begin_group
115
-
112
+ df_until_begin_group = df.loc[data_load_loc + 1: next_begin_group_loc - 1] # From data_load to next begin_group
113
+
116
114
  # Reset indices for proper concatenation
117
115
  df_input = df_input.reset_index(drop=True)
118
116
  df_before_data_load = df_before_data_load.reset_index(drop=True)
119
117
  df_until_begin_group = df_until_begin_group.reset_index(drop=True)
120
-
118
+
121
119
  # Concatenate in the correct order
122
- df_combined = pd.concat([
123
- df_before_data_load, # First part until data_load
124
- df_input, # Injected converted fields
125
- df_until_begin_group # Remaining part until next begin_group
126
- ]).reset_index(drop=True)
127
-
120
+ df_combined = pd.concat(
121
+ [
122
+ df_before_data_load, # First part until data_load
123
+ df_input, # Injected converted fields
124
+ df_until_begin_group, # Remaining part until next begin_group
125
+ ]
126
+ ).reset_index(drop=True)
127
+
128
128
  # Handle post-break section
129
129
  df_after = df.loc[next_pause_point_begin_group_loc:].reset_index(drop=True)
130
130
 
131
-
132
131
  # Final concatenation
133
132
  final_df = pd.concat([df_combined, df_after])
134
133
  if calculate_name:
135
- final_df.loc[final_df['name']=='hidden','calculation']='0'
136
-
137
- final_df.fillna('', inplace=True)
134
+ final_df.loc[final_df["name"] == "hidden", "calculation"] = "0"
135
+
136
+ final_df.fillna("", inplace=True)
138
137
  final_df.reset_index(inplace=True, drop=True)
139
-
140
- return final_df, hidden_names
141
138
 
139
+ return final_df, hidden_names
142
140
 
143
141
 
144
142
  def get_tasksstrings(hidden_names, df_survey):
145
- '''This function makes a list of strings of hidden fields that will be loaded into a form that continues the consultation.
146
- This is very handy as this string must be pasted into the tasks.js file in CHT.
143
+ """This function makes a list of strings of hidden fields that will be loaded
144
+ into a form that continues the consultation.
145
+ This is very handy as this string must be pasted into the tasks.js file in CHT.
147
146
  @hidden_names: are the names of the 'hidden' fields in the input group of the follow up form
148
147
  @df_survey: is the survey tab of the complete (original) form without breaks, going from A to Z
149
- @tasks_strings: is the string that has to be pasted into tasks.js'''
150
-
148
+ @tasks_strings: is the string that has to be pasted into tasks.js"""
149
+
151
150
  task_string_template = "content['{variableName}'] = getField(report, '{full_path}')"
152
151
  task_strings = {}
153
152
  for s in hidden_names:
154
- df_above_s = df_survey.iloc[:df_survey.loc[df_survey['name']==s].index[0]]
155
- df_above_s_groups = df_above_s.loc[df_above_s['type'].isin(['begin group', 'end group'])]
153
+ df_above_s = df_survey.iloc[: df_survey.loc[df_survey["name"] == s].index[0]]
154
+ df_above_s_groups = df_above_s.loc[df_above_s["type"].isin(["begin group", "end group"])]
156
155
  above_s_grouprows = df_above_s_groups.index
157
156
  fullpath = []
158
157
  for i in above_s_grouprows:
159
- if df_above_s.iloc[i]['type']=='begin group':
160
- fullpath.append(df_above_s.iloc[i]['name'])
161
- else:
158
+ if df_above_s.iloc[i]["type"] == "begin group":
159
+ fullpath.append(df_above_s.iloc[i]["name"])
160
+ else:
162
161
  fullpath = fullpath[:-1]
163
- if len(fullpath)>0:
164
- line = task_string_template.format(
165
- variableName=s, full_path='.'.join(fullpath) + chf_clean_name(s)
166
- )
162
+ if len(fullpath) > 0:
163
+ line = task_string_template.format(variableName=s, full_path=".".join(fullpath) + chf_clean_name(s))
167
164
  else:
168
- line = task_string_template.format(
169
- variableName=s, full_path=chf_clean_name(s)
170
- )
171
- task_strings[s]=line
172
- return list(task_strings.values())
173
-
174
-
175
- def get_task_js(form_id, calculate_name, title, form_types, hidden_names, df_survey, repalce_dots=False, task_title="'id: '+getField(report, 'g_registration.p_id')+'; age: '+getField(report, 'p_age')+getField(report, 'g_registration.p_gender')+' months; '+getField(report, 'p_weight') + 'kg; ' + getField(report, 'g_fever.p_temp')+'°'"):
165
+ line = task_string_template.format(variableName=s, full_path=chf_clean_name(s))
166
+ task_strings[s] = line
167
+ return list(task_strings.values())
168
+
169
+
170
+ def get_task_js(
171
+ form_id,
172
+ calculate_name,
173
+ title,
174
+ form_types,
175
+ hidden_names,
176
+ df_survey,
177
+ repalce_dots=False,
178
+ task_title="id: '+getField(report, 'g_registration.p_id')+';age: '+getField(report, 'p_age')+getField(report, 'g_registration.p_gender')+' months; '+getField(report, 'p_weight') + 'kg; ' + getField(report, 'g_fever.p_temp')+'°'", # noqa: E501
179
+ ):
176
180
  task_name = f"{form_id}"
177
181
  task_name_upper = task_name.upper()
178
182
 
179
-
180
183
  return f"""
181
184
  /* eslint-disable no-use-before-define */
182
185
  /* eslint-disable */
@@ -185,7 +188,7 @@ const {{injectDataFromForm, isFormArrayHasSourceId}} = require('./stph-extras');
185
188
  const {{getField}} = require("./nools-extras");
186
189
 
187
190
  const CASE_DATA = ['{"','".join(hidden_names)}'];
188
-
191
+
189
192
 
190
193
  const {task_name_upper}_FORMS = ['{"','".join(form_types)}'];
191
194
 
@@ -195,7 +198,7 @@ const {task_name_upper}_TASK_FORM = '{form_id}';
195
198
 
196
199
  const {task_name}Content = function (content, contact, report){{
197
200
 
198
- injectDataFromForm(content, '', CASE_DATA, {task_name_upper}_FORMS, [report], {'true' if repalce_dots else 'false'});
201
+ injectDataFromForm(content, '', CASE_DATA, {task_name_upper}_FORMS, [report], {'true' if repalce_dots else 'false'});
199
202
  content['patient_id'] = report.contact._id;
200
203
  content['source_id'] = report._id;
201
204
  console.log(content);
@@ -230,7 +233,7 @@ module.exports = {{
230
233
  {task_name}ResolveIf,
231
234
  {task_name}AppliesIf,
232
235
  }}
233
- //
236
+ //
234
237
  //// to be copied in task
235
238
  //
236
239
  //const {{
@@ -238,7 +241,7 @@ module.exports = {{
238
241
  // {task_name_upper}_FORMS,
239
242
  // {task_name}Content,
240
243
  // {task_name}ContactLabel,
241
- // {task_name}ResolveIf,
244
+ // {task_name}ResolveIf,
242
245
  // {task_name}AppliesIf, }} = require('./{task_name}');
243
246
  //
244
247
  //module.exports = [
@@ -270,4 +273,3 @@ module.exports = {{
270
273
  // }}
271
274
  //];
272
275
  """
273
-
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tricc-oo
3
- Version: 1.5.13
3
+ Version: 1.6.8
4
4
  Summary: Python library that converts CDSS L2 in L3
5
5
  Project-URL: Homepage, https://github.com/SwissTPH/tricc
6
6
  Project-URL: Issues, https://github.com/SwissTPH/tricc/issues
@@ -9,6 +9,7 @@ Classifier: Programming Language :: Python :: 3
9
9
  Classifier: Operating System :: OS Independent
10
10
  Requires-Python: >=3.8
11
11
  Description-Content-Type: text/markdown
12
+ License-File: LICENSE
12
13
  Requires-Dist: lxml
13
14
  Requires-Dist: markdownify
14
15
  Requires-Dist: pydantic
@@ -23,8 +24,133 @@ Requires-Dist: antlr4-python3-runtime==4.13.2
23
24
  Requires-Dist: antlr4-tools==0.2.1
24
25
  Requires-Dist: beautifulsoup4
25
26
  Requires-Dist: ocldev
27
+ Requires-Dist: pyxform
28
+ Dynamic: license-file
26
29
 
27
- # design rules tricc_oo
30
+ # TRICC-OO
31
+
32
+
33
+ ## Strategy
34
+
35
+ ### XLSFormStrategy
36
+
37
+ to use on OKD and clones,
38
+
39
+ ### XLSFormCDSSStrategy
40
+
41
+ based on XLSFormStrategy
42
+ to use on OKD and clones,
43
+ support the CDSS specific behaviour such as Classification management
44
+
45
+ ### XLSFormCHTStrategy
46
+
47
+ based on XLSFormCDSSStrategy
48
+ to use on medic CHT if the questionnaire is run Patient level
49
+ Support the inputs from patient
50
+ Support the extention libs
51
+
52
+ ### XLSFormCHTHFStrategy
53
+
54
+ based on XLSFormCHTStrategy
55
+ to use on medic CHT if the questionnaire is run on Health facility level without selecting a patient
56
+ Support inputs from HF
57
+
58
+
59
+ ### OpenMRSStrategy
60
+
61
+ (under development)
62
+
63
+ ### FhirStrategy
64
+
65
+ (UNTESTED)
66
+
67
+ ### HTMLStrategy
68
+
69
+ (UNTESTED)
70
+
71
+ ## start nodes
72
+
73
+ ### Main start
74
+
75
+ the flow required at least 1 main start node, but in case of cdss output strategy , several could be used given that they have a 'process' atrribute
76
+
77
+ here is the list of the CPG process, this will be the execution oder too:
78
+ - **registration**,
79
+ - **triage**,
80
+ - **emergency-care**,
81
+ - **local-urgent-care**,
82
+ - **actue-tertiary-care**,
83
+ - **history-and-physical**,
84
+ - **diagnostic-testing**,
85
+ - **determine-diagnosis**,
86
+ - **provide-counseling**,
87
+ - **dispense-medications**,
88
+ - **monitor-and-follow-up-of-patient**,
89
+ - **alerts-reminders-education**,
90
+ - **discharge-referral-of-patient**,
91
+ - **charge-for-service**,
92
+ - **record-and-report**
93
+
94
+
95
+
96
+
97
+ # Note
98
+
99
+ ## generation of the expressions
100
+
101
+ ### add calcualte:
102
+
103
+ - Non or No in an egde will generate a negate node
104
+ - save adds a calcualte
105
+ - a rhombus will generate a calcualte using the reference (can you the label as a test, either with comparaisin or option selected with [option label])
106
+
107
+ ### for calculate
108
+
109
+ Then we calculate based on the previous nodes: [get_prev_node_expression]
110
+ - if a "fake" calculate (Rhombus, exclusion) then get the underlying expression (should not depend of Calcualte = true) [get_calculation_terms]
111
+ - if a Select, manage it as a calculate too (should not depend of Calcualte = true) [get_calculation_terms]
112
+ - else get the expression via [get_calculation_terms] [get_prev_node_expression , calculate = False] -> get_node_expression for the prev node
113
+
114
+ # Running directly
115
+
116
+ `tricc` is technically a python library, but you can run it directly via the [`build.py` script](./tests/build.py).
117
+
118
+ ## Running with Docker
119
+
120
+ Alternatively, if you prefer to build/run the project with Docker, you can do the following.
121
+
122
+ Start by building the Docker image:
123
+
124
+ ```shell
125
+ git clone https://github.com/SwissTPH/tricc.git
126
+ cd tricc
127
+
128
+ docker build -t tricc .
129
+ ```
130
+
131
+ Once you have the image built you can use it to convert local `.drawio` files by mapping the local directory to the `docker run` command. (Note that `--user` is specified to make sure the current host user has write access to the output files.)
132
+
133
+ ```shell
134
+ docker run --rm -v "$PWD":/proj --user $(id -u):$(id -g) tricc --help
135
+ ```
136
+
137
+ This command will convert all `.drawio` files in the current directory:
138
+
139
+ ```shell
140
+ docker run --rm -v "$PWD":/proj --user $(id -u):$(id -g) tricc -i /proj -o /proj
141
+ ```
142
+
143
+ You can also convert a single file:
144
+
145
+ ```shell
146
+ docker run --rm -v "$PWD":/proj --user $(id -u):$(id -g) tricc -i /proj/demo.drawio -o /proj
147
+ ```
148
+
149
+ Use the `-O` flag to specify the output strategy. For example to generate CHT files:
150
+
151
+ ```shell
152
+ docker run --rm -v "$PWD":/proj --user $(id -u):$(id -g) tricc -i /proj -o /proj -O XLSFormCHTStrategy
153
+ ```
28
154
 
29
155
  ## Nodes
30
156
 
@@ -131,90 +257,8 @@ if not a calculate then relevance will be used unless it is "required" then cond
131
257
  the Rhombus act as an AND between its imputs and its reference BUT it is an OR beween the inputs
132
258
  (input1 OR input2 OR input3) AND reference
133
259
 
134
- ## start nodes
135
-
136
- ### Main start
137
-
138
- the flow required at least 1 main start node, but in case of cdss output strategy , several could be used given that they have a 'process' atrribute
139
-
140
- here is the list of the CPG process, this will be the execution oder too:
141
- - **registration**,
142
- - **triage**,
143
- - **emergency-care**,
144
- - **local-urgent-care**,
145
- - **actue-tertiary-care**,
146
- - **history-and-physical**,
147
- - **diagnostic-testing**,
148
- - **determine-diagnosis**,
149
- - **provide-counseling**,
150
- - **dispense-medications**,
151
- - **monitor-and-follow-up-of-patient**,
152
- - **alerts-reminders-education**,
153
- - **discharge-referral-of-patient**,
154
- - **charge-for-service**,
155
- - **record-and-report**
156
-
157
-
158
260
  # READ Xressource
159
261
  https://jgraph.github.io/drawio-tools/tools/convert.html
160
262
 
161
263
  option can have only incoming edge from images to be placed as option$
162
264
 
163
-
164
- # Note
165
-
166
- ## generation of the expressions
167
-
168
- ### add calcualte:
169
-
170
- - Non or No in an egde will generate a negate node
171
- - save adds a calcualte
172
- - a rhombus will generate a calcualte using the reference (can you the label as a test, either with comparaisin or option selected with [option label])
173
-
174
- ### for calculate
175
-
176
- Then we calculate based on the previous nodes: [get_prev_node_expression]
177
- - if a "fake" calculate (Rhombus, exclusion) then get the underlying expression (should not depend of Calcualte = true) [get_calculation_terms]
178
- - if a Select, manage it as a calculate too (should not depend of Calcualte = true) [get_calculation_terms]
179
- - else get the expression via [get_calculation_terms] [get_prev_node_expression , calculate = False] -> get_node_expression for the prev node
180
-
181
- # Running directly
182
-
183
- `tricc` is technically a python library, but you can run it directly via the [`build.py` script](./tests/build.py).
184
-
185
- ## Running with Docker
186
-
187
- Alternatively, if you prefer to build/run the project with Docker, you can do the following.
188
-
189
- Start by building the Docker image:
190
-
191
- ```shell
192
- git clone https://github.com/SwissTPH/tricc.git
193
- cd tricc
194
-
195
- docker build -t tricc .
196
- ```
197
-
198
- Once you have the image built you can use it to convert local `.drawio` files by mapping the local directory to the `docker run` command. (Note that `--user` is specified to make sure the current host user has write access to the output files.)
199
-
200
- ```shell
201
- docker run --rm -v "$PWD":/proj --user $(id -u):$(id -g) tricc --help
202
- ```
203
-
204
- This command will convert all `.drawio` files in the current directory:
205
-
206
- ```shell
207
- docker run --rm -v "$PWD":/proj --user $(id -u):$(id -g) tricc -i /proj -o /proj
208
- ```
209
-
210
- You can also convert a single file:
211
-
212
- ```shell
213
- docker run --rm -v "$PWD":/proj --user $(id -u):$(id -g) tricc -i /proj/demo.drawio -o /proj
214
- ```
215
-
216
- Use the `-O` flag to specify the output strategy. For example to generate CHT files:
217
-
218
- ```shell
219
- docker run --rm -v "$PWD":/proj --user $(id -u):$(id -g) tricc -i /proj -o /proj -O XLSFormCHTStrategy
220
- ```
@@ -0,0 +1,52 @@
1
+ tests/build.py,sha256=Qbxvjkj_Wk2nQ-WjaMGiE1FIe3SRmJMRIgeoMoxqlfQ,6748
2
+ tests/test_build.py,sha256=5t8iliPe_0XwoZjSGkHxUbZaNOWBfc6SpIQijh9DLUA,10037
3
+ tests/test_cql.py,sha256=dAsLMqVaS6qxnq62fg5KqTFu6UG6pHO6Ab3NZ1c9T3Y,5248
4
+ tests/to_ocl.py,sha256=4e-i65K3UM6wHgdVcrZcM9AyL1bahIsXJiZTXhhHgQk,2048
5
+ tricc_oo/__init__.py,sha256=oWCE1ubmC_6iqaWOMgTei4eXVQgV202Ia-tXS1NnW_4,139
6
+ tricc_oo/converters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ tricc_oo/converters/codesystem_to_ocl.py,sha256=Fh7Vk73OsxljZKu1k6H9uzYwz334tpQTMZBjWWbamYE,6151
8
+ tricc_oo/converters/cql_to_operation.py,sha256=PUyV_YpUY98Ox0H_F_CN3UUf_I-BhFZVOcWWKTtwecM,14492
9
+ tricc_oo/converters/datadictionnary.py,sha256=T2HLCBo4Am1p0kFqSH1r0PqbD8AC2IGuWkbvMvSCru0,3658
10
+ tricc_oo/converters/drawio_type_map.py,sha256=UCPiGs7Lw0bigKScmZUnmOhACBz-FiDq92jHkI7RTSQ,9113
11
+ tricc_oo/converters/tricc_to_xls_form.py,sha256=wsWv4aA0QssY7ry9R7KsuuMzVfovj9fwE3i9AtCum0c,3842
12
+ tricc_oo/converters/utils.py,sha256=JZrtrvvOfXwdkw49pKauzinOcauWwsy-CVcw36TjyLo,1684
13
+ tricc_oo/converters/xml_to_tricc.py,sha256=PEBe8N-JIGJMVX2FO3UVxRcy5GrGsMvgcArEwUXmr6o,39572
14
+ tricc_oo/converters/cql/cqlLexer.py,sha256=8HArbRphcrpnAG4uogJ2rHv4tc1WLzjN0B1uFeYILAc,49141
15
+ tricc_oo/converters/cql/cqlListener.py,sha256=fA7-8DcS2Q69ckwjdg57-OfFHBxjTZFdoSKrtw7Hffc,57538
16
+ tricc_oo/converters/cql/cqlParser.py,sha256=x3KdrwX9nwENSEJ5Ex7_l5NMnu3kWBO0uLdYu4moTq0,414745
17
+ tricc_oo/converters/cql/cqlVisitor.py,sha256=iHuup2S7OGSVWLEcI4H3oecRqgXztC1sKnew_1P2iGY,33880
18
+ tricc_oo/models/__init__.py,sha256=CgS52LLqdDIaXHvZy08hhu_VaYw80OEdfL_llM9ICBA,108
19
+ tricc_oo/models/base.py,sha256=saMpSiXnvQe_xkQ4PKJbNLqPkzZaiEGwb42HJ1CtwfM,25937
20
+ tricc_oo/models/calculate.py,sha256=uNP0IDUqPQcJq9Co05H8eX5wbR_DikSxuOHxfVE5Dxg,8018
21
+ tricc_oo/models/lang.py,sha256=ZMRwdoPWe01wEDhOM0uRk-6rt3BkoAAZM8mZ61--s3A,2265
22
+ tricc_oo/models/ocl.py,sha256=MybSeB6fgCOUVJ4aektff0vrrTZsyfwZ2Gt_pPBu_FY,8728
23
+ tricc_oo/models/ordered_set.py,sha256=BpXLW8plRAy4te25PIUPvVXPnLPcypvKg3iNPhtPulA,3833
24
+ tricc_oo/models/tricc.py,sha256=lQ1xguJjhbRQ8wFt2rwefw_756aq_y4rWxf8Gj9zhas,17475
25
+ tricc_oo/parsers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
+ tricc_oo/parsers/xml.py,sha256=uzkb1y18MHfqVFmZqVh0sKT4cx6u0-NcAT_lV_gHBt8,4208
27
+ tricc_oo/serializers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
+ tricc_oo/serializers/planuml.py,sha256=t57587-6L3aDncpHh58lS77Zft8yxDE9DPtXx2BeUSU,132
29
+ tricc_oo/serializers/xls_form.py,sha256=L0WF774zFt6PbdqncJGeyZzM9NiLq9NY5vO98yGTLhM,22133
30
+ tricc_oo/strategies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
+ tricc_oo/strategies/input/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
+ tricc_oo/strategies/input/base_input_strategy.py,sha256=BEODXS74na1QRRcJVQ4cxiD8F7uRqaLyhE3QzKpGVvk,3891
33
+ tricc_oo/strategies/input/drawio.py,sha256=uXAUPhXOeg0Uk_BNqlCqFBW4cWNox4VfH559bj1fhC0,12767
34
+ tricc_oo/strategies/output/base_output_strategy.py,sha256=i9L5CVUqkEAMNyBsdHJ4xA7Nptr3myHr_fHHveDX1cU,8928
35
+ tricc_oo/strategies/output/dhis2_form.py,sha256=jW9NW72_61ch1bHm8ShIH4xsJH-HMlZGPTT5txJxMUk,38278
36
+ tricc_oo/strategies/output/fhir_form.py,sha256=hbL921pe1Doun4IQrJuZ_Sq2fCh98G3grYie5olC4uc,15740
37
+ tricc_oo/strategies/output/html_form.py,sha256=qSleEZOMV_-Z04y-i-ucyd5rgAYWAyjPwMrw0IHtCRM,8604
38
+ tricc_oo/strategies/output/openmrs_form.py,sha256=ne6TwAyhafR-WDs27QTKKFl85VD5sij_VEJtK6ZjOIE,28996
39
+ tricc_oo/strategies/output/spice.py,sha256=QMeoismVC3PdbvwTK0PtUjWX9jl9780fbQIXn76fMXw,10761
40
+ tricc_oo/strategies/output/xls_form.py,sha256=_pNTND7n-55EjRphJ1hSVtRYa-UkXlmwpam2OKQ8o_w,30860
41
+ tricc_oo/strategies/output/xlsform_cdss.py,sha256=X00Lt5MzV8TX14dR4dFI1MqllI5S1e13bKbeysWM9uA,17435
42
+ tricc_oo/strategies/output/xlsform_cht.py,sha256=eKAc6LLDnvdZ5m8a2Vk6eAhvPbUvOfykgYr0ou3an9k,27164
43
+ tricc_oo/strategies/output/xlsform_cht_hf.py,sha256=xm6SKirV3nMZvM2w54_zJcXAeAgAkq-EEqGEjnOWv6c,988
44
+ tricc_oo/visitors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
+ tricc_oo/visitors/tricc.py,sha256=8fULbAxKSeEtPyD5TYTaIG8-20Bjg2iZmzxcJM70n18,110295
46
+ tricc_oo/visitors/utils.py,sha256=j83aAq5s5atXi3OC0jc_uJd54a8XrHHmizeeEbWZQJg,421
47
+ tricc_oo/visitors/xform_pd.py,sha256=ryAnI3V9x3eTmJ2LNsUZfvl0_yfCqo6oBgeSu-WPqaE,9613
48
+ tricc_oo-1.6.8.dist-info/licenses/LICENSE,sha256=Pz2eACSxkhsGfW9_iN60pgy-enjnbGTj8df8O3ebnQQ,16726
49
+ tricc_oo-1.6.8.dist-info/METADATA,sha256=g9u0_NdvNT8FFgNB3LQzsUADmGqL1PBB1DPdnCBKVuI,8599
50
+ tricc_oo-1.6.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
51
+ tricc_oo-1.6.8.dist-info/top_level.txt,sha256=NvbfMNAiy9m4b1unBsqpeOQWh4IgA1Xa33BtKA4abxk,15
52
+ tricc_oo-1.6.8.dist-info/RECORD,,