medicafe 0.250818.0__py3-none-any.whl → 0.250819.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
MediBot/MediBot.py CHANGED
@@ -662,6 +662,34 @@ if __name__ == "__main__":
662
662
  # Initialize constants from config
663
663
  MediBot_Preprocessor_lib.initialize(e_state.config)
664
664
 
665
+ # PERFORMANCE OPTIMIZATION: Load both Medicare and Private patient databases during startup
666
+ # Files are small (10K-20K rows each) so memory usage is minimal (~4MB total)
667
+ # This eliminates the 1-2 second delay from user workflow entirely
668
+ print("Loading patient databases...")
669
+ MediLink_ConfigLoader.log("Loading patient databases...", level="INFO")
670
+
671
+ try:
672
+ medicare_path = e_state.config.get('MEDICARE_MAPAT_MED_PATH', "")
673
+ private_path = e_state.config.get('MAPAT_MED_PATH', "")
674
+
675
+ # Load both databases into separate caches
676
+ medicare_cache = MediBot_Preprocessor.load_existing_patient_ids(medicare_path) if medicare_path else {}
677
+ private_cache = MediBot_Preprocessor.load_existing_patient_ids(private_path) if private_path else {}
678
+
679
+ # Store both caches for later use
680
+ MediBot_Preprocessor.set_patient_caches(medicare_cache, private_cache)
681
+
682
+ if PERFORMANCE_LOGGING:
683
+ print("Patient databases loaded: {} Medicare, {} Private patients".format(
684
+ len(medicare_cache), len(private_cache)))
685
+ MediLink_ConfigLoader.log("Patient databases loaded: {} Medicare, {} Private patients".format(
686
+ len(medicare_cache), len(private_cache)), level="INFO")
687
+
688
+ except Exception as e:
689
+ MediLink_ConfigLoader.log("Warning: Could not load patient databases: {}".format(e), level="WARNING")
690
+ if PERFORMANCE_LOGGING:
691
+ print("Warning: Could not load patient databases - will load on demand")
692
+
665
693
  if PERFORMANCE_LOGGING:
666
694
  print("Loading CSV Data...")
667
695
  MediLink_ConfigLoader.log("Loading CSV Data...", level="INFO")
@@ -745,7 +773,13 @@ if __name__ == "__main__":
745
773
  if (not _ac()) or (not _ac().get_mapat_med_path()) or (not os.path.exists(_ac().get_mapat_med_path())):
746
774
  record_startup_warning("Warning: MAPAT.MED PATH is missing or invalid. Please check the path configuration.")
747
775
 
748
- # Perform the existing patients check
776
+ # PERFORMANCE OPTIMIZATION: Select the appropriate pre-loaded patient cache
777
+ # Both caches were loaded during startup, now we just select the right one
778
+ MediBot_Preprocessor.select_active_cache(is_medicare)
779
+ if PERFORMANCE_LOGGING:
780
+ print("Using {} patient cache for existing patient check".format("Medicare" if is_medicare else "Private"))
781
+
782
+ # Perform the existing patients check (now uses cached data)
749
783
  existing_patients, patients_to_process = MediBot_Preprocessor.check_existing_patients(selected_patient_ids, _ac().get_mapat_med_path() if _ac() else '')
750
784
 
751
785
  if existing_patients:
@@ -9,10 +9,7 @@ to improve code organization and maintainability.
9
9
  Compatible with Python 3.4.4 and Windows XP environments.
