tricc-oo 1.4.19__tar.gz → 1.4.21__tar.gz
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.
- {tricc_oo-1.4.19/tricc_oo.egg-info → tricc_oo-1.4.21}/PKG-INFO +1 -1
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/pyproject.toml +1 -1
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/drawio_type_map.py +2 -2
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/tricc_to_xls_form.py +4 -4
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/models/base.py +13 -6
- tricc_oo-1.4.19/tricc_oo/strategies/output/xlsform_cht_hf.py → tricc_oo-1.4.21/tricc_oo/strategies/output/xlsform_cht.py +167 -19
- tricc_oo-1.4.21/tricc_oo/strategies/output/xlsform_cht_hf.py +43 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/visitors/tricc.py +97 -76
- {tricc_oo-1.4.19 → tricc_oo-1.4.21/tricc_oo.egg-info}/PKG-INFO +2 -2
- tricc_oo-1.4.19/tricc_oo/strategies/output/xlsform_cht.py +0 -200
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/README.md +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/setup.cfg +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tests/build.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tests/test_cql.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tests/to_ocl.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/__init__.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/__init__.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/codesystem_to_ocl.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/cql/cqlLexer.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/cql/cqlListener.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/cql/cqlParser.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/cql/cqlVisitor.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/cql_to_operation.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/datadictionnary.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/utils.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/xml_to_tricc.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/models/__init__.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/models/calculate.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/models/lang.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/models/ocl.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/models/ordered_set.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/models/tricc.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/parsers/__init__.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/parsers/xml.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/serializers/__init__.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/serializers/planuml.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/serializers/xls_form.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/strategies/__init__.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/strategies/input/__init__.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/strategies/input/base_input_strategy.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/strategies/input/drawio.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/strategies/output/base_output_strategy.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/strategies/output/spice.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/strategies/output/xls_form.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/strategies/output/xlsform_cdss.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/visitors/__init__.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/visitors/utils.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/visitors/xform_pd.py +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo.egg-info/SOURCES.txt +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo.egg-info/dependency_links.txt +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo.egg-info/requires.txt +0 -0
- {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo.egg-info/top_level.txt +0 -0
|
@@ -94,13 +94,13 @@ TYPE_MAP = {
|
|
|
94
94
|
|
|
95
95
|
TriccNodeType.text: {
|
|
96
96
|
"objects": ["UserObject", "object"],
|
|
97
|
-
"attributes": ["relevance"],
|
|
97
|
+
"attributes": ["save", "relevance"],
|
|
98
98
|
"mandatory_attributes": ["label", 'name'],
|
|
99
99
|
"model": TriccNodeText
|
|
100
100
|
},
|
|
101
101
|
TriccNodeType.date: {
|
|
102
102
|
"objects": ["UserObject", "object"],
|
|
103
|
-
"attributes": ["relevance"],
|
|
103
|
+
"attributes": ["save", "relevance"],
|
|
104
104
|
"mandatory_attributes": ["label", "name"],
|
|
105
105
|
"model": TriccNodeDate
|
|
106
106
|
},
|
|
@@ -35,12 +35,12 @@ def get_export_name(node, replace_dots=True):
|
|
|
35
35
|
node.gen_name()
|
|
36
36
|
if isinstance(node, TriccNodeSelectOption):
|
|
37
37
|
node.export_name = node.name
|
|
38
|
-
elif isinstance(node, TriccNodeActivityStart):
|
|
39
|
-
node.export_name = clean_name(node.name + INSTANCE_SEPARATOR + str(node.instance), replace_dots=replace_dots)
|
|
40
|
-
elif isinstance(node, TriccNodeInput):
|
|
41
|
-
node.export_name = clean_name('load.' +node.name, replace_dots=replace_dots)
|
|
42
38
|
elif node.last == False:
|
|
43
39
|
node.export_name = clean_name(node.name + VERSION_SEPARATOR + str(node.version), replace_dots=replace_dots)
|
|
40
|
+
elif node.activity.instance>1:
|
|
41
|
+
node.export_name = clean_name(node.name + INSTANCE_SEPARATOR + str(node.activity.instance), replace_dots=replace_dots)
|
|
42
|
+
elif isinstance(node, TriccNodeInput):
|
|
43
|
+
node.export_name = clean_name('load.' +node.name, replace_dots=replace_dots)
|
|
44
44
|
else:
|
|
45
45
|
node.export_name = clean_name(node.name, replace_dots=replace_dots)
|
|
46
46
|
|
|
@@ -112,7 +112,14 @@ class TriccBaseModel(BaseModel):
|
|
|
112
112
|
version: int = 1
|
|
113
113
|
def get_datatype(self):
|
|
114
114
|
return self.datatype or self.tricc_type
|
|
115
|
-
|
|
115
|
+
|
|
116
|
+
def get_next_instance(self):
|
|
117
|
+
if getattr(self, 'instances', None):
|
|
118
|
+
return max(100, *[n.instance for n in self.instances.values()]) + 1
|
|
119
|
+
if getattr(self, 'base_instance', None) and getattr(self.base_instance, 'instances', None):
|
|
120
|
+
return max(100, *[n.instance for n in self.base_instance.instances.values()]) + 1
|
|
121
|
+
return max(100,self.instance) + 1
|
|
122
|
+
|
|
116
123
|
def to_dict(self):
|
|
117
124
|
return {key: value for key, value in vars(self).items() if not key.startswith('_')}
|
|
118
125
|
|
|
@@ -233,20 +240,20 @@ class TriccNodeBaseModel(TriccBaseModel):
|
|
|
233
240
|
# to be updated while processing because final expression will be possible to build$
|
|
234
241
|
# #only the last time the script will go through the node (all prev node expression would be created
|
|
235
242
|
def get_name(self):
|
|
236
|
-
result = str(super().get_name())
|
|
243
|
+
result = self.__class__.__name__[9:]# str(super().get_name())
|
|
237
244
|
name = getattr(self, 'name', None)
|
|
238
245
|
label = getattr(self, 'label', None)
|
|
239
246
|
|
|
240
247
|
if name:
|
|
241
|
-
result
|
|
248
|
+
result += name
|
|
242
249
|
if label:
|
|
243
|
-
result
|
|
250
|
+
result += "::" + (
|
|
244
251
|
next(iter(self.label.values())) if isinstance(self.label, Dict) else self.label
|
|
245
252
|
)
|
|
246
|
-
if len(result) <
|
|
253
|
+
if len(result) < 80:
|
|
247
254
|
return result
|
|
248
255
|
else:
|
|
249
|
-
return result[:
|
|
256
|
+
return result[:80]
|
|
250
257
|
|
|
251
258
|
|
|
252
259
|
|
|
@@ -2,19 +2,35 @@ import datetime
|
|
|
2
2
|
import logging
|
|
3
3
|
import os
|
|
4
4
|
import shutil
|
|
5
|
-
|
|
5
|
+
import re
|
|
6
6
|
import pandas as pd
|
|
7
7
|
|
|
8
8
|
from tricc_oo.models.lang import SingletonLangClass
|
|
9
|
-
from tricc_oo.
|
|
10
|
-
from tricc_oo.
|
|
11
|
-
from tricc_oo.
|
|
9
|
+
from tricc_oo.models.calculate import TriccNodeEnd
|
|
10
|
+
from tricc_oo.serializers.xls_form import SURVEY_MAP, get_input_line
|
|
11
|
+
from tricc_oo.strategies.output.xlsform_cdss import XLSFormCDSSStrategy
|
|
12
|
+
from tricc_oo.converters.tricc_to_xls_form import get_export_name
|
|
13
|
+
from tricc_oo.converters.utils import clean_name, remove_html
|
|
14
|
+
from tricc_oo.visitors.xform_pd import make_breakpoints, get_task_js
|
|
12
15
|
|
|
13
16
|
langs = SingletonLangClass()
|
|
14
17
|
logger = logging.getLogger("default")
|
|
15
18
|
|
|
16
|
-
class
|
|
19
|
+
class XLSFormCHTStrategy(XLSFormCDSSStrategy):
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def process_export(self, start_pages, **kwargs):
|
|
23
|
+
diags = []
|
|
24
|
+
self.activity_export(start_pages[self.processes[0]], **kwargs)
|
|
25
|
+
#self.add_tab_breaks_choice()
|
|
26
|
+
cht_header = pd.DataFrame(columns=SURVEY_MAP.keys())
|
|
27
|
+
cht_input_df = self.get_cht_input( start_pages, **kwargs)
|
|
28
|
+
self.df_survey= self.df_survey[~self.df_survey['name'].isin(cht_input_df['name'])]
|
|
29
|
+
self.df_survey.reset_index(drop=True, inplace=True)
|
|
17
30
|
|
|
31
|
+
|
|
32
|
+
self.df_survey = pd.concat([cht_input_df, self.df_survey ,self.get_cht_summary() ], ignore_index=True)
|
|
33
|
+
|
|
18
34
|
def get_cht_input(self, start_pages, **kwargs):
|
|
19
35
|
empty = langs.get_trads('', force_dict =True)
|
|
20
36
|
df_input = pd.DataFrame(columns=SURVEY_MAP.keys())
|
|
@@ -120,6 +136,7 @@ class XLSFormCHTHFStrategy(XLSFormCHTStrategy):
|
|
|
120
136
|
*list(empty.values())
|
|
121
137
|
,'', '', '', '' ,''
|
|
122
138
|
]
|
|
139
|
+
self.get_contact_inputs(df_input)
|
|
123
140
|
inputs = self.export_inputs( start_pages[self.processes[0]], **kwargs)
|
|
124
141
|
for input in inputs:
|
|
125
142
|
df_input.loc[len(df_input)] = get_input_line(input)
|
|
@@ -308,27 +325,158 @@ class XLSFormCHTHFStrategy(XLSFormCHTStrategy):
|
|
|
308
325
|
|
|
309
326
|
|
|
310
327
|
|
|
328
|
+
return df_input
|
|
329
|
+
|
|
330
|
+
def get_contact_inputs(self, df_input):
|
|
331
|
+
empty = langs.get_trads('', force_dict =True)
|
|
332
|
+
|
|
333
|
+
df_input.loc[len(df_input)] = [
|
|
334
|
+
'calculate', 'patient_sex',
|
|
335
|
+
*list(langs.get_trads('Sex', force_dict = True).values()),
|
|
336
|
+
*list(empty.values()),
|
|
337
|
+
*list(empty.values()),
|
|
338
|
+
'', 'hidden', '',
|
|
339
|
+
*list(empty.values()),
|
|
340
|
+
'', '','',
|
|
341
|
+
*list(empty.values())
|
|
342
|
+
,'', '../inputs/contact/sex', '', '' ,''
|
|
343
|
+
]
|
|
344
|
+
df_input.loc[len(df_input)] = [
|
|
345
|
+
'calculate', 'patient_dob',
|
|
346
|
+
*list(langs.get_trads('Date of birth', force_dict = True).values()),
|
|
347
|
+
*list(empty.values()),
|
|
348
|
+
*list(empty.values()),
|
|
349
|
+
'', 'hidden', '',
|
|
350
|
+
*list(empty.values()),
|
|
351
|
+
'', '','',
|
|
352
|
+
*list(empty.values())
|
|
353
|
+
,'', 'date(../inputs/contact/date_of_birth)', '', '' ,''
|
|
354
|
+
]
|
|
355
|
+
|
|
311
356
|
return df_input
|
|
312
357
|
|
|
313
358
|
def get_cht_summary(self):
|
|
314
359
|
|
|
315
360
|
df_summary = pd.DataFrame(columns=SURVEY_MAP.keys())
|
|
316
361
|
#[ #type, '',#name ''#label, '',#hint '',#help '',#default '',#'appearance', '',#'constraint', '',#'constraint_message' '',#'relevance' '',#'disabled' '',#'required' '',#'required message' '',#'read only' '',#'expression' '',#'repeat_count' ''#'image' ],
|
|
317
|
-
#df_summary.loc[len(df_summary)] = [
|
|
318
|
-
#df_summary.loc[len(df_summary)] = [
|
|
319
|
-
#df_summary.loc[len(df_summary)] = [
|
|
320
|
-
#df_summary.loc[len(df_summary)] = [
|
|
321
|
-
#df_summary.loc[len(df_summary)] = [
|
|
362
|
+
#df_summary.loc[len(df_summary)] = [ 'begin group', 'group_summary' , 'Summary', '', '', '', 'field-list summary', '', '', '', '', '', '', '', '', '', '' ]
|
|
363
|
+
#df_summary.loc[len(df_summary)] = [ 'note', 'r_patient_info', '**${patient_name}** ID: ${patient_id}', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ]
|
|
364
|
+
#df_summary.loc[len(df_summary)] = [ 'note', 'r_followup', 'Follow Up <i class=“fa fa-flag”></i>', '', '', '', '', '', '','', '', '', '', '', '', '', '' ]
|
|
365
|
+
#df_summary.loc[len(df_summary)] = [ 'note', 'r_followup_note' ,'FOLLOWUP instruction', '', '', '', '', '', '', '','', '', '', '', '', '', '' ]
|
|
366
|
+
#df_summary.loc[len(df_summary)] = [ 'end group', '' ,'', '', '', '', '', '', '', '', '', '', '', '', '','', '' ]
|
|
322
367
|
return df_summary
|
|
323
368
|
|
|
324
|
-
def
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
369
|
+
def export(self, start_pages, version, **kwargs):
|
|
370
|
+
form_id = None
|
|
371
|
+
if start_pages[self.processes[0]].root.form_id is not None:
|
|
372
|
+
form_id= str(start_pages[self.processes[0]].root.form_id )
|
|
373
|
+
else:
|
|
374
|
+
logger.critical("form id required in the first start node")
|
|
375
|
+
exit(1)
|
|
376
|
+
title = remove_html(start_pages[self.processes[0]].root.label)
|
|
377
|
+
file_name = form_id + ".xlsx"
|
|
378
|
+
# make a 'settings' tab
|
|
379
|
+
now = datetime.datetime.now()
|
|
380
|
+
version=now.strftime('%Y%m%d%H%M')
|
|
381
|
+
indx=[[1]]
|
|
382
|
+
# CHT FORCE file name to be equal to id
|
|
383
|
+
|
|
384
|
+
newfilename = form_id + ".xlsx"
|
|
385
|
+
newpath = os.path.join(self.output_path, newfilename)
|
|
386
|
+
media_path = os.path.join(self.output_path, form_id + "-media")
|
|
387
|
+
|
|
388
|
+
settings={'form_title':title,'form_id':form_id,'version':version,'default_language':'English (en)','style':'pages'}
|
|
389
|
+
df_settings=pd.DataFrame(settings,index=indx)
|
|
390
|
+
df_settings.head()
|
|
391
|
+
if len(self.df_survey[self.df_survey['name'] == 'version'] ):
|
|
392
|
+
self.df_survey.loc[ self.df_survey['name'] == 'version', 'label'] = f"v{version}"
|
|
393
|
+
#create a Pandas Excel writer using XlsxWriter as the engine
|
|
394
|
+
writer = pd.ExcelWriter(newpath, engine='xlsxwriter')
|
|
395
|
+
self.df_survey.to_excel(writer, sheet_name='survey',index=False)
|
|
396
|
+
self.df_choice.to_excel(writer, sheet_name='choices',index=False)
|
|
397
|
+
df_settings.to_excel(writer, sheet_name='settings',index=False)
|
|
398
|
+
writer.close()
|
|
399
|
+
# pause
|
|
400
|
+
ends = []
|
|
401
|
+
for p in self.project.pages.values():
|
|
402
|
+
p_ends = list(filter(lambda x: issubclass(x.__class__, TriccNodeEnd) and getattr(x, 'process', '') == 'pause', p.nodes.values() ))
|
|
403
|
+
if p_ends:
|
|
404
|
+
ends += p_ends
|
|
405
|
+
if ends:
|
|
406
|
+
ends_prev = []
|
|
407
|
+
for e in ends:
|
|
408
|
+
|
|
409
|
+
latest = None
|
|
410
|
+
for p in e.prev_nodes:
|
|
411
|
+
if not latest or latest.path_len < p.path_len:
|
|
412
|
+
latest = p
|
|
413
|
+
if hasattr(latest, 'select'):
|
|
414
|
+
latest = latest.select
|
|
415
|
+
ends_prev.append(
|
|
416
|
+
(int(self.df_survey[self.df_survey.name == latest.export_name].index.values[0]), e,)
|
|
417
|
+
)
|
|
418
|
+
forms = [form_id]
|
|
419
|
+
for i, e in ends_prev:
|
|
420
|
+
new_form_id = f"{form_id}_{clean_name(e.name)}"
|
|
421
|
+
newfilename = f"{new_form_id}.xlsx"
|
|
422
|
+
newpath = os.path.join(self.output_path, newfilename)
|
|
423
|
+
settings={'form_title':title,'form_id':f"{new_form_id}",'version':version,'default_language':'English (en)','style':'pages'}
|
|
424
|
+
df_settings=pd.DataFrame(settings,index=indx)
|
|
425
|
+
df_settings.head()
|
|
426
|
+
task_df, hidden_names = make_breakpoints(self.df_survey, i, e.name, replace_dots=True)
|
|
427
|
+
# deactivate the end node
|
|
428
|
+
task_df.loc[task_df['name'] == get_export_name(e), 'calculation'] = 0
|
|
429
|
+
#print fileds
|
|
430
|
+
writer = pd.ExcelWriter(newpath, engine='xlsxwriter')
|
|
431
|
+
task_df.to_excel(writer, sheet_name='survey',index=False)
|
|
432
|
+
self.df_choice.to_excel(writer, sheet_name='choices',index=False)
|
|
433
|
+
df_settings.to_excel(writer, sheet_name='settings',index=False)
|
|
434
|
+
writer.close()
|
|
435
|
+
newfilename = f"{new_form_id}.js"
|
|
436
|
+
newpath = os.path.join(self.output_path, newfilename)
|
|
437
|
+
with open(newpath, 'w') as f:
|
|
438
|
+
f.write(
|
|
439
|
+
get_task_js(
|
|
440
|
+
new_form_id,
|
|
441
|
+
e.name,
|
|
442
|
+
f"continue {title}",
|
|
443
|
+
forms,
|
|
444
|
+
hidden_names,
|
|
445
|
+
self.df_survey,
|
|
446
|
+
repalce_dots=False,
|
|
447
|
+
task_title=e.hint
|
|
448
|
+
)
|
|
449
|
+
)
|
|
450
|
+
f.close()
|
|
451
|
+
forms.append(new_form_id)
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
media_path_tmp = os.path.join(self.output_path, 'media-tmp')
|
|
456
|
+
if (os.path.isdir(media_path_tmp)):
|
|
457
|
+
if os.path.isdir(media_path): # check if it exists, because if it does, error will be raised
|
|
458
|
+
shutil.rmtree(media_path)
|
|
459
|
+
# (later change to make folder complaint to CHT)
|
|
460
|
+
os.mkdir(media_path)
|
|
461
|
+
|
|
462
|
+
file_names = os.listdir(media_path_tmp)
|
|
463
|
+
for file_name in file_names:
|
|
464
|
+
shutil.move(os.path.join(media_path_tmp, file_name), media_path)
|
|
465
|
+
shutil.rmtree(media_path_tmp)
|
|
332
466
|
|
|
467
|
+
def tricc_operation_zscore(self, ref_expressions):
|
|
468
|
+
y, ll, m, s = self.get_zscore_params(ref_expressions)
|
|
469
|
+
# return ((Math.pow((y / m), l) - 1) / (s * l));
|
|
470
|
+
return f"cht:extension-lib('{ref_expressions[0][1:-1]}.js',{self.clean_coalesce(ref_expressions[1])} ,{self.clean_coalesce(ref_expressions[2])} ,{self.clean_coalesce(ref_expressions[3])})"
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
def tricc_operation_izscore(self, ref_expressions):
|
|
474
|
+
z, ll, m, s = self.get_zscore_params(ref_expressions)
|
|
475
|
+
# return (m * (z*s*l-1)^(1/l));
|
|
476
|
+
return f"cht:extension-lib('{ref_expressions[0][1:-1]}.js',{self.clean_coalesce(ref_expressions[1])} ,{self.clean_coalesce(ref_expressions[2])} ,{self.clean_coalesce(ref_expressions[3])}, true)"
|
|
333
477
|
|
|
334
|
-
|
|
478
|
+
def tricc_operation_drug_dosage(self, ref_expressions):
|
|
479
|
+
# drug name
|
|
480
|
+
# age
|
|
481
|
+
#weight
|
|
482
|
+
return f"cht:extension-lib('drugs.js',{','.join(map(self.clean_coalesce, ref_expressions))})"
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
import shutil
|
|
5
|
+
|
|
6
|
+
import pandas as pd
|
|
7
|
+
|
|
8
|
+
from tricc_oo.models.lang import SingletonLangClass
|
|
9
|
+
from tricc_oo.serializers.xls_form import SURVEY_MAP,get_input_line, get_input_calc_line
|
|
10
|
+
from tricc_oo.strategies.output.xlsform_cht import XLSFormCHTStrategy
|
|
11
|
+
from tricc_oo.visitors.xform_pd import make_breakpoints, get_tasksstrings
|
|
12
|
+
|
|
13
|
+
langs = SingletonLangClass()
|
|
14
|
+
logger = logging.getLogger("default")
|
|
15
|
+
|
|
16
|
+
class XLSFormCHTHFStrategy(XLSFormCHTStrategy):
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_contact_inputs(df_inputs):
|
|
20
|
+
return None
|
|
21
|
+
|
|
22
|
+
def get_cht_summary(self):
|
|
23
|
+
|
|
24
|
+
df_summary = pd.DataFrame(columns=SURVEY_MAP.keys())
|
|
25
|
+
#[ #type, '',#name ''#label, '',#hint '',#help '',#default '',#'appearance', '',#'constraint', '',#'constraint_message' '',#'relevance' '',#'disabled' '',#'required' '',#'required message' '',#'read only' '',#'expression' '',#'repeat_count' ''#'image' ],
|
|
26
|
+
#df_summary.loc[len(df_summary)] = [ 'begin_group', 'group_summary' , 'Summary', '', '', '', 'field-list summary', '', '', '', '', '', '', '', '', '', '' ]
|
|
27
|
+
#df_summary.loc[len(df_summary)] = [ 'note', 'r_patient_info', '**${patient_name}** ID: ${patient_id}', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ]
|
|
28
|
+
#df_summary.loc[len(df_summary)] = [ 'note', 'r_followup', 'Follow Up <i class=“fa fa-flag”></i>', '', '', '', '', '', '','', '', '', '', '', '', '', '' ]
|
|
29
|
+
#df_summary.loc[len(df_summary)] = [ 'note', 'r_followup_note' ,'FOLLOWUP instruction', '', '', '', '', '', '', '','', '', '', '', '', '', '' ]
|
|
30
|
+
#df_summary.loc[len(df_summary)] = [ 'end_group', '' ,'', '', '', '', '', '', '', '', '', '', '', '', '','', '' ]
|
|
31
|
+
return df_summary
|
|
32
|
+
|
|
33
|
+
def tricc_operation_age_day(self, exps):
|
|
34
|
+
raise NotImplemented("AgeInDays Not compatible with this strategy")
|
|
35
|
+
|
|
36
|
+
def tricc_operation_age_year(self, exps):
|
|
37
|
+
raise NotImplemented("AgeInYears Not compatible with this strategy")
|
|
38
|
+
|
|
39
|
+
def tricc_operation_age_month(self, exps):
|
|
40
|
+
raise NotImplemented("AgeInMonths Not compatible with this strategy")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
@@ -93,6 +93,81 @@ def get_node_expressions(node, processed_nodes, process=None):
|
|
|
93
93
|
expression = TriccStatic(True)
|
|
94
94
|
return expression
|
|
95
95
|
|
|
96
|
+
def set_last_version_false(node, processed_nodes):
|
|
97
|
+
node_name = node.name if not isinstance(node, TriccNodeEnd) else node.get_reference()
|
|
98
|
+
last_version = get_last_version(node_name, processed_nodes) if issubclass(node.__class__, (TriccNodeDisplayModel, TriccNodeDisplayCalculateBase, TriccNodeEnd)) and not isinstance(node, TriccNodeSelectOption) else None
|
|
99
|
+
#last_version = processed_nodes.find_prev(node, lambda item: hasattr(item, 'name') and item.name == node.name)
|
|
100
|
+
if last_version and getattr(node, 'process', '') != 'pause':
|
|
101
|
+
# 0-100 for manually specified instance. 100-200 for auto instance
|
|
102
|
+
node.version = last_version.version + 1
|
|
103
|
+
last_version.last = False
|
|
104
|
+
node.path_len = max(node.path_len, last_version.path_len + 1)
|
|
105
|
+
return last_version
|
|
106
|
+
|
|
107
|
+
def get_version_inheritance(node, last_version, processed_nodes):
|
|
108
|
+
# FIXME this is for XLS form where only calculate are evaluated for a activity that is not triggered
|
|
109
|
+
if not issubclass(node.__class__, (TriccNodeInputModel)):
|
|
110
|
+
node.last = True
|
|
111
|
+
if (
|
|
112
|
+
issubclass(node.__class__, (TriccNodeDisplayCalculateBase, TriccNodeEnd)) and node.name is not None
|
|
113
|
+
):
|
|
114
|
+
#logger.debug("set last to false for node {} and add its link it to next one".format(last_used_calc.get_name()))
|
|
115
|
+
if node.prev_nodes:
|
|
116
|
+
set_prev_next_node(last_version, node)
|
|
117
|
+
else:
|
|
118
|
+
expression = node.expression or node.expression_reference or getattr(node, 'relevance', None)
|
|
119
|
+
datatype = expression.get_datatype()
|
|
120
|
+
if datatype == 'boolean':
|
|
121
|
+
expression_reference = TriccOperation(
|
|
122
|
+
TriccOperator.OR,
|
|
123
|
+
[TriccOperation(TriccOperator.ISTRUE, [last_version]), expression]
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
elif datatype == 'number':
|
|
127
|
+
expression = TriccOperation(
|
|
128
|
+
TriccOperator.PLUS,
|
|
129
|
+
[last_version, expression]
|
|
130
|
+
)
|
|
131
|
+
else:
|
|
132
|
+
expression = TriccOperation(
|
|
133
|
+
TriccOperator.COALESCE,
|
|
134
|
+
[last_version, expression]
|
|
135
|
+
)
|
|
136
|
+
if node.expression:
|
|
137
|
+
node.expression = expression
|
|
138
|
+
elif node.expression_reference:
|
|
139
|
+
node.expression_reference = expression
|
|
140
|
+
elif node.relevance:
|
|
141
|
+
node.relevance = expression
|
|
142
|
+
else:
|
|
143
|
+
node.last = False
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
calc = TriccNodeCalculate(
|
|
147
|
+
id=generate_id(f"save{node.id}"),
|
|
148
|
+
name=node.name,
|
|
149
|
+
path_len=node.path_len+1,
|
|
150
|
+
version=get_next_version(node.name, processed_nodes, node.version+2),
|
|
151
|
+
expression=TriccOperation(
|
|
152
|
+
TriccOperator.COALESCE,
|
|
153
|
+
[node, last_version, TriccStatic("''")]
|
|
154
|
+
),
|
|
155
|
+
last=True,
|
|
156
|
+
activity=node.activity,
|
|
157
|
+
group=node.group
|
|
158
|
+
)
|
|
159
|
+
node.activity.nodes[calc.id]=calc
|
|
160
|
+
node.activity.calculates.append(calc)
|
|
161
|
+
set_last_version_false(calc, processed_nodes)
|
|
162
|
+
processed_nodes.add(calc)
|
|
163
|
+
if issubclass(node.__class__, TriccNodeInputModel):
|
|
164
|
+
node.expression = TriccOperation(
|
|
165
|
+
TriccOperator.COALESCE,
|
|
166
|
+
[
|
|
167
|
+
'$this',
|
|
168
|
+
last_version
|
|
169
|
+
]
|
|
170
|
+
)
|
|
96
171
|
|
|
97
172
|
def process_calculate(node,processed_nodes, stashed_nodes, calculates, used_calculates,
|
|
98
173
|
warn = False, process=None, **kwargs ):
|
|
@@ -117,76 +192,11 @@ def process_calculate(node,processed_nodes, stashed_nodes, calculates, used_calc
|
|
|
117
192
|
):
|
|
118
193
|
if kwargs.get('warn', True):
|
|
119
194
|
logger.debug('Processing relevance for node {0}'.format(node.get_name()))
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
node.version = last_version.version + 1
|
|
126
|
-
last_version.last = False
|
|
127
|
-
node.path_len = max(node.path_len, last_version.path_len + 1)
|
|
128
|
-
# FIXME this is for XLS form where only calculate are evaluated for a activity that is not triggered
|
|
129
|
-
if not issubclass(node.__class__, (TriccNodeInputModel)):
|
|
130
|
-
node.last = True
|
|
131
|
-
if (
|
|
132
|
-
issubclass(node.__class__, (TriccNodeDisplayCalculateBase, TriccNodeEnd)) and node.name is not None
|
|
133
|
-
):
|
|
134
|
-
#logger.debug("set last to false for node {} and add its link it to next one".format(last_used_calc.get_name()))
|
|
135
|
-
if node.prev_nodes:
|
|
136
|
-
set_prev_next_node(last_version, node)
|
|
137
|
-
else:
|
|
138
|
-
expression = node.expression or node.expression_reference or node.relevance
|
|
139
|
-
datatype = expression.get_datatype()
|
|
140
|
-
if datatype == 'boolean':
|
|
141
|
-
expression_reference = TriccOperation(
|
|
142
|
-
TriccOperator.OR,
|
|
143
|
-
[TriccOperation(TriccOperator.ISTRUE, [last_version]), expression]
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
elif datatype == 'number':
|
|
147
|
-
expression = TriccOperation(
|
|
148
|
-
TriccOperator.PLUS,
|
|
149
|
-
[last_version, expression]
|
|
150
|
-
)
|
|
151
|
-
else:
|
|
152
|
-
expression = TriccOperation(
|
|
153
|
-
TriccOperator.COALESCE,
|
|
154
|
-
[last_version, expression]
|
|
155
|
-
)
|
|
156
|
-
if node.expression:
|
|
157
|
-
node.expression = expression
|
|
158
|
-
elif node.expression_reference:
|
|
159
|
-
node.expression_reference = expression
|
|
160
|
-
elif node.relevance:
|
|
161
|
-
node.relevance = expression
|
|
162
|
-
else:
|
|
163
|
-
node.last = False
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
calc = TriccNodeCalculate(
|
|
167
|
-
id=generate_id(f"save{node.id}"),
|
|
168
|
-
name=node.name,
|
|
169
|
-
path_len=node.path_len+1,
|
|
170
|
-
version=last_version.version + 2,
|
|
171
|
-
expression=TriccOperation(
|
|
172
|
-
TriccOperator.COALESCE,
|
|
173
|
-
[node, last_version, TriccStatic("''")]
|
|
174
|
-
),
|
|
175
|
-
last=True,
|
|
176
|
-
activity=node.activity,
|
|
177
|
-
group=node.group
|
|
178
|
-
)
|
|
179
|
-
node.activity.nodes[calc.id]=calc
|
|
180
|
-
node.activity.calculates.append(calc)
|
|
181
|
-
if issubclass(node.__class__, TriccNodeInputModel):
|
|
182
|
-
node.expression = TriccOperation(
|
|
183
|
-
TriccOperator.COALESCE,
|
|
184
|
-
[
|
|
185
|
-
'$this',
|
|
186
|
-
last_version
|
|
187
|
-
]
|
|
188
|
-
)
|
|
189
|
-
|
|
195
|
+
last_version = set_last_version_false(node, processed_nodes)
|
|
196
|
+
if last_version:
|
|
197
|
+
last_version = get_version_inheritance(node, last_version, processed_nodes)
|
|
198
|
+
generate_calculates(node,calculates, used_calculates,processed_nodes=processed_nodes)
|
|
199
|
+
|
|
190
200
|
|
|
191
201
|
|
|
192
202
|
# if has prev, create condition
|
|
@@ -218,7 +228,6 @@ def process_calculate(node,processed_nodes, stashed_nodes, calculates, used_calc
|
|
|
218
228
|
if issubclass(r.__class__, (TriccNodeDisplayCalculateBase )):
|
|
219
229
|
add_used_calculate(node, r, calculates, used_calculates, processed_nodes)
|
|
220
230
|
|
|
221
|
-
generate_calculates(node,calculates, used_calculates,processed_nodes=processed_nodes)
|
|
222
231
|
if last_version and hasattr(node, 'relevance'):
|
|
223
232
|
if isinstance(node, TriccNodeInputModel):
|
|
224
233
|
version_relevance = TriccOperation(
|
|
@@ -468,16 +477,23 @@ def generate_calculates(node,calculates, used_calculates,processed_nodes):
|
|
|
468
477
|
calc_node.path_len += 1
|
|
469
478
|
calc_node.name=calculate_name
|
|
470
479
|
calc_node.label = "save select: " +node.get_name()
|
|
471
|
-
|
|
480
|
+
elif node.name != calculate_name:
|
|
472
481
|
calc_id = generate_id(f"autosave{node.id}")
|
|
482
|
+
|
|
473
483
|
calc_node = TriccNodeCalculate(
|
|
474
484
|
name=calculate_name,
|
|
475
485
|
id = calc_id,
|
|
476
486
|
group = node.group,
|
|
487
|
+
version=get_next_version(calculate_name, processed_nodes, node.version+2),
|
|
477
488
|
activity = node.activity,
|
|
478
489
|
label = "save: " +node.get_name(),
|
|
479
|
-
path_len=node.path_len+ 1
|
|
490
|
+
path_len=node.path_len+ 1,
|
|
491
|
+
last=True
|
|
480
492
|
)
|
|
493
|
+
node.activity.nodes[calc_node.id]=calc_node
|
|
494
|
+
node.activity.calculates.append(calc_node)
|
|
495
|
+
set_last_version_false(calc_node, processed_nodes)
|
|
496
|
+
processed_nodes.add(calc_node)
|
|
481
497
|
logger.debug("generate_save_calculate:{}:{} as {}".format(calc_node.tricc_type, node.name if hasattr(node,'name') else node.id, calculate_name))
|
|
482
498
|
if isinstance(node, TriccNodeSelectYesNo):
|
|
483
499
|
yesNode = node.options[0]
|
|
@@ -948,6 +964,9 @@ def walkthrough_tricc_option(node, callback, processed_nodes, stashed_nodes, pat
|
|
|
948
964
|
warn = warn,
|
|
949
965
|
node_path = node_path.copy(), **kwargs)
|
|
950
966
|
|
|
967
|
+
def get_next_version(name, processed_nodes, version=0,):
|
|
968
|
+
return max(version, 100,*[(getattr(n,'version',0) or getattr(n,'instance',0) or 0) for n in get_versions(name, processed_nodes)])
|
|
969
|
+
|
|
951
970
|
|
|
952
971
|
def get_data_for_log(node):
|
|
953
972
|
return "{}:{}|{} {}:{}".format(
|
|
@@ -1207,6 +1226,7 @@ def get_all_dependant(loop, stashed_nodes, processed_nodes, depth=0, waited=None
|
|
|
1207
1226
|
looped = {}
|
|
1208
1227
|
if waited is None:
|
|
1209
1228
|
waited = {}
|
|
1229
|
+
all_dependant = OrderedSet()
|
|
1210
1230
|
for n in loop:
|
|
1211
1231
|
cur_path = path.copy()
|
|
1212
1232
|
cur_path.append(n)
|
|
@@ -1222,7 +1242,7 @@ def get_all_dependant(loop, stashed_nodes, processed_nodes, depth=0, waited=None
|
|
|
1222
1242
|
pass
|
|
1223
1243
|
for d in dependant:
|
|
1224
1244
|
if d in path:
|
|
1225
|
-
logger.warning(f"loop {str(d)} already in path {'::'.join(map(
|
|
1245
|
+
logger.warning(f"loop {str(d)} already in path {'::'.join(map(str, path))} ")
|
|
1226
1246
|
if isinstance(d, TriccNodeSelectOption):
|
|
1227
1247
|
d = d.select
|
|
1228
1248
|
|
|
@@ -1238,9 +1258,10 @@ def get_all_dependant(loop, stashed_nodes, processed_nodes, depth=0, waited=None
|
|
|
1238
1258
|
looped = add_to_tree(looped, n, d)
|
|
1239
1259
|
else :
|
|
1240
1260
|
waited = add_to_tree(waited, n, d)
|
|
1261
|
+
all_dependant = all_dependant.union(dependant)
|
|
1241
1262
|
if depth < MAX_DRILL:
|
|
1242
|
-
|
|
1243
|
-
|
|
1263
|
+
waited, looped = get_all_dependant(all_dependant, stashed_nodes, processed_nodes, depth+1, waited , looped, path=cur_path)
|
|
1264
|
+
|
|
1244
1265
|
return waited, looped
|
|
1245
1266
|
|
|
1246
1267
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: tricc-oo
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.21
|
|
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
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import datetime
|
|
2
|
-
import logging
|
|
3
|
-
import os
|
|
4
|
-
import shutil
|
|
5
|
-
import re
|
|
6
|
-
import pandas as pd
|
|
7
|
-
|
|
8
|
-
from tricc_oo.models.lang import SingletonLangClass
|
|
9
|
-
from tricc_oo.models.calculate import TriccNodeEnd
|
|
10
|
-
from tricc_oo.serializers.xls_form import SURVEY_MAP, get_input_line
|
|
11
|
-
from tricc_oo.strategies.output.xlsform_cdss import XLSFormCDSSStrategy
|
|
12
|
-
from tricc_oo.converters.tricc_to_xls_form import get_export_name
|
|
13
|
-
from tricc_oo.converters.utils import clean_name, remove_html
|
|
14
|
-
from tricc_oo.visitors.xform_pd import make_breakpoints, get_task_js
|
|
15
|
-
|
|
16
|
-
langs = SingletonLangClass()
|
|
17
|
-
logger = logging.getLogger("default")
|
|
18
|
-
|
|
19
|
-
class XLSFormCHTStrategy(XLSFormCDSSStrategy):
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def process_export(self, start_pages, **kwargs):
|
|
23
|
-
diags = []
|
|
24
|
-
self.activity_export(start_pages[self.processes[0]], **kwargs)
|
|
25
|
-
#self.add_tab_breaks_choice()
|
|
26
|
-
cht_header = pd.DataFrame(columns=SURVEY_MAP.keys())
|
|
27
|
-
cht_input_df = self.get_cht_input( start_pages, **kwargs)
|
|
28
|
-
self.df_survey= self.df_survey[~self.df_survey['name'].isin(cht_input_df['name'])]
|
|
29
|
-
self.df_survey.reset_index(drop=True, inplace=True)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
self.df_survey = pd.concat([cht_input_df, self.df_survey ,self.get_cht_summary() ], ignore_index=True)
|
|
33
|
-
|
|
34
|
-
def get_cht_input(self, start_pages, **kwargs):
|
|
35
|
-
df_input = pd.DataFrame(columns=SURVEY_MAP.keys())
|
|
36
|
-
#[ #type, '',#name ''#label, '',#hint '',#help '',#default '',#'appearance', '',#'constraint', '',#'constraint_message' '',#'relevance' '',#'disabled' '',#'required' '',#'required message' '',#'read only' '',#'expression' '',#'repeat_count' ''#'image' ],
|
|
37
|
-
df_input.loc[len(df_input)] = [ 'begin group', 'inputs' ,*list(langs.get_trads('Inputs', force_dict = True).values()), *list(langs.get_trads('', force_dict = True).values()), *list(langs.get_trads('', force_dict = True).values()), '', 'field-list', '', *list(langs.get_trads('', force_dict = True).values()), './source = "user"', '','', *list(langs.get_trads('', force_dict = True).values()) ,'', '', '', '', '' ]
|
|
38
|
-
df_input.loc[len(df_input)] = [ 'hidden', 'source', *list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()) ,'', '', '', '', '' ]
|
|
39
|
-
df_input.loc[len(df_input)] = [ 'hidden', 'source_id',*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()) ,'', '', '', '', '' ]
|
|
40
|
-
inputs = self.export_inputs( start_pages[self.processes[0]], **kwargs)
|
|
41
|
-
for input in inputs:
|
|
42
|
-
df_input.loc[len(df_input)] = get_input_line(input)
|
|
43
|
-
df_input.loc[len(df_input)] = [
|
|
44
|
-
'hidden', 'data_load',
|
|
45
|
-
*list(langs.get_trads('NO_LABEL', force_dict = True).values()),
|
|
46
|
-
*list(langs.get_trads('', force_dict = True).values()),
|
|
47
|
-
*list(langs.get_trads('', force_dict = True).values()),
|
|
48
|
-
'', 'hidden', '',
|
|
49
|
-
*list(langs.get_trads('', force_dict = True).values()),
|
|
50
|
-
'', '','',
|
|
51
|
-
*list(langs.get_trads('', force_dict = True).values())
|
|
52
|
-
,'', '', '', ''
|
|
53
|
-
]
|
|
54
|
-
df_input.loc[len(df_input)] = [ 'hidden', 'task_id' ,*list(langs.get_trads('Task ID', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()) ,'', '', '', '', '' ]
|
|
55
|
-
df_input.loc[len(df_input)] = [ 'begin group ', 'contact' ,*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()) ,'', '', '', '', '' ]
|
|
56
|
-
df_input.loc[len(df_input)] = [ 'db:person', '_id', *list(langs.get_trads('Patient ID', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()), '', 'db-object', '', *list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()) ,'', '', '', '', '' ]
|
|
57
|
-
df_input.loc[len(df_input)] = [ 'string', 'patient_id' ,*list(langs.get_trads('Medic ID', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()), '', 'hidden', '', *list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()) ,'', '', '', '', '' ]
|
|
58
|
-
df_input.loc[len(df_input)] = [ 'string', 'patient_name',*list(langs.get_trads('Patient Name', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()), '', 'hidden', '', *list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()) ,'', '', '', '', '' ]
|
|
59
|
-
df_input.loc[len(df_input)] = [ 'date', 'date_of_birth',*list(langs.get_trads('Date of birth', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()), '', 'hidden', '', *list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()) ,'', '', '', '', '' ]
|
|
60
|
-
df_input.loc[len(df_input)] = [ 'string', 'sex',*list(langs.get_trads('Patient Sex', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()), '', 'hidden', '', *list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()) ,'', '', '', '', '' ]
|
|
61
|
-
df_input.loc[len(df_input)] = [ 'end group', '' ,*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()) ,'', '', '', '', '' ]
|
|
62
|
-
df_input.loc[len(df_input)] = [ 'end group', '' ,*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()) ,'', '', '', '', '' ]
|
|
63
|
-
df_input.loc[len(df_input)] = [ 'calculate', '_id' ,*list(langs.get_trads('label', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', '../inputs/contact/_id', '', '' , '' ]
|
|
64
|
-
df_input.loc[len(df_input)] = [ 'calculate', 'patient_uuid' ,*list(langs.get_trads('label', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', '../inputs/contact/patient_id', '', '' , '' ]
|
|
65
|
-
df_input.loc[len(df_input)] = [ 'calculate', 'p_name' ,*list(langs.get_trads('label', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', '../inputs/contact/patient_name', '', '' , '' ]
|
|
66
|
-
|
|
67
|
-
df_input.loc[len(df_input)] = [ 'calculate', 'p_age_days' ,*list(langs.get_trads('label', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', 'int((today()-date(${date_of_birth})))', '', '' , '' ]
|
|
68
|
-
df_input.loc[len(df_input)] = [ 'calculate', 'p_age_months' ,*list(langs.get_trads('label', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', 'int(${id.age_day} div 30.4)', '', '' , '' ]
|
|
69
|
-
df_input.loc[len(df_input)] = [ 'calculate', 'p_age_years' ,*list(langs.get_trads('label', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', 'int(${p_age_month} div 12)', '', '' , '' ]
|
|
70
|
-
df_input.loc[len(df_input)] = [ 'calculate', 'p_sex' ,*list(langs.get_trads('label', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', '../inputs/contact/sex', '', '' , '' ]
|
|
71
|
-
df_input.loc[len(df_input)] = [ 'calculate', 'p_dob',*list(langs.get_trads('Date of birth', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()),*list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', '', '', *list(langs.get_trads('', force_dict = True).values()), '', 'date(../inputs/contact/date_of_birth)', '','' , '' ]
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
return df_input
|
|
75
|
-
|
|
76
|
-
def get_cht_summary(self):
|
|
77
|
-
|
|
78
|
-
df_summary = pd.DataFrame(columns=SURVEY_MAP.keys())
|
|
79
|
-
#[ #type, '',#name ''#label, '',#hint '',#help '',#default '',#'appearance', '',#'constraint', '',#'constraint_message' '',#'relevance' '',#'disabled' '',#'required' '',#'required message' '',#'read only' '',#'expression' '',#'repeat_count' ''#'image' ],
|
|
80
|
-
#df_summary.loc[len(df_summary)] = [ 'begin group', 'group_summary' , 'Summary', '', '', '', 'field-list summary', '', '', '', '', '', '', '', '', '', '' ]
|
|
81
|
-
#df_summary.loc[len(df_summary)] = [ 'note', 'r_patient_info', '**${patient_name}** ID: ${patient_id}', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ]
|
|
82
|
-
#df_summary.loc[len(df_summary)] = [ 'note', 'r_followup', 'Follow Up <i class=“fa fa-flag”></i>', '', '', '', '', '', '','', '', '', '', '', '', '', '' ]
|
|
83
|
-
#df_summary.loc[len(df_summary)] = [ 'note', 'r_followup_note' ,'FOLLOWUP instruction', '', '', '', '', '', '', '','', '', '', '', '', '', '' ]
|
|
84
|
-
#df_summary.loc[len(df_summary)] = [ 'end group', '' ,'', '', '', '', '', '', '', '', '', '', '', '', '','', '' ]
|
|
85
|
-
return df_summary
|
|
86
|
-
|
|
87
|
-
def export(self, start_pages, version, **kwargs):
|
|
88
|
-
form_id = None
|
|
89
|
-
if start_pages[self.processes[0]].root.form_id is not None:
|
|
90
|
-
form_id= str(start_pages[self.processes[0]].root.form_id )
|
|
91
|
-
else:
|
|
92
|
-
logger.critical("form id required in the first start node")
|
|
93
|
-
exit(1)
|
|
94
|
-
title = remove_html(start_pages[self.processes[0]].root.label)
|
|
95
|
-
file_name = form_id + ".xlsx"
|
|
96
|
-
# make a 'settings' tab
|
|
97
|
-
now = datetime.datetime.now()
|
|
98
|
-
version=now.strftime('%Y%m%d%H%M')
|
|
99
|
-
indx=[[1]]
|
|
100
|
-
# CHT FORCE file name to be equal to id
|
|
101
|
-
|
|
102
|
-
newfilename = form_id + ".xlsx"
|
|
103
|
-
newpath = os.path.join(self.output_path, newfilename)
|
|
104
|
-
media_path = os.path.join(self.output_path, form_id + "-media")
|
|
105
|
-
|
|
106
|
-
settings={'form_title':title,'form_id':form_id,'version':version,'default_language':'English (en)','style':'pages'}
|
|
107
|
-
df_settings=pd.DataFrame(settings,index=indx)
|
|
108
|
-
df_settings.head()
|
|
109
|
-
if len(self.df_survey[self.df_survey['name'] == 'version'] ):
|
|
110
|
-
self.df_survey.loc[ self.df_survey['name'] == 'version', 'label'] = f"v{version}"
|
|
111
|
-
#create a Pandas Excel writer using XlsxWriter as the engine
|
|
112
|
-
writer = pd.ExcelWriter(newpath, engine='xlsxwriter')
|
|
113
|
-
self.df_survey.to_excel(writer, sheet_name='survey',index=False)
|
|
114
|
-
self.df_choice.to_excel(writer, sheet_name='choices',index=False)
|
|
115
|
-
df_settings.to_excel(writer, sheet_name='settings',index=False)
|
|
116
|
-
writer.close()
|
|
117
|
-
# pause
|
|
118
|
-
ends = []
|
|
119
|
-
for p in self.project.pages.values():
|
|
120
|
-
p_ends = list(filter(lambda x: issubclass(x.__class__, TriccNodeEnd) and getattr(x, 'process', '') == 'pause', p.nodes.values() ))
|
|
121
|
-
if p_ends:
|
|
122
|
-
ends += p_ends
|
|
123
|
-
if ends:
|
|
124
|
-
ends_prev = []
|
|
125
|
-
for e in ends:
|
|
126
|
-
|
|
127
|
-
latest = None
|
|
128
|
-
for p in e.prev_nodes:
|
|
129
|
-
if not latest or latest.path_len < p.path_len:
|
|
130
|
-
latest = p
|
|
131
|
-
if hasattr(latest, 'select'):
|
|
132
|
-
latest = latest.select
|
|
133
|
-
ends_prev.append(
|
|
134
|
-
(int(self.df_survey[self.df_survey.name == latest.export_name].index.values[0]), e,)
|
|
135
|
-
)
|
|
136
|
-
forms = [form_id]
|
|
137
|
-
for i, e in ends_prev:
|
|
138
|
-
new_form_id = f"{form_id}_{clean_name(e.name)}"
|
|
139
|
-
newfilename = f"{new_form_id}.xlsx"
|
|
140
|
-
newpath = os.path.join(self.output_path, newfilename)
|
|
141
|
-
settings={'form_title':title,'form_id':f"{new_form_id}",'version':version,'default_language':'English (en)','style':'pages'}
|
|
142
|
-
df_settings=pd.DataFrame(settings,index=indx)
|
|
143
|
-
df_settings.head()
|
|
144
|
-
task_df, hidden_names = make_breakpoints(self.df_survey, i, e.name, replace_dots=True)
|
|
145
|
-
# deactivate the end node
|
|
146
|
-
task_df.loc[task_df['name'] == get_export_name(e), 'calculation'] = 0
|
|
147
|
-
#print fileds
|
|
148
|
-
writer = pd.ExcelWriter(newpath, engine='xlsxwriter')
|
|
149
|
-
task_df.to_excel(writer, sheet_name='survey',index=False)
|
|
150
|
-
self.df_choice.to_excel(writer, sheet_name='choices',index=False)
|
|
151
|
-
df_settings.to_excel(writer, sheet_name='settings',index=False)
|
|
152
|
-
writer.close()
|
|
153
|
-
newfilename = f"{new_form_id}.js"
|
|
154
|
-
newpath = os.path.join(self.output_path, newfilename)
|
|
155
|
-
with open(newpath, 'w') as f:
|
|
156
|
-
f.write(
|
|
157
|
-
get_task_js(
|
|
158
|
-
new_form_id,
|
|
159
|
-
e.name,
|
|
160
|
-
f"continue {title}",
|
|
161
|
-
forms,
|
|
162
|
-
hidden_names,
|
|
163
|
-
self.df_survey,
|
|
164
|
-
repalce_dots=False,
|
|
165
|
-
task_title=e.hint
|
|
166
|
-
)
|
|
167
|
-
)
|
|
168
|
-
f.close()
|
|
169
|
-
forms.append(new_form_id)
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
media_path_tmp = os.path.join(self.output_path, 'media-tmp')
|
|
174
|
-
if (os.path.isdir(media_path_tmp)):
|
|
175
|
-
if os.path.isdir(media_path): # check if it exists, because if it does, error will be raised
|
|
176
|
-
shutil.rmtree(media_path)
|
|
177
|
-
# (later change to make folder complaint to CHT)
|
|
178
|
-
os.mkdir(media_path)
|
|
179
|
-
|
|
180
|
-
file_names = os.listdir(media_path_tmp)
|
|
181
|
-
for file_name in file_names:
|
|
182
|
-
shutil.move(os.path.join(media_path_tmp, file_name), media_path)
|
|
183
|
-
shutil.rmtree(media_path_tmp)
|
|
184
|
-
|
|
185
|
-
def tricc_operation_zscore(self, ref_expressions):
|
|
186
|
-
y, ll, m, s = self.get_zscore_params(ref_expressions)
|
|
187
|
-
# return ((Math.pow((y / m), l) - 1) / (s * l));
|
|
188
|
-
return f"cht:extension-lib('{ref_expressions[0][1:-1]}.js',{self.clean_coalesce(ref_expressions[1])} ,{self.clean_coalesce(ref_expressions[2])} ,{self.clean_coalesce(ref_expressions[3])})"
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
def tricc_operation_izscore(self, ref_expressions):
|
|
192
|
-
z, ll, m, s = self.get_zscore_params(ref_expressions)
|
|
193
|
-
# return (m * (z*s*l-1)^(1/l));
|
|
194
|
-
return f"cht:extension-lib('{ref_expressions[0][1:-1]}.js',{self.clean_coalesce(ref_expressions[1])} ,{self.clean_coalesce(ref_expressions[2])} ,{self.clean_coalesce(ref_expressions[3])}, true)"
|
|
195
|
-
|
|
196
|
-
def tricc_operation_drug_dosage(self, ref_expressions):
|
|
197
|
-
# drug name
|
|
198
|
-
# age
|
|
199
|
-
#weight
|
|
200
|
-
return f"cht:extension-lib('drugs.js',{','.join(map(self.clean_coalesce, ref_expressions))})"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|