janus-llm 4.2.0__py3-none-any.whl → 4.3.5__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. janus/__init__.py +1 -1
  2. janus/__main__.py +1 -1
  3. janus/_tests/evaluator_tests/EvalReadMe.md +85 -0
  4. janus/_tests/evaluator_tests/incose_tests/incose_large_test.json +39 -0
  5. janus/_tests/evaluator_tests/incose_tests/incose_small_test.json +17 -0
  6. janus/_tests/evaluator_tests/inline_comment_tests/mumps_inline_comment_test.m +71 -0
  7. janus/_tests/test_cli.py +3 -2
  8. janus/cli/aggregate.py +135 -0
  9. janus/cli/cli.py +111 -0
  10. janus/cli/constants.py +43 -0
  11. janus/cli/database.py +289 -0
  12. janus/cli/diagram.py +178 -0
  13. janus/cli/document.py +174 -0
  14. janus/cli/embedding.py +122 -0
  15. janus/cli/llm.py +187 -0
  16. janus/cli/partition.py +125 -0
  17. janus/cli/self_eval.py +149 -0
  18. janus/cli/translate.py +183 -0
  19. janus/converter/__init__.py +1 -1
  20. janus/converter/_tests/test_translate.py +2 -0
  21. janus/converter/converter.py +129 -92
  22. janus/converter/document.py +21 -14
  23. janus/converter/evaluate.py +237 -4
  24. janus/converter/translate.py +3 -3
  25. janus/embedding/collections.py +1 -1
  26. janus/language/alc/_tests/alc.asm +3779 -0
  27. janus/language/alc/_tests/test_alc.py +1 -1
  28. janus/language/alc/alc.py +9 -4
  29. janus/language/binary/_tests/hello.bin +0 -0
  30. janus/language/block.py +47 -12
  31. janus/language/file.py +1 -1
  32. janus/language/mumps/_tests/mumps.m +235 -0
  33. janus/language/splitter.py +31 -23
  34. janus/language/treesitter/_tests/languages/fortran.f90 +416 -0
  35. janus/language/treesitter/_tests/languages/ibmhlasm.asm +16 -0
  36. janus/language/treesitter/_tests/languages/matlab.m +225 -0
  37. janus/language/treesitter/treesitter.py +9 -1
  38. janus/llm/models_info.py +26 -13
  39. janus/metrics/_tests/asm_test_file.asm +10 -0
  40. janus/metrics/_tests/mumps_test_file.m +6 -0
  41. janus/metrics/_tests/test_treesitter_metrics.py +1 -1
  42. janus/metrics/prompts/clarity.txt +8 -0
  43. janus/metrics/prompts/completeness.txt +16 -0
  44. janus/metrics/prompts/faithfulness.txt +10 -0
  45. janus/metrics/prompts/hallucination.txt +16 -0
  46. janus/metrics/prompts/quality.txt +8 -0
  47. janus/metrics/prompts/readability.txt +16 -0
  48. janus/metrics/prompts/usefulness.txt +16 -0
  49. janus/parsers/code_parser.py +4 -4
  50. janus/parsers/doc_parser.py +12 -9
  51. janus/parsers/eval_parsers/incose_parser.py +134 -0
  52. janus/parsers/eval_parsers/inline_comment_parser.py +112 -0
  53. janus/parsers/parser.py +7 -0
  54. janus/parsers/partition_parser.py +47 -13
  55. janus/parsers/reqs_parser.py +8 -5
  56. janus/parsers/uml.py +5 -4
  57. janus/prompts/prompt.py +2 -2
  58. janus/prompts/templates/README.md +30 -0
  59. janus/prompts/templates/basic_aggregation/human.txt +6 -0
  60. janus/prompts/templates/basic_aggregation/system.txt +1 -0
  61. janus/prompts/templates/basic_refinement/human.txt +14 -0
  62. janus/prompts/templates/basic_refinement/system.txt +1 -0
  63. janus/prompts/templates/diagram/human.txt +9 -0
  64. janus/prompts/templates/diagram/system.txt +1 -0
  65. janus/prompts/templates/diagram_with_documentation/human.txt +15 -0
  66. janus/prompts/templates/diagram_with_documentation/system.txt +1 -0
  67. janus/prompts/templates/document/human.txt +10 -0
  68. janus/prompts/templates/document/system.txt +1 -0
  69. janus/prompts/templates/document_cloze/human.txt +11 -0
  70. janus/prompts/templates/document_cloze/system.txt +1 -0
  71. janus/prompts/templates/document_cloze/variables.json +4 -0
  72. janus/prompts/templates/document_cloze/variables_asm.json +4 -0
  73. janus/prompts/templates/document_inline/human.txt +13 -0
  74. janus/prompts/templates/eval_prompts/incose/human.txt +32 -0
  75. janus/prompts/templates/eval_prompts/incose/system.txt +1 -0
  76. janus/prompts/templates/eval_prompts/incose/variables.json +3 -0
  77. janus/prompts/templates/eval_prompts/inline_comments/human.txt +49 -0
  78. janus/prompts/templates/eval_prompts/inline_comments/system.txt +1 -0
  79. janus/prompts/templates/eval_prompts/inline_comments/variables.json +3 -0
  80. janus/prompts/templates/micromanaged_mumps_v1.0/human.txt +23 -0
  81. janus/prompts/templates/micromanaged_mumps_v1.0/system.txt +3 -0
  82. janus/prompts/templates/micromanaged_mumps_v2.0/human.txt +28 -0
  83. janus/prompts/templates/micromanaged_mumps_v2.0/system.txt +3 -0
  84. janus/prompts/templates/micromanaged_mumps_v2.1/human.txt +29 -0
  85. janus/prompts/templates/micromanaged_mumps_v2.1/system.txt +3 -0
  86. janus/prompts/templates/multidocument/human.txt +15 -0
  87. janus/prompts/templates/multidocument/system.txt +1 -0
  88. janus/prompts/templates/partition/human.txt +22 -0
  89. janus/prompts/templates/partition/system.txt +1 -0
  90. janus/prompts/templates/partition/variables.json +4 -0
  91. janus/prompts/templates/pseudocode/human.txt +7 -0
  92. janus/prompts/templates/pseudocode/system.txt +7 -0
  93. janus/prompts/templates/refinement/fix_exceptions/human.txt +19 -0
  94. janus/prompts/templates/refinement/fix_exceptions/system.txt +1 -0
  95. janus/prompts/templates/refinement/format/code_format/human.txt +12 -0
  96. janus/prompts/templates/refinement/format/code_format/system.txt +1 -0
  97. janus/prompts/templates/refinement/format/requirements_format/human.txt +14 -0
  98. janus/prompts/templates/refinement/format/requirements_format/system.txt +1 -0
  99. janus/prompts/templates/refinement/hallucination/human.txt +13 -0
  100. janus/prompts/templates/refinement/hallucination/system.txt +1 -0
  101. janus/prompts/templates/refinement/reflection/human.txt +15 -0
  102. janus/prompts/templates/refinement/reflection/incose/human.txt +26 -0
  103. janus/prompts/templates/refinement/reflection/incose/system.txt +1 -0
  104. janus/prompts/templates/refinement/reflection/incose_deduplicate/human.txt +16 -0
  105. janus/prompts/templates/refinement/reflection/incose_deduplicate/system.txt +1 -0
  106. janus/prompts/templates/refinement/reflection/system.txt +1 -0
  107. janus/prompts/templates/refinement/revision/human.txt +16 -0
  108. janus/prompts/templates/refinement/revision/incose/human.txt +16 -0
  109. janus/prompts/templates/refinement/revision/incose/system.txt +1 -0
  110. janus/prompts/templates/refinement/revision/incose_deduplicate/human.txt +17 -0
  111. janus/prompts/templates/refinement/revision/incose_deduplicate/system.txt +1 -0
  112. janus/prompts/templates/refinement/revision/system.txt +1 -0
  113. janus/prompts/templates/refinement/uml/alc_fix_variables/human.txt +15 -0
  114. janus/prompts/templates/refinement/uml/alc_fix_variables/system.txt +2 -0
  115. janus/prompts/templates/refinement/uml/fix_connections/human.txt +15 -0
  116. janus/prompts/templates/refinement/uml/fix_connections/system.txt +2 -0
  117. janus/prompts/templates/requirements/human.txt +13 -0
  118. janus/prompts/templates/requirements/system.txt +2 -0
  119. janus/prompts/templates/retrieval/language_docs/human.txt +10 -0
  120. janus/prompts/templates/retrieval/language_docs/system.txt +1 -0
  121. janus/prompts/templates/simple/human.txt +16 -0
  122. janus/prompts/templates/simple/system.txt +3 -0
  123. janus/refiners/format.py +49 -0
  124. janus/refiners/refiner.py +143 -4
  125. janus/utils/enums.py +140 -111
  126. janus/utils/logger.py +2 -0
  127. {janus_llm-4.2.0.dist-info → janus_llm-4.3.5.dist-info}/METADATA +7 -7
  128. janus_llm-4.3.5.dist-info/RECORD +210 -0
  129. {janus_llm-4.2.0.dist-info → janus_llm-4.3.5.dist-info}/WHEEL +1 -1
  130. janus_llm-4.3.5.dist-info/entry_points.txt +3 -0
  131. janus/cli.py +0 -1343
  132. janus_llm-4.2.0.dist-info/RECORD +0 -113
  133. janus_llm-4.2.0.dist-info/entry_points.txt +0 -3
  134. {janus_llm-4.2.0.dist-info → janus_llm-4.3.5.dist-info}/LICENSE +0 -0