10
10
  """
11
11
 
12
- import json
13
- import os
14
- import sys
15
- import threading
12
+ import json, os, sys
16
13
 
17
14
  # Set the project directory to the parent directory of the current file
18
15
  project_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
@@ -144,30 +144,104 @@ def preprocess_csv_data(csv_data, crosswalk):
144
144
  MediLink_ConfigLoader.log(message, level="ERROR")
145
145
  print(message)
146
146
 
147
- def check_existing_patients(selected_patient_ids, MAPAT_MED_PATH):
148
- existing_patients = []
149
- # Convert to set for O(1) lookup performance
150
- selected_patient_ids_set = set(selected_patient_ids)
147
+ # Global caches for existing patient IDs to avoid repeated file I/O
148
+ _medicare_patients_cache = None
149
+ _private_patients_cache = None
150
+ _current_cache = None # Points to the active cache based on user selection
151
151
 
152
+ def load_existing_patient_ids(MAPAT_MED_PATH):
153
+ """
154
+ Load all existing patient IDs from MAPAT.MED file into memory cache.
155
+
156
+ Args:
157
+ MAPAT_MED_PATH: Path to the MAPAT.MED file
158
+
159
+ Returns:
160
+ dict: {patient_id: patient_name} mapping of all existing patients
161
+ """
162
+ patient_cache = {}
163
+
164
+ if not MAPAT_MED_PATH:
165
+ MediLink_ConfigLoader.log("MAPAT.MED path not provided - returning empty cache", level="WARNING")
166
+ return patient_cache
167
+
152
168
  try:
169
+ MediLink_ConfigLoader.log("Loading patient cache from: {}".format(MAPAT_MED_PATH), level="INFO")
153
170
  with open(MAPAT_MED_PATH, 'r') as file:
154
171
  next(file) # Skip header row
155
172
  for line in file:
156
- if line.startswith("0"): # 1 is a flag for a deleted record so it would need to be re-entered.
173
+ if line.startswith("0"): # 1 is a flag for a deleted record so it would need to be re-entered.
157
174
  patient_id = line[194:202].strip() # Extract Patient ID (Columns 195-202)
158
175
  patient_name = line[9:39].strip() # Extract Patient Name (Columns 10-39)
159
176
 
160
- if patient_id in selected_patient_ids_set:
161
- existing_patients.append((patient_id, patient_name))
162
- # Remove from set for O(1) operation
163
- selected_patient_ids_set.discard(patient_id)
177
+ if patient_id: # Only cache non-empty patient IDs
178
+ patient_cache[patient_id] = patient_name
179
+
180
+ MediLink_ConfigLoader.log("Loaded {} patients into cache from {}".format(len(patient_cache), MAPAT_MED_PATH), level="INFO")
181
+
164
182
  except FileNotFoundError:
165
- # Handle the case where MAPAT_MED_PATH is not found
166
- print("MAPAT.med was not found at location indicated in config file.")
167
- print("Skipping existing patient check and continuing...")
183
+ MediLink_ConfigLoader.log("MAPAT.med was not found at location: {}".format(MAPAT_MED_PATH), level="WARNING")
184
+ print("MAPAT.med was not found at location: {}".format(MAPAT_MED_PATH))
185
+ print("Continuing with empty patient cache...")
186
+ except Exception as e:
187
+ MediLink_ConfigLoader.log("Error loading patient cache: {}".format(e), level="ERROR")
188
+ print("Error loading patient cache: {}".format(e))
189
+
190
+ return patient_cache
191
+
192
+ def set_patient_caches(medicare_cache, private_cache):
193
+ """
194
+ Store both patient caches for later use based on user selection.
195
+
196
+ Args:
197
+ medicare_cache: Dict of Medicare patient IDs and names
198
+ private_cache: Dict of Private patient IDs and names
199
+ """
200
+ global _medicare_patients_cache, _private_patients_cache
201
+ _medicare_patients_cache = medicare_cache
202
+ _private_patients_cache = private_cache
203
+
204
+ def select_active_cache(is_medicare):
205
+ """
206
+ Select which patient cache to use based on Medicare selection.
207
+
208
+ Args:
209
+ is_medicare: True for Medicare patients, False for Private patients
210
+ """
211
+ global _current_cache, _medicare_patients_cache, _private_patients_cache
212
+ _current_cache = _medicare_patients_cache if is_medicare else _private_patients_cache
213
+
214
+ def check_existing_patients(selected_patient_ids, MAPAT_MED_PATH):
215
+ """
216
+ Check which selected patients already exist in the system using cached data.
217
+ This is now much faster as it uses in-memory cache instead of file I/O.
218
+
219
+ Args:
220
+ selected_patient_ids: List of patient IDs to check
221
+ MAPAT_MED_PATH: Path to MAPAT.MED file (for fallback if cache not available)
168
222
 
