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.
Files changed (52) hide show
  1. {tricc_oo-1.4.19/tricc_oo.egg-info → tricc_oo-1.4.21}/PKG-INFO +1 -1
  2. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/pyproject.toml +1 -1
  3. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/drawio_type_map.py +2 -2
  4. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/tricc_to_xls_form.py +4 -4
  5. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/models/base.py +13 -6
  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
  7. tricc_oo-1.4.21/tricc_oo/strategies/output/xlsform_cht_hf.py +43 -0
  8. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/visitors/tricc.py +97 -76
  9. {tricc_oo-1.4.19 → tricc_oo-1.4.21/tricc_oo.egg-info}/PKG-INFO +2 -2
  10. tricc_oo-1.4.19/tricc_oo/strategies/output/xlsform_cht.py +0 -200
  11. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/README.md +0 -0
  12. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/setup.cfg +0 -0
  13. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tests/build.py +0 -0
  14. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tests/test_cql.py +0 -0
  15. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tests/to_ocl.py +0 -0
  16. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/__init__.py +0 -0
  17. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/__init__.py +0 -0
  18. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/codesystem_to_ocl.py +0 -0
  19. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/cql/cqlLexer.py +0 -0
  20. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/cql/cqlListener.py +0 -0
  21. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/cql/cqlParser.py +0 -0
  22. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/cql/cqlVisitor.py +0 -0
  23. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/cql_to_operation.py +0 -0
  24. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/datadictionnary.py +0 -0
  25. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/utils.py +0 -0
  26. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/converters/xml_to_tricc.py +0 -0
  27. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/models/__init__.py +0 -0
  28. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/models/calculate.py +0 -0
  29. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/models/lang.py +0 -0
  30. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/models/ocl.py +0 -0
  31. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/models/ordered_set.py +0 -0
  32. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/models/tricc.py +0 -0
  33. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/parsers/__init__.py +0 -0
  34. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/parsers/xml.py +0 -0
  35. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/serializers/__init__.py +0 -0
  36. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/serializers/planuml.py +0 -0
  37. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/serializers/xls_form.py +0 -0
  38. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/strategies/__init__.py +0 -0
  39. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/strategies/input/__init__.py +0 -0
  40. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/strategies/input/base_input_strategy.py +0 -0
  41. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/strategies/input/drawio.py +0 -0
  42. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/strategies/output/base_output_strategy.py +0 -0
  43. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/strategies/output/spice.py +0 -0
  44. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/strategies/output/xls_form.py +0 -0
  45. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/strategies/output/xlsform_cdss.py +0 -0
  46. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/visitors/__init__.py +0 -0
  47. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/visitors/utils.py +0 -0
  48. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo/visitors/xform_pd.py +0 -0
  49. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo.egg-info/SOURCES.txt +0 -0
  50. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo.egg-info/dependency_links.txt +0 -0
  51. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo.egg-info/requires.txt +0 -0
  52. {tricc_oo-1.4.19 → tricc_oo-1.4.21}/tricc_oo.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tricc-oo
3
- Version: 1.4.19
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tricc-oo"
7
- version = "1.4.19"
7
+ version = "1.4.21"
8
8
  description = "Python library that converts CDSS L2 in L3"
9
9
  readme = "README.md"
10
10
 
@@ -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 = result + "::" + name
248
+ result += name
242
249
  if label:
243
- result = result + "::" + (
250
+ result += "::" + (
244
251
  next(iter(self.label.values())) if isinstance(self.label, Dict) else self.label
245
252
  )
246
- if len(result) < 50:
253
+ if len(result) < 80:
247
254
  return result
248
255
  else:
249
- return result[:50]
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.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
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 XLSFormCHTHFStrategy(XLSFormCHTStrategy):
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)] = [ 'begin_group', 'group_summary' , 'Summary', '', '', '', 'field-list summary', '', '', '', '', '', '', '', '', '', '' ]
318
- #df_summary.loc[len(df_summary)] = [ 'note', 'r_patient_info', '**${patient_name}** ID: ${patient_id}', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ]
319
- #df_summary.loc[len(df_summary)] = [ 'note', 'r_followup', 'Follow Up <i class=“fa fa-flag”></i>', '', '', '', '', '', '','', '', '', '', '', '', '', '' ]
320
- #df_summary.loc[len(df_summary)] = [ 'note', 'r_followup_note' ,'FOLLOWUP instruction', '', '', '', '', '', '', '','', '', '', '', '', '', '' ]
321
- #df_summary.loc[len(df_summary)] = [ 'end_group', '' ,'', '', '', '', '', '', '', '', '', '', '', '', '','', '' ]
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 tricc_operation_age_day(self, exps):
325
- raise NotImplemented("AgeInDays Not compatible with this strategy")
326
-
327
- def tricc_operation_age_year(self, exps):
328
- raise NotImplemented("AgeInYears Not compatible with this strategy")
329
-
330
- def tricc_operation_age_month(self, exps):
331
- raise NotImplemented("AgeInMonths Not compatible with this strategy")
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
- node_name = node.name if not isinstance(node, TriccNodeEnd) else node.get_reference()
121
- last_version = get_last_version(node_name, processed_nodes) if issubclass(node.__class__, (TriccNodeDisplayModel, TriccNodeDisplayCalculateBase, TriccNodeEnd)) and not isinstance(node, TriccNodeSelectOption) else None
122
- #last_version = processed_nodes.find_prev(node, lambda item: hasattr(item, 'name') and item.name == node.name)
123
- if last_version and getattr(node, 'process', '') != 'pause':
124
- # 0-100 for manually specified instance. 100-200 for auto instance
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
- else:
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(path, str))} ")
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
- return get_all_dependant(looped, stashed_nodes, processed_nodes, depth+1, waited , looped, path=cur_path)
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.3
1
+ Metadata-Version: 2.4
2
2
  Name: tricc-oo
3
- Version: 1.4.19
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