@@ -20,7 +20,7 @@ class TestAlcSplitter(unittest.TestCase):
20
20
  def test_split(self):
21
21
  """Test the split method."""
22
22
  tree_root = self.splitter.split(self.test_file)
23
- self.assertAlmostEqual(tree_root.n_descendents, 32, delta=5)
23
+ self.assertAlmostEqual(tree_root.n_descendents, 16, delta=2)
24
24
  self.assertLessEqual(tree_root.max_tokens, self.splitter.max_tokens)
25
25
  self.assertFalse(tree_root.complete)
26
26
  self.combiner.combine_children(tree_root)
janus/language/alc/alc.py CHANGED
@@ -79,10 +79,15 @@ class AlcSplitter(TreeSitterSplitter):
79
79
  if len(sects) > 1:
80
80
  block.children = []
81
81
  for sect in sects:
82
- if sect[0].node_type in sect_types:
83
- sect_node = self.merge_nodes(sect)
84
- sect_node.children = sect
85
- sect_node.node_type = NodeType(str(sect[0].node_type)[:5])
82
+ node_type = sect[0].node_type
83
+ if node_type in sect_types:
84
+ if len(sect) == 1:
85
+ # Don't make a node its own child
86
+ sect_node = sect[0]
87
+ else:
88
+ sect_node = self.merge_nodes(sect)
89
+ sect_node.children = sect
90
+ sect_node.node_type = NodeType(str(node_type)[:5])
86
91
  block.children.append(sect_node)