169
- # Convert remaining set back to list for return
170
- patients_to_process = list(selected_patient_ids_set)
223
+ Returns:
224
+ tuple: (existing_patients, patients_to_process)
225
+ """
226
+ global _current_cache
227
+
228
+ # Use current cache if available, otherwise fallback to loading file
229
+ if _current_cache is not None:
230
+ existing_patients_dict = _current_cache
231
+ else:
232
+ # Fallback: load from file if cache not available
233
+ existing_patients_dict = load_existing_patient_ids(MAPAT_MED_PATH)
234
+
235
+ existing_patients = []
236
+ patients_to_process = []
237
+
238
+ # Use cached data for O(1) lookups instead of file I/O
239
+ for patient_id in selected_patient_ids:
240
+ if patient_id in existing_patients_dict:
241
+ patient_name = existing_patients_dict[patient_id]
242
+ existing_patients.append((patient_id, patient_name))
243
+ else:
244
+ patients_to_process.append(patient_id)
171
245
 
172
246
  return existing_patients, patients_to_process
173
247
 
@@ -309,6 +309,103 @@ def detect_date_format(date_str):
309
309
 
310
310
  return None
311
311
 
312
+ class OptimizedDate:
313
+ """
314
+ Optimized date object that pre-computes all common format variations
315
+ to avoid redundant datetime conversions throughout the application.
316
+ """
317
+ def __init__(self, datetime_obj):
318
+ self.datetime = datetime_obj
319
+ # Pre-compute all common format variations
320
+ self._display_short = datetime_obj.strftime('%m-%d') # For table display
321
+ self._display_full = datetime_obj.strftime('%m-%d-%Y') # Full format
322
+ self._medisoft_format = datetime_obj.strftime('%m%d%Y') # For Medisoft entry
323
+ self._iso_format = datetime_obj.strftime('%Y-%m-%d') # For sorting/comparison
324
+
325
+ @property
326
+ def display_short(self):
327
+ """Short display format: MM-DD"""
328
+ return self._display_short
329
+
330
+ @property
331
+ def display_full(self):
332
+ """Full display format: MM-DD-YYYY"""
333
+ return self._display_full
334
+
335
+ @property
336
+ def medisoft_format(self):
337
+ """Medisoft entry format: MMDDYYYY"""
338
+ return self._medisoft_format
339
+
340
+ @property
341
+ def iso_format(self):
342
+ """ISO format for sorting: YYYY-MM-DD"""
343
+ return self._iso_format
344
+
345
+ def __str__(self):
346
+ return self._display_full
347
+
348
+ def __repr__(self):
349
+ return "OptimizedDate({})".format(self._display_full)
350
+
351
+ def __eq__(self, other):
352
+ if isinstance(other, OptimizedDate):
353
+ return self.datetime == other.datetime
354
+ elif hasattr(other, 'strftime'): # datetime object
355
+ return self.datetime == other
356
+ return False
357
+
358
+ def __lt__(self, other):
359
+ if isinstance(other, OptimizedDate):
360
+ return self.datetime < other.datetime
361
+ elif hasattr(other, 'strftime'): # datetime object
362
+ return self.datetime < other
363
+ return NotImplemented
364
+
365
+ def __gt__(self, other):
366
+ if isinstance(other, OptimizedDate):
367
+ return self.datetime > other.datetime
368
+ elif hasattr(other, 'strftime'): # datetime object
369
+ return self.datetime > other
370
+ return NotImplemented
371
+
372
+ def strftime(self, format_str):
373
+ """Fallback for any custom format needs"""
374
+ return self.datetime.strftime(format_str)
375
+
376
+ @classmethod
377
+ def from_string(cls, date_str, cleaned=False):
378
+ """
379
+ Create OptimizedDate from string, with optional pre-cleaning.
380
+
381
+ Args:
382
+ date_str: Date string to parse
383
+ cleaned: If True, assumes string is already cleaned
384
+
385
+ Returns:
386
+ OptimizedDate object or None if parsing fails
387
+ """
388
+ if not cleaned:
389
+ date_str = clean_surgery_date_string(date_str)
390
+ if not date_str:
391
+ return None
392
+
393
+ # Try standard format first (most common)
394
+ try:
395
+ return cls(datetime.strptime(date_str, '%m/%d/%Y'))
396
+ except ValueError:
397
+ pass
398
+
399
+ # Try alternative formats
400
+ formats = ['%m-%d-%Y', '%m/%d/%y', '%m-%d-%y', '%Y/%m/%d', '%Y-%m-%d']
401
+ for fmt in formats:
402
+ try:
403
+ return cls(datetime.strptime(date_str, fmt))
404
+ except ValueError:
405
+ continue
406
+
407
+ return None
408
+
312
409
  def clean_surgery_date_string(date_str):
313
410
  """
314
411
  Cleans and normalizes surgery date strings to handle damaged data.
MediBot/__init__.py CHANGED
@@ -19,7 +19,7 @@ Smart Import Integration:
19
19
  medibot_main = get_components('medibot_main')
20
20
  """
21
21
 
22
- __version__ = "0.250818.0"
22
+ __version__ = "0.250819.0"
23
23
  __author__ = "Daniel Vidaud"
24
24
  __email__ = "daniel@personalizedtransformation.com"
25
25
 
MediCafe/__init__.py CHANGED
@@ -27,7 +27,7 @@ Smart Import System:
27
27
  api_suite = get_api_access()
28
28
  """
29
29
 
30
- __version__ = "0.250818.0"
30
+ __version__ = "0.250819.0"
31
31
  __author__ = "Daniel Vidaud"
32
32
  __email__ = "daniel@personalizedtransformation.com"
33
33
 
@@ -202,7 +202,7 @@ def write_output_file(document_segments, output_directory, endpoint_key, input_f
202
202
 
203
203
  # Write the document to the output file
204
204
  try:
205
- with open(new_output_file_path, 'w') as output_file:
205
+ with open(new_output_file_path, 'w', encoding='utf-8') as output_file:
206
206
  output_file.write('\n'.join(document_segments))
207
207
  MediLink_ConfigLoader.log("Successfully converted and saved to {}".format(new_output_file_path), config, level="INFO")
208
208
  return new_output_file_path