87
92
  else:
88
93
  block.children.extend(sect)
Binary file
janus/language/block.py CHANGED
@@ -181,7 +181,6 @@ class TranslatedCodeBlock(CodeBlock):
181
181
  Attributes:
182
182
  original: The original code block.
183
183
  cost: The total cost to translate the original code block.
184
- retries: The number of times translation had to be retried for this code
185
184
  translated: Whether this block has been successfully translated
186
185
  """
187
186
 
@@ -217,9 +216,13 @@ class TranslatedCodeBlock(CodeBlock):
217
216
  self.complete = original.complete
218
217
  self.translated = False
219
218
  self.cost = 0.0
220
- self.retries = 0
219
+ self.num_requests = 0
220
+ self.tokens = 0
221
221
  self.processing_time = 0.0
222
222
 
223
+ self.request_input_tokens = 0
224
+ self.request_output_tokens = 0
225
+
223
226
  @property
224
227
  def total_cost(self) -> float:
225
228
  """The total cost spent translating this block and all its descendents
@@ -229,16 +232,6 @@ class TranslatedCodeBlock(CodeBlock):
229
232
  """
230
233
  return self.cost + sum(c.total_cost for c in self.children)
231
234
 
232
- @property
233
- def total_retries(self) -> int:
234
- """The total number of retries that were required to translate this block and
235
- all its descendents
236
-
237
- Returns:
238
- The total number of retries that were required to translate this block and
239
- """
240
- return self.retries + sum(c.total_retries for c in self.children)
241
-
242
235
  @property
243
236
  def total_input_tokens(self) -> int:
244
237
  """The total number of input tokens represented by this block and all its
@@ -250,6 +243,48 @@ class TranslatedCodeBlock(CodeBlock):
250
243
  children_sum = sum(c.total_input_tokens for c in self.children)
251
244
  return children_sum + (self.original.tokens if self.translated else 0)
252
245
 
246
+ @property
247
+ def total_request_input_tokens(self) -> int:
248
+ """
249
+ The total number of tokens sent to LLM during all requests during translation
250
+
251
+ Returns:
252
+ The total number of tokens sent to LLM during all requests during translation
253
+ """
254
+ children_sum = sum(c.total_request_input_tokens for c in self.children)
255
+ return children_sum + self.request_input_tokens
256
+
257
+ @property
258
+ def total_request_output_tokens(self) -> int:
259
+ """
260
+ The total number of tokens output by an LLM during translation
261
+
262
+ Returns:
263
+ The total number of tokens output by an LLM during translation
264
+ """
265
+ children_sum = sum(c.total_request_output_tokens for c in self.children)
266
+ return children_sum + self.request_output_tokens
267
+
268
+ @property
269
+ def total_num_requests(self) -> int:
270
+ """
271
+ Total number of requests made to LLM during translation
272
+
273
+ Returns:
274
+ Total number of requests made to LLM during translation
275
+ """
276
+ children_sum = sum(c.total_num_requests for c in self.children)
277
+ return children_sum + self.num_requests
278
+
279
+ @property
280
+ def translation_completed(self) -> bool:
281
+ """Whether or not the code block was successfully translated
282
+
283
+ Returns:
284
+ Whether or not the code block was successfully translated
285
+ """
286
+ return self.translated and all(c.translation_completed for c in self.children)
287
+
253
288
  @property
254
289
  def translation_completeness(self) -> float:
255
290
  """The share of the input that was successfully translated
janus/language/file.py CHANGED
@@ -15,4 +15,4 @@ class FileManager:
15
15
  """
16
16
  self.language: str = language
17
17
  self.comment: str = LANGUAGES[self.language]["comment"]
18
- self.suffix: str = LANGUAGES[self.language]["suffix"]
18
+ self.suffixes: list[str] = LANGUAGES[self.language]["suffixes"]
@@ -0,0 +1,235 @@
1
+ PSXRPPL ;BIR/WPB,BAB-Gathers data for the CMOP Transmission ;13 Mar 2002 10:31 AM
2
+ ;;2.0;CMOP;**3,23,33,28,40,42,41,48,62,58,66,65,69,70,81,83,87,91**;11 Apr 97;Build 33
3
+ ;Reference to ^PS(52.5, supported by DBIA #1978
4
+ ;Reference to ^PSRX( supported by DBIA #1977
5
+ ;Reference to ^PSOHLSN1 supported by DBIA #2385
6
+ ;Reference to ^PSORXL supported by DBIA #1969
7
+ ;Reference to ^PSOLSET supported by DBIA #1973
8
+ ;Reference to %ZIS(1 supported by DBIA #290
9
+ ;Reference to %ZIS(2 supported by DBIA #2247
10
+ ;Reference to ^PSSLOCK supported by DBIA #2789
11
+ ;Reference to ^XTMP("ORLK-" supported by DBIA #4001
12
+ ;Reference to ^BPSUTIL supported by DBIA #4410
13
+ ;Reference to ^PS(59 supported by DBIA #1976
14
+ ;Reference to $$SELPRT^PSOFDAUT supported by DBIA #5740
15
+ ;Reference to LOG^BPSOSL supported by ICR# 6764
16
+ ;Reference to IEN59^BPSOSRX supported by ICR# 4412
17
+ ;
18
+ ;Called from PSXRSUS -Builds ^PSX(550.2,,15,"C" , and returns to PSXRSUS or PSXRTRAN
19
+ ;
20
+ SDT ;
21
+ K ^TMP($J,"PSX"),^TMP($J,"PSXDFN"),^TMP("PSXEPHNB",$J)
22
+ K PSXBAT,ZCNT
23
+ I $D(XRTL) D T0^%ZOSV
24
+ S PSXTDIV=PSOSITE,PSXTYP=$S(+$G(PSXCS):"C",1:"N")
25
+ ;
26
+ ; $$SBTECME^PSXRPPL1 goes through the suspense queue for either CS
27
+ ; or non-CS prescriptions (according to PSXTYP), up to and including
28
+ ; the through date (PRTDT). For each Rx, it will send a claim if
29
+ ; the patient has insurance.
30
+ ;
31
+ I $$ECMEON^BPSUTIL(PSXTDIV),$$CMOPON^BPSUTIL(PSXTDIV) D
32
+ . N BPSCNT S BPSCNT=$$SBTECME^PSXRPPL1(PSXTYP,PSXTDIV,PRTDT,PSXDTRG)
33
+ . ; - Wait 15 seconds per prescription sent to ECME (max of 2 hours)
34
+ . I BPSCNT>0 H 60+$S((BPSCNT*15)>7200:7200,1:(BPSCNT*15))
35
+ ;
36
+ ; After many additional checks, GETDATA^PSXRPPL will eventually add
37
+ ; each prescription to this batch (see RS550215, below). Later in
38
+ ; the process, either they will be sent to CMOP (EN^PSXRTR) or
39
+ ; labels will be printed (PRT^PSXRPPL).
40
+ ;
41
+ K ^TMP("PSXEPHIN",$J)
42
+ S SDT=0
43
+ F S SDT=$O(^PS(52.5,"CMP","Q",PSXTYP,PSXTDIV,SDT)),XDFN=0 Q:(SDT>PRTDT)!(SDT'>0) D
44
+ . F S XDFN=$O(^PS(52.5,"CMP","Q",PSXTYP,PSXTDIV,SDT,XDFN)),REC=0 Q:(XDFN'>0)!(XDFN="") D
45
+ . . F S REC=$O(^PS(52.5,"CMP","Q",PSXTYP,PSXTDIV,SDT,XDFN,REC)) Q:(REC'>0)!(REC="") D
46
+ . . . D GETDATA D:$G(RXN) PSOUL^PSSLOCK(RXN),OERRLOCK(RXN)
47
+ ;
48
+ ; After making a first pass through the suspense queue (SBTECME^
49
+ ; PSXRPPL1), it will now make a second pass (CHKDFN^PSXRPPL2) to look
50
+ ; for additional Rxs for patients who already have an Rx in the batch.
51
+ ; CHKDFN^PSXRPPL2 makes a pass and sends claims when appropriate, and
52
+ ; CHKDFN^PSXRPPL makes the same pass and calls GETDATA, which condi-
53
+ ; tionally adds each Rx to the batch.
54
+ ;
55
+ I $G(PSXBAT),'$G(PSXRTRAN) D CHKDFN^PSXRPPL2(PRTDT)
56
+ I $G(PSXBAT),'$G(PSXRTRAN) D CHKDFN
57
+ ;
58
+ ; - Sends a Mailman message if there were transmission problems with the 3rd Party Payer
59
+ I $D(^TMP("PSXEPHIN",$J)) D ^PSXBPSMS K ^TMP("PSXEPHIN",$J),^TMP("PSXEPHNB",$J)
60
+ ;
61
+ EXIT ;
62
+ K SDT,DFN,REC,RXNUM,PSXOK,FILNUM,REF,PNAME,CNAME,DIE,DR,%,CNT,COM,DTTM,FILL,JJ,PRTDT,PSXDIV,XDFN,NFLAG,CIND
63
+ K CHKDT,DAYS,DRUG,DRUGCHK,NM,OPDT,PHARCLK,PHY,PSTAT,PTRA,PTRB,QTY,REL,RXERR,RXF,SFN,PSXDGST,PSXMC,PSXMDT
64
+ S:$D(XRT0) XRTN=$T(+0) D:$D(XRT0) T1^%ZOSV
65
+ K ^TMP("PSXEPHIN",$J),^TMP("PSXEPHNB",$J)
66
+ Q
67
+ ;
68
+ GETDATA ;Screens rxs and builds data
69
+ ;PSXOK=1:NOT CMOP DRUG OR DO NOT MAIL,2:TRADENAME,3:WINDOW,4:PRINTED,5:NOT SUSPENDED
70
+ ;PSXOK=6:ALREADY RELEASED,7:DIFFERENT DIVISION,8:BAD DATA IN 52.5
71
+ ;9:CS Mismatch,10:DEA 1 or 2
72
+ I '$D(^PS(52.5,REC,0)) K ^PS(52.5,"AQ",SDT,XDFN,REC),^PS(52.5,"CMP","Q",PSXTYP,PSXTDIV,SDT,XDFN,REC) Q
73
+ I $P(^PS(52.5,REC,0),"^",7)="" K ^PS(52.5,"AQ",SDT,XDFN,REC),^PS(52.5,"CMP","Q",PSXTYP,PSXTDIV,SDT,XDFN,REC) Q
74
+ I ($P(^PS(52.5,REC,0),"^",3)'=XDFN) K ^PS(52.5,"AQ",SDT,XDFN,REC),^PS(52.5,"CMP","Q",PSXTYP,PSXTDIV,SDT,XDFN,REC) Q
75
+ N DFN S DFN=XDFN D DEM^VADPT
76
+ I $G(VADM(6))'="" D DELETE K VADM Q
77
+ S PSXOK=0,NFLAG=0
78
+ S RXN=$P($G(^PS(52.5,REC,0)),"^",1) I RXN="" S PSXOK=8 Q
79
+ S RFL=+$$GET1^DIQ(52.5,REC,9,"I")
80
+ I '$D(^TMP($J,"PSXBAI",DFN)) D
81
+ .S PSXGOOD=$$ADDROK^PSXMISC1(RXN)
82
+ .I 'PSXGOOD S PSXFIRST=1 D I 'PSXFIRST S PSXOK=8
83
+ ..D CHKACT^PSXMISC1(RXN)
84
+ I PSXOK=8 K RXN Q
85
+ ;
86
+ N EPHQT
87
+ S EPHQT=0
88
+ I $$PATCH^XPDUTL("PSO*7.0*148"),'$$TRICVANB^PSXRPPL1(RXN,RFL) D EPHARM^PSXRPPL2
89
+ D LOG^BPSOSL($$IEN59^BPSOSRX(RXN,RFL),$T(+0)_"-GETDATA, EPHQT="_EPHQT) ; ICR #4412,6764
90
+ I EPHQT Q
91
+ ;
92
+ D CHKDATA^PSXMISC1
93
+ ;
94
+ SET Q:(PSXOK=7)!(PSXOK=8)!(PSXOK=9)
95
+ S PNAME=$G(VADM(1))
96
+ I ($G(PSXCSRX)=1)&($G(PSXCS)=1) S ^XTMP("PSXCS",PSOSITE,DT,RXN)=""
97
+ I (PSXOK=0)&(PSXFLAG=1) S ^TMP($J,"PSXDFN",XDFN)="",NFLAG=4 D DQUE,RX550215 Q
98
+ I (PSXOK=0)&(PSXFLAG=2) D RX550215 Q
99
+ I (PSXOK>0)&(PSXOK<7)!(PSXOK=10) D DELETE Q
100
+ Q
101
+ ;
102
+ DELETE ; deletes the CMOP STATUS field in PS(52.5, reindex 'AC' x-ref
103
+ L +^PS(52.5,REC):600 Q:'$T
104
+ N DR,DIE,DA S DIE="^PS(52.5,",DA=REC,DR="3///@" D ^DIE
105
+ S ^PS(52.5,"AC",$P(^PS(52.5,REC,0),"^",3),$P(^PS(52.5,REC,0),"^",2),REC)=""
106
+ L -^PS(52.5,REC)
107
+ Q
108
+ ;
109
+ CHKDFN ;
110
+ I '$D(^PSX(550.2,PSXBAT,15,"C")) Q
111
+ S PSXPTNM=""
112
+ F S PSXPTNM=$O(^PSX(550.2,PSXBAT,15,"C",PSXPTNM)) Q:PSXPTNM="" D
113
+ . S XDFN=0
114
+ . F S XDFN=$O(^PSX(550.2,PSXBAT,"15","C",PSXPTNM,XDFN)) Q:(XDFN'>0) D
115
+ . . S SDT=PRTDT
116
+ . . F S SDT=$O(^PS(52.5,"CMP","Q",PSXTYP,PSXTDIV,SDT)) Q:(SDT>PSXDTRG)!(SDT="") D
117
+ . . . S REC=0
118
+ . . . F S REC=$O(^PS(52.5,"CMP","Q",PSXTYP,PSXTDIV,SDT,XDFN,REC)) Q:REC'>0 D
119
+ . . . . D GETDATA D:$G(RXN) PSOUL^PSSLOCK(RXN),OERRLOCK(RXN)
120
+ Q
121
+ ;
122
+ BEGIN ; Select print device
123
+ I '$D(PSOPAR) D ^PSOLSET
124
+ I $D(PSOLAP),($G(PSOLAP)'=ION) S PSLION=PSOLAP G PROFILE
125
+ W ! S %ZIS("A")="PRINTER 'LABEL' DEVICE: ",%ZIS("B")="",%ZIS="MQN" D ^%ZIS S PSLION=ION G:POP EXIT
126
+ I $G(IOST)["C-" W !,"You must select a printer!",! G BEGIN
127
+ F J=0,1 S @("PSOBAR"_J)="" I $D(^%ZIS(2,^%ZIS(1,IOS,"SUBTYPE"),"BAR"_J)) S @("PSOBAR"_J)=^("BAR"_J)
128
+ S PSOBARS=PSOBAR1]""&(PSOBAR0]"")&$P(PSOPAR,"^",19)
129
+ K PSOION,J D ^%ZISC I $D(IO("Q")) K IO("Q")
130
+ ;
131
+ PROFILE I $D(PSOPROP),($G(PSOPROP)'=ION) G FDAMG
132
+ I $P(PSOPAR,"^",8) S %ZIS="MNQ",%ZIS("A")="Select PROFILE PRINTER: " D ^%ZIS K %ZIS,IO("Q"),IOP G:POP EXIT S PSOPROP=ION D ^%ZISC
133
+ I $G(PSOPROP)=ION W !,"You must select a printer!",! G PROFILE
134
+ ;
135
+ FDAMG ; Selects FDA Medication Guide Printer
136
+ I $$GET1^DIQ(59,PSOSITE,134)'="" N FDAPRT S FDAPRT="" D I FDAPRT="^"!($G(PSOFDAPT)="") S POP=1 G EXIT
137
+ . F D Q:FDAPRT'=""
138
+ . . S FDAPRT=$$SELPRT^PSOFDAUT($P($G(PSOFDAPT),"^"))
139
+ . . I FDAPRT="" W $C(7),!,"You must select a valid FDA Medication Guide printer."
140
+ . I FDAPRT'="",(FDAPRT'="^") S PSOFDAPT=FDAPRT
141
+ Q
142
+ ;
143
+ PRT ; Print labels.
144
+ D NOW^%DTC S DTTM=% K %
145
+ S NM="" F S NM=$O(^PSX(550.2,PSXBAT,15,"C",NM)) Q:NM="" D DFN,PPL ;gather patient RXs, print patient RXs
146
+ S DIK="^PSX(550.2,",DA=PSXBAT D ^DIK K PSXBAT
147
+ K CHKDT,CIND,DAYS,DRUG,DRUGCHK,NFLAG,NM,ORD,PDT,PHARCLK,PHY,PSTAT,PTRA,PTRB,QTY,REL,RXERR,RXF,SFN,SIG,SITE,SUS,SUSPT
148
+ Q
149
+ ;
150
+ DFN S DFN=0,NFLAG=2
151
+ F S DFN=$O(^PSX(550.2,PSXBAT,15,"C",NM,DFN)),RXN=0 Q:(DFN="")!(DFN'>0) D
152
+ .F S RXN=$O(^PSX(550.2,PSXBAT,15,"C",NM,DFN,RXN)),RXF="" Q:(RXN="")!(RXN'>0) D
153
+ ..F S RXF=$O(^PSX(550.2,PSXBAT,15,"C",NM,DFN,RXN,RXF)) Q:RXF="" D BLD
154
+ Q
155
+ ;
156
+ BLD ;
157
+ S BATRXDA=$O(^PSX(550.2,PSXBAT,15,"B",RXN,0)) D NOW^%DTC S DTTM=%
158
+ S REC=$P(^PSX(550.2,PSXBAT,15,BATRXDA,0),U,5),SUS=$O(^PS(52.5,"B",RXN,0))
159
+ I SUS=REC,+SUS'=0 I 1 ;rx still valid in suspense
160
+ E D Q ;rx gone
161
+ . N DA,DIK S DIK=550.2,DA(1)=PSXBAT,DA=BATRXDA
162
+ . D ^DIK
163
+ S PSOSU(DFN,SUS)=RXN,RXCNTR=$G(RXCNTR)+1,NFLAG=2
164
+ S $P(^PSRX(RXN,0),U,15)=0,$P(^PSRX(RXN,"STA"),U,1)=0
165
+ K % S COM="CMOP Suspense Label "_$S($G(^PS(52.5,SUS,"P"))=0:"Printed",$G(^PS(52.5,SUS,"P"))="":"Printed",1:"Reprinted")_$S($G(^PSRX(RXN,"TYPE"))>0:" (PARTIAL)",1:"")
166
+ D EN^PSOHLSN1(RXN,"SC","ZU",COM)
167
+ S DA=SUS D DQUE K DA
168
+ ACTLOG F JJ=0:0 S JJ=$O(^PSRX(RXN,"A",JJ)) Q:'JJ S CNT=JJ
169
+ S RFCNT=0 F RF=0:0 S RF=$O(^PSRX(RXN,1,RF)) Q:'RF S RFCNT=$S(RF<6:RF,1:RF+1)
170
+ S CNT=CNT+1,^PSRX(RXN,"A",0)="^52.3DA^"_CNT_"^"_CNT
171
+ LOCK L +^PSRX(RXN):600 G:'$T LOCK
172
+ S ^PSRX(RXN,"A",CNT,0)=DTTM_"^S^"_DUZ_"^"_RFCNT_"^"_COM L -^PSRX(RXN)
173
+ K CNT,COM,RFCNT,%,JJ,RF,Y,RXCNTR
174
+ Q
175
+ ;
176
+ PPL K PPL,PPL1 S ORD="" F S ORD=$O(PSOSU(ORD)) Q:(ORD="")!(ORD'>0) D PPL1
177
+ Q
178
+ ;
179
+ PPL1 ; print patient labels
180
+ F SFN=0:0 S SFN=$O(PSOSU(ORD,SFN)) Q:'SFN D
181
+ . S:$L($G(PPL))<240 PPL=$P(PSOSU(ORD,SFN),"^")_","_$G(PPL)
182
+ . S:$L($G(PPL))>239 PPL1=$P(PSOSU(ORD,SFN),"^")_","_$G(PPL1)
183
+ . S DFN=$P(^PS(52.5,SFN,0),"^",3)
184
+ S SUSPT=1,PSNP=$S($P(PSOPAR,"^",8):1,1:0) S:$D(PSOPROP) PFIO=PSOPROP
185
+ D QLBL^PSORXL
186
+ I $D(PPL1) S PSNP=0,PPL=PPL1 D QLBL^PSORXL
187
+ K PPL,PPL1,PSOSU(ORD)
188
+ Q
189
+ ;
190
+ DQUE ; sets the CMOP indicator field, and printed field in 52.5
191
+ L +^PS(52.5,REC):600 G:'$T DQUE
192
+ I NFLAG=4 D
193
+ . S DA=REC,DIE="^PS(52.5,",DR="3////L;4////"_DT D ^DIE K DIE,DA,DR L -^PS(52.5,REC) ; the rest moved into PSXRTR
194
+ S CIND=$S(NFLAG=1:"X",NFLAG=2:"P",NFLAG=3:"@",1:0)
195
+ I $G(NFLAG)'=2 D
196
+ .S DA=REC,DIE="^PS(52.5,",DR="3////"_CIND_";4////"_DT
197
+ .D ^DIE K DIE,DA,DR
198
+ .S ^PS(52.5,REC,"P")=1,^PS(52.5,"ADL",DT,REC)=""
199
+ I $G(NFLAG)=2 D ;print label cycle
200
+ . S DA=REC,DIE="^PS(52.5,",DR="3////"_CIND_";4////"_DTTM_";5////"_DUZ_";7////"_RXCNTR
201
+ . D ^DIE K DIE,DA,DR
202
+ . S ^PS(52.5,REC,"P")=1,^PS(52.5,"ADL",$E($P(^PS(52.5,REC,0),"^",8),1,7),REC)=""
203
+ L -^PS(52.5,REC)
204
+ I $G(NFLAG)=2 D EN^PSOHLSN1(RXN,"SC","ZU","CMOP Suspense Label Printed")
205
+ Q
206
+ ;
207
+ RX550215 ; put RX into RX multiple TRANS 550.215 for PSXBAT
208
+ I '$G(PSXBAT) D BATCH^PSXRSYU ; first time through create batch, & return PSXBAT
209
+ K DD,DO,DIC,DA,DR,D0
210
+ S:'$D(^PSX(550.2,PSXBAT,15,0)) ^PSX(550.2,PSXBAT,15,0)="^550.215P^^"
211
+ S X=RXN,DA(1)=PSXBAT
212
+ S DIC="^PSX(550.2,"_PSXBAT_",15,",DIC("DR")=".02////^S X=RXF;.03////^S X=DFN;.05////^S X=REC",DIC(0)="ZF"
213
+ D FILE^DICN
214
+ S PSXRXTDA=+Y ;RX DA within PSXBAT 'T'ransmission
215
+ K DD,DO,DIC,DA,DR,D0
216
+ Q
217
+ ;
218
+ OERRLOCK(RXN) ; set XTMP for OERR/CPRS order locking
219
+ I $G(PSXBAT),$G(RXN),$G(PSXRXTDA) I 1
220
+ E Q
221
+ I $P(^PSX(550.2,PSXBAT,15,PSXRXTDA,0),U,1)'=RXN Q
222
+ RXNSET ; set ^XTMP("ORLK-"_ORDER per IA 4001 needs RXN
223
+ Q:'$G(RXN)
224
+ N ORD,NOW,NOW1 S ORD=+$P($G(^PSRX(+$G(RXN),"OR1")),"^",2)
225
+ Q:'ORD
226
+ S NOW=$$NOW^XLFDT,NOW1=$$FMADD^XLFDT(NOW,1)
227
+ S ^XTMP("ORLK-"_+ORD,0)=NOW1_U_NOW_"^CPRS/CMOP RX/Order Lock",^(1)=DUZ_U_$J
228
+ Q
229
+ ;
230
+ RXNCLEAR ; needs RXN
231
+ Q:'$G(RXN)
232
+ N ORD S ORD=+$P($G(^PSRX(+$G(RXN),"OR1")),"^",2) Q:'ORD
233
+ I $D(^XTMP("ORLK-"_ORD,0)),^(0)["CPRS/CMOP" K ^XTMP("ORLK-"_ORD)
234
+ Q
235
+ ;
@@ -275,42 +275,50 @@ class Splitter(FileManager):
275
275
 
276
276
  groups = [[n] for n in nodes]
277
277
  while len(groups) > 1 and min(adj_sums) <= self.max_tokens and any(merge_allowed):
278
- # Get the indices of the adjacent nodes that would result in the
279
- # smallest possible merged snippet. Ignore protected nodes.
278
+ # Get the index of the node that would result in the smallest
279
+ # merged snippet when merged with the node that follows it.
280
+ # Ignore protected nodes.
280
281
  mergeable_indices = compress(range(len(adj_sums)), merge_allowed)
281
- i0 = int(min(mergeable_indices, key=adj_sums.__getitem__))
282
- i1 = i0 + 1
282
+ C = int(min(mergeable_indices, key=adj_sums.__getitem__))
283
+
284
+ # C: Central index
285
+ # L: Index to the left
286
+ # R: Index to the right (to be merged in to C)
287
+ # N: Next index (to the right of R, the "new R")
288
+ L, R, N = C - 1, C + 1, C + 2
283
289
 
284
290
  # Recalculate the length. We can't simply use the adj_sum, because
285
291
  # it is an underestimate due to the adjoining suffix/prefix.
286
- central_node = groups[i0][-1]
287
- merged_text = "".join([text_chunks[i0], central_node.suffix, text_chunks[i1]])
292
+ central_node = groups[C][-1]
293
+ merged_text = "".join([text_chunks[C], central_node.suffix, text_chunks[R]])
288
294
  merged_text_length = self._count_tokens(merged_text)
289
295
 
290
296
  # If the true length of the merged pair is too long, don't merge them
291
297
  # Instead, correct the estimate, since shorter pairs may yet exist
292
298
  if merged_text_length > self.max_tokens:
293
- adj_sums[i0] = merged_text_length
299
+ adj_sums[C] = merged_text_length
294
300
  continue
295
301
 
296
302
  # Update adjacent sum estimates
297
- if i0 > 0:
298
- adj_sums[i0 - 1] += merged_text_length
299
- if i1 < len(adj_sums) - 1:
300
- adj_sums[i1 + 1] += merged_text_length
301
-
302
- if i0 > 0 and i1 < len(merge_allowed) - 1:
303
- if not (merge_allowed[i0 - 1] and merge_allowed[i1 + 1]):
304
- merge_allowed[i0 - 1] = merge_allowed[i1 + 1] = False
303
+ if L >= 0:
304
+ adj_sums[L] = lengths[L] + merged_text_length
305
+ if N < len(adj_sums):
306
+ adj_sums[R] = lengths[N] + merged_text_length
305
307
 
306
308
  # The potential merge length for this pair is removed
307
- adj_sums.pop(i0)
308
- merge_allowed.pop(i0)
309
+ adj_sums.pop(C)
310
+
311
+ # The merged-in node is removed from the protected list
312
+ # The merge_allowed list need not be updated - if the node now to
313
+ # its right is protected, the merge_allowed element corresponding
314
+ # to the merged neighbor will have been True, and now corresponds
315
+ # to the merged node.
316
+ merge_allowed.pop(C)
309
317
 
310
318
  # Merge the pair of node groups
311
- groups[i0 : i1 + 1] = [groups[i0] + groups[i1]]
312
- text_chunks[i0 : i1 + 1] = [merged_text]
313
- lengths[i0 : i1 + 1] = [merged_text_length]
319
+ groups[C:N] = [groups[C] + groups[R]]
320
+ text_chunks[C:N] = [merged_text]
321
+ lengths[C:N] = [merged_text_length]
314
322
 
315
323
  return groups
316
324
 
@@ -403,13 +411,13 @@ class Splitter(FileManager):
403
411
  self._split_into_lines(node)
404
412
 
405
413
  def _split_into_lines(self, node: CodeBlock):
406
- split_text = re.split(r"(\n+)", node.text)
414
+ split_text = list(re.split(r"(\n+)", node.text))
407
415
 
408
416
  # If the string didn't start/end with newlines, make sure to include
409
417
  # empty strings for the prefix/suffixes
410
- if split_text[0].strip("\n"):
418
+ if not re.match(r"^\n+$", split_text[0]):
411
419
  split_text = [""] + split_text
412
- if split_text[-1].strip("\n"):
420
+ if not re.match(r"^\n+$", split_text[-1]):
413
421
  split_text.append("")
414
422
  betweens = split_text[::2]
415
423
  lines = split_text[1::2]