
    Q[jn              	         d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlmZ ddlmZmZ ddlmZmZmZ ddlmZ ddlmZmZmZ dd	lmZ  ej                    d
z  dz  dz  Zedz  ZdZdZ  e!dd          Z"dZ#dZ$h dZ%dddddddddZ&dZ'dhd e'D             z   e(e&)                                          z  Z*dhd  e%D             z  Z+h d!Z,h d"Z- ed#$           G d% d&                      Z.dkd+Z/dld.Z0dmd2Z1dnd4Z2dod9Z3dpd;Z4dpd<Z5dmd=Z6dqd?Z7dqd@Z8	 drdsdCZ9dqdDZ:dtdFZ;dudJZ<dvdNZ=dwdSZ>dxdVZ?dyd]Z@	 drdzd`ZAdldaZBd{dcZCd|dfZDdrd}diZEeFdjk    r eG eE                      dS )~aK  Safety-first multimodal correlation engine for HealthManager.

The engine computes exploratory, phase-stratified Spearman associations from
complete cases only. Missing symptom days are never interpreted as symptom-free.
Only aggregate statistics are persisted; daily values and source names remain in
the protected source tables.
    )annotationsN)defaultdict)	dataclassreplace)datedatetime	timedelta)Path)AnyCallableIterable)	spearmanrz.hermesassets
Gesundheitzhealth_data.db   g333333?   Bspearman_7d_block_permutation_complete_case_phase_stratified_bh_v1i  >   hautaugengelenkegi_darmaphthen_mundulzeramuedigkeit_fatiguevaskulaer_thrombose_warnzeichenzlab:crp_mg_lzlab:d_dimer_ug_lzlab:fibrinogen_g_lzlab:factor_viii_percentzlab:platelets_tsd_ulzlab:leukocytes_tsd_ulzlab:ferritin_ng_ml))c_reaktives_protein_crpmg_l)crpr   )d_dimerug_l)
fibrinogeng_l)faktor_viiipercent)thrombozytentsd_ul)
leukozytenr%   )ferritinng_ml)
step_countactive_energysleep_analysisresting_heart_rateheart_rate_variabilityblood_oxygen_saturationrespiratory_ratephysical_effortnutrition:histamine_scorec                    h | ]}d | S )apple: ).0metrics     H/home/agent/.hermes/assets/Gesundheit/scripts/multimodal_correlations.py	<setcomp>r8   B   s!    555V555    symptom_totalc                    h | ]}d | S symptom_r4   r5   	dimensions     r7   r8   r8   E   s!    &b&b&b)'=)'='=&b&b&br9   >   unknownearly_treatmentstable_treatmentbaseline_pre_treatment>   computedinsufficient_ninsufficient_coverageT)frozenc                      e Zd ZU ded<   ded<   ded<   ded<   ded<   ded<   ded	<   d
ed<   ded<   ded<   ded<   ded<   ded<   ded<   ded<   ded<   dS )CorrelationResultstr	predictortargetintlag_daysmedication_phaseneligible_target_daysexpected_target_daysfloattarget_coveragemissing_pairsfloat | Nonerhop_valueq_valuestatusmethodztuple[str, ...]quality_flagsinterpretationN)__name__
__module____qualname____annotations__r4   r9   r7   rI   rI   J   s         NNNKKKMMM
FFFKKKKKK""""r9   rI   db_pathr
   returnsqlite3.Connectionc                P    t          j        |           }t           j        |_        |S N)sqlite3connectRowrow_factory)rb   
connections     r7   connrl   ^   s!    ))J$[Jr9   rk   Nonec                (    t           j        | _        d S rf   )rg   ri   rj   )rk   s    r7   _ensure_row_factoryro   d   s    $[Jr9   valuer   rV   c                :   	 | %t          |                                           dk    rd S t          t          |                               dd                                                    }t	          j        |          r|nd S # t          t          f$ r Y d S w xY w)N ,.)rJ   striprS   r   mathisfinite	TypeError
ValueError)rp   numbers     r7   _floatr{   h   s    =CJJ,,.."444s5zz))#s3399;;<<v..8vvD8z"   tts   'B AB BB
str | Nonec                   t          | pd                                          }t          j        d|          r8	 t	          j        |                                          S # t          $ r Y d S w xY wt          j        d|          sd S 	 t          j        |	                    d          r|d d         dz   n|          }n# t          $ r Y d S w xY w|                                                                S )Nrr   z\d{4}-\d{2}-\d{2}zG\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,6})?(?:Z|[+-]\d{2}:\d{2})?Zz+00:00)
rJ   ru   re	fullmatchr   fromisoformat	isoformatry   r   endswith)rp   textparseds      r7   _canonical_dayr   r   s   u{!!##D	|($// 	%d++55777 	 	 	44	<R   t'c@R@R(\SbS	H(<(<X\]]   tt;;==""$$$s#   %A   
A.-A.	6C   
CCdayrJ   lagrM   c                p    t          j        |           t          |          z                                   S )Ndays)r   r   r	   r   )r   r   s     r7   _day_addr      s/    s##iS&9&9&99DDFFFr9   r   c           	         t          | pd                                                              t                               ddddd                    }t	          j        dd|                              d          S )	Nrr   aeoeuess)   ä   ö   ü   ßz
[^a-z0-9]+_)rJ   casefold	translate	maketransr   subru   )r   
normalizeds     r7   _slugr      sh    TZR))++55cmm4W[cgosDtDt6u6uvvJ6-j1177<<<r9   c                    t          t          | pd                              dd                              dd                              dd                    S )Nrr      µuu   μ%z	 percent )r   rJ   r   )r   s    r7   
_unit_slugr      sK    TZR((s33;;D#FFNNsT_``aaar9   c                    t          | pd                                                                          }dddddddddddddd}|                    |          S )Nrr                 ?g       @g      @)0123z	keine (0)znone (0)z
leicht (1)zmild (1)z
mittel (2)zmoderat (2)z
schwer (3)z	stark (3)zhoch (3))rJ   r   ru   get)rp   r   exacts      r7   	_severityr      sp    u{$$&&,,..D E 99T??r9   dict[str, dict[str, float]]c                6   t          |            t          d           }|                     d          D ]}t          t	          |d                             }|t
          vr.t	          |d                   dd         }||         |                             t          |d                              di id	 t
          D             }|                                D ]\  }}t          |          t
          k    rt          d
 |                                D                       rJd |                                D             }t          |                                          |d         |<   |                                D ]\  }}||d|          |<   |S )z@Load only complete structured quick logs; absence stays missing.c                 *    t          t                    S rf   )r   listr4   r9   r7   <lambda>z&load_symptom_targets.<locals>.<lambda>   s    ;W[K\K\ r9   zSELECT id,datum,symptom,schwergrad FROM symptom_log
           WHERE kontext='daily_quick_score' AND datum IS NOT NULL
           ORDER BY idsymptomdatumN
   
schwergradr:   c                    i | ]}d | i 	S r<   r4   r>   s     r7   
<dictcomp>z(load_symptom_targets.<locals>.<dictcomp>   s#    
J
J
J)!i!!2
J
J
Jr9   c              3  P   K   | ]!}t          |          d k    p	|d         du V  "dS )   r   N)len)r5   valuess     r7   	<genexpr>z'load_symptom_targets.<locals>.<genexpr>   s;      WWs6{{a46!9#4WWWWWWr9   c                P    i | ]#\  }}|d          |t          |d                    $S )r   )rS   )r5   r?   r   s      r7   r   z(load_symptom_targets.<locals>.<dictcomp>   s>     
 
 
!	6ay$ uVAY''$$$r9   r=   )ro   r   executer   rJ   SYMPTOM_DIMENSIONSappendr   itemssetanyr   sum)	rk   by_dayrowr?   r   result
dimensionscomplete_valuesrp   s	            r7   load_symptom_targetsr      s   
###7BC\C\7]7]F!!	  D D
 #c)n--..	...#g,$ 	sI%%iL0A&B&BCCCC+
J
J7I
J
J
J+F "<<>> 8 8Zz??000WW:CTCTCVCVWWWWW 	
 
%/%5%5%7%7
 
 

 (+?+A+A+C+C'D'D$ / 5 5 7 7 	8 	8Iu27F)i))*3//	8Mr9   c                8   t          |            i }|                     d          D ]p}t          |d         pd          dk    st          |d         pd          dk    r9t          |d                   }| ||t	          |d                   dd         <   qd	|iS )
zUse only the rule-based score whose unit semantics are explicit.

    Macro and nutrient columns stay excluded until the separate YAZIO nutrient-unit
    audit is complete.
    zSELECT datum,histamine_score,item_count,histamine_unknown_count
           FROM nutrition_daily_summary_v2 WHERE datum IS NOT NULL
item_countr   histamine_unknown_counthistamine_scoreNr   r   r1   )ro   r   rM   r{   rJ   )rk   seriesr   rp   s       r7   load_nutrition_featuresr      s     
###!F!!	F  3 3 s< %A&&!++s37P3Q3VUV/W/W[\/\/\s,-..-2F3s7|$$SbS)*'00r9   points_loader&Callable[[str], dict[str, Any]] | Nonec           	        |}|t          |            t          j                            dt	          t          t                                                    j                             ddl	m
 d                    d t          D                       }t          t                    |                     d| dt                    }|D ]0}t	          |d                                                |           1dfd}|}i }t          D ]j}i }	 ||                                          D ]@\  }
}t%          |dd           dk    rt'          t%          |dd                     }|||	|
<   A|	|d| <   k|S )Nr   )daily_pointsrs   c              3     K   | ]}d V  dS )?Nr4   )r5   r   s     r7   r   z&load_apple_features.<locals>.<genexpr>   s"      ;;;;;;;;r9   zSELECT id,metric,value,unit,start_date,end_date,source_name,file_name,file_hash
                FROM apple_health_records
                WHERE value IS NOT NULL AND start_date IS NOT NULL
                  AND metric IN (zD)
                ORDER BY metric,start_date,end_date,source_name,idr6   rJ   rc   dict[str, Any]c                F     |                      | g                     S )N)_rows)r   )r6   r   rows_by_metrics    r7   	from_rowsz&load_apple_features.<locals>.from_rows   s(    <n.@.@.L.LMMMMr9   qualitydirectrp   r3   )r6   rJ   rc   r   )ro   syspathinsertrJ   r
   __file__resolveparentapple_health_analyticsr   joinAPPLE_METRICSr   r   r   r   r   getattrr{   )rk   r   loaderplaceholdersrowsr   r   featuresr6   r   r   pointrp   r   r   s                @@r7   load_apple_featuresr      s    F~J'''3tH~~5577>??@@@777777xx;;];;;;;7B47H7H!!F #/F F F
 
 
  	; 	;C3s8}--.55c::::	N 	N 	N 	N 	N 	N 	N ,.H - -#% &....00 	$ 	$JCui..(::75'48899E #s&,"&""##Or9   c           
     f   t          |            t          t                    }|                     d          }t          t                    }t          j        d          }|D ]}t                              t          t          |d                             t          t          |d                             f          }|sat          |d                   pt          |d                   }||||f                             t          |d         pd	                                                     |                                D ]Y\  \  }}}t!          |          d
k    s|                    |d                   s7t%          |d                   }	|	|	||         |<   Zt          |          S )zHLoad only exact, strictly provenance-verified same-day lab observations.aQ  SELECT parameter_name,wert,einheit,abnahme_datum,befund_datum
           FROM laborwerte
           WHERE lower(trim(COALESCE(validierungsstatus,'')))='validiert'
             AND verified_against_original=1
             AND reference_range_source='scanned_original'
             AND trim(COALESCE(einheit,''))<>''
           ORDER BY idz^[+-]?\d+(?:[.,]\d+)?$parameter_nameeinheitabnahme_datumbefund_datumNwertrr   r   r   )ro   r   dictr   r   r   compileLAB_FEATURE_ALLOWLISTr   r   rJ   r   r   r   ru   r   r   r   r{   )
rk   r   r   
candidatesexact_numberr   safe_featurer   
raw_valuesrp   s
             r7   load_lab_featuresr     s   
###,7,=,=H	 D 4?t3D3DJ:788L O O,003s+,--..
3s9~;N;N0O0OP
 
  	 S122YnSEX6Y6Y;L#&'..s3v;3D"/E/E/K/K/M/MNNNN+5+;+;+=+= 0 0'sZz??a|'='=jm'L'Lz!}%%*/H\"3'>>r9   Callable[[str], str]c                   t          |            |                     d                                          d         }fd|                     d          D             }|r#|s!t          j        t          |                    nd d	fd}|S )
NaY  SELECT COUNT(*) FROM medication_administrations
           WHERE (lower(COALESCE(medication_name,'')) LIKE '%hyrimoz%'
              OR lower(COALESCE(medication_name,'')) LIKE '%adalimumab%')
             AND lower(trim(COALESCE(event_type,''))) IN
                 ('stopped','paused','restart','dose_change','abgesetzt','pausiert','neustart')r   c                B    g | ]}t          |d                    xS )r   )r   )r5   r   r   s     r7   
<listcomp>z-medication_phase_function.<locals>.<listcomp>5  s>     	 	 	 "#g,///C< 	 =<<r9   a!  SELECT datum FROM medication_administrations
               WHERE (lower(COALESCE(medication_name,'')) LIKE '%hyrimoz%'
                  OR lower(COALESCE(medication_name,'')) LIKE '%adalimumab%')
                 AND lower(trim(COALESCE(event_type,''))) IN ('administered','verabreicht')r   rJ   rc   c                    dS t          j        | d d                   }|k     rdS |t          d          z   k     rdS dS )Nr@   r   rC   8   r   rA   rB   )r   r   r	   )r   currentstarts     r7   phasez(medication_phase_function.<locals>.phaseA  s[    =9$S"X..U??++UYB//////$$!!r9   )r   rJ   rc   rJ   )ro   r   fetchoner   r   min)rk   
disruptiveadministration_daysr  r   r  s       @@r7   medication_phase_functionr	  ,  s    
#####	c  hjjJ	 	 	 	%%_
 
	 	 	 =PlXblDs#677888hlE" " " " " " Lr9   p_valuesIterable[float]list[float]c                n   t          |           }t          |          }|sg S t          t          |          |j                  }dg|z  }d}t          |dz
  dd          D ]R}||         }|dz   }t          |||         |z  |z            }t          t          |||                   d          ||<   S|S )N)keyr   r   r   )r   r   sortedrange__getitem__r  max)	r
  r   countorderadjustedrunning
rank_indexoriginal_indexranks	            r7   benjamini_hochbergr  N  s    (^^FKKE 	5<<V%7888Euu}HGEAIr2.. R R
z*A~gvn5=DEE#&s7F>4J'K'KS#Q#Q  Or9   xsysrS   c                F    t          t          | |          j                  S rf   )rS   r   	statistic)r  r  s     r7   _spearman_rhor  ^  s    2r"",---r9   r   r   	list[str]list[list[float]]c                   t          |           t          |          k    rt          d          t          t                    t	          || d          D ]m\  }}t          j        |          }|t          |                                          z
  	                                }|         
                    ||f           nfdt                    D             S )Nz&values and days must have equal lengthT)strictr   c                N    g | ]!}d  t          |                   D             "S )c                    g | ]\  }}|S r4   r4   )r5   _dayrp   s      r7   r   z4_calendar_week_blocks.<locals>.<listcomp>.<listcomp>k  s    >>>;4>>>r9   )r  )r5   
week_startby_weeks     r7   r   z)_calendar_week_blocks.<locals>.<listcomp>j  sD        	?>&)<"="=>>>  r9   )r   ry   r   r   zipr   r   r	   weekdayr   r   r  )r   r   day_textrp   r   r'  r(  s         @r7   _calendar_week_blocksr,  b  s    
6{{c$iiABBB2=d2C2CGtVD999 6 6% **I3;;==9999DDFF

""He#45555    //   r9   	pair_days	seed_textc                   t          t          | |                    }t          ||          t          t	          t                                        }t                    dk     rdS t                    dk    r"t          t          j        |                    }nt          t          j        |                                                                          dd         d          }t          j        |          }|g}|h}	t          |          t           k     ryt          |          }
|                    |
           t          |
          }||	vr*|	                    |           |                    |           t          |          t           k     yd}|D ]9}fd|D             }t          t          | |                    |dz
  k    r|d	z  }:t)          |d	          t          |          z  S )
zGTwo-sided calendar-week block permutation preserving within-week order.   r      N   r   c                *    g | ]}|         D ]}|S r4   r4   )r5   block_indexrp   blockss      r7   r   z(_block_permutation_p.<locals>.<listcomp>  s+    ZZZkf[FYZZUEZZZZr9   g-q=r   )absr  r,  tupler  r   r   	itertoolspermutationsrM   hashlibsha256encode	hexdigestrandomRandomMAX_BLOCK_PERMUTATIONSshuffleaddr   r  )r  r  r-  r.  observedindexesr9  seedrngseen	candidateitemextremepermutationpermutedr5  s                  @r7   _block_permutation_prM  p  s    =R(())H"2y11FE#f++&&''G
6{{Qs
6{{aI27;;<<7>)"2"2"4"455??AA#2#FKKmD!!yy,"888WIKK	"""##D4##D))) ,"888 G#  ZZZZ[ZZZ}R**++x%/???qLGw??S....r9   rK   rL   
phase_nameeligibleexpectedcoveragec
                   t          |          }
g d}t          | ||||
||t          |d          t          ||
z
  d          d t                    }|t
          k     r6|                    d           t          di |d d dt          |          ddS |
t          k     s@t          t          |                    d	k     s t          t          |                    d	k     r6|                    d
           t          di |d d dt          |          ddS t          ||          }t          |||	|  d| d| d|           }t          di |t          |d          t          |d          dt          |          ddS )Ncomplete_casephase_stratified7d_block_permutationno_causality   r   )rK   rL   rN   rO   rP   rQ   rR   rT   rU   rY   r[   low_target_coveragerF   2   Zielabdeckung unter 60 Prozent; keine Kausalität.)rW   rX   rZ   r\   r]      low_n_or_variancerE   G   Unzureichende vollständige Datenpaare oder Varianz; keine Kausalität.|rD   u`   Explorative phasenstratifizierte Rangassoziation mit 7-Tage-Blockpermutation; keine Kausalität.r4   )r   r   roundr  METHODMIN_TARGET_COVERAGEr   rI   r7  	MIN_PAIRSr   r  rM  )rK   rL   r   rN  rO  rP  rQ  r  r  r-  rP   flagscommonrW   rX   s                  r7   _result_for_pairsre    s    	BAYYYE#
%%h**(Q,**  F %%%*+++  
 

*,,O
 
 
 
 	
 	9}}CGGq((CBLL1,<,<()))  
 

#,,d
 
 
 
 	
 B

C"
B	iEE&EE3EEEE G   
#qMMgq!!Elly    r9   apple_points_loaderlist[CorrelationResult]c                   ! t          |           }i }|                    t          |                      |                    t          | |                     |                    t	          |                      t          |           g  |                                D ]R\  }!!s	t          fd!D                       pdg}t          |                                          D ]\  }}|s	t          D ]|D ]}fd|D             }	t          t          !          t          |	                    }
t          t          !          t          |	                    }|
|k    rlg }t          j        |
          }t          j        |          }||k    rq|                                }t          |           } |          |k    r$ |          |k    r|                    |           |t!          d          z  }||k    q|s!fd|D             }t#          |          t#          |          z  }g }g }g }|D ]c}t          |           }||vr|                    ||                    |                    !|                    |                    |           d                     t%          |||t#          |          t#          |          ||||
  
                   
Tt'          t(                    }t+                     D ]>\  }}|j        dk    r.|j        '||j        |j        f                             |           ?|                                D ]y}t7           fd|D                       }t9          ||          D ]K\  }}|d	k    o |         j        d
k    }|rdnd}t=           |         t?          |d          |           |<   Lz S )Nc                &    h | ]} |          S r4   r4   )r5   r   	phase_fors     r7   r8   z"compute_results.<locals>.<setcomp>  s!    AAAC3AAAr9   r@   c                0    g | ]}t          |          S r4   )r   )r5   r   r   s     r7   r   z#compute_results.<locals>.<listcomp>  s#    -]-]-]ShsC.@.@-]-]-]r9   r   r   c                    g | ]}|v |	S r4   r4   )r5   r   target_seriess     r7   r   z#compute_results.<locals>.<listcomp>  s#    $Z$Z$ZSSMEYEYSEYEYEYr9   rD   c                H    g | ]}|         j         |         j         ndS )Nr   )rX   )r5   indexresultss     r7   r   z#compute_results.<locals>.<listcomp>  sA     '
 '
 '
 '.en&<&HGEN""c'
 '
 '
r9   皙?   B   Exploratives Signal nach Mehrfachtestkorrektur; keine Kausalität.G   Kein belastbares korrigiertes Signal; explorativ und keine Kausalität.rX  )rY   r]   ) r   updater   r   r   r	  r   r  LAGSr  r  r   r   r   r   r   r	   r   re  r   r   	enumeraterZ   rX   rL   rO   r   r  r)  rP   r   r_  )"rk   rf  targetsr   target_namephasesrK   predictor_seriesrN  shifted_predictor_daysr  endexpected_daysr  end_dateoutcome_daypredictor_dayeligible_daysrQ  r  r  r-  groupedro  r   rD  r  rY   signalr]   r   rj  rp  rm  s"                                 @@@@r7   compute_resultsr    s    #:..G,.HOO+J77888OO'
4GHHIIIOO%j11222)*55I')G&-mmoo 2 2"] 	AAAA=AAABBQyk+1(..2B2B+C+C .	 .	'I'#  + +"( * *J-]-]-]-]L\-]-]-]*M 2 2C8N4O4OPPEc-00#6L2M2MNNCs{{ /1M"077G#1#66H!X--&-&7&7&9&9(0sd(C(C$9[11Z??IImD\D\`jDjDj)00===9!#4#4#44 "X-- ) ! $Z$Z$Z$ZM$Z$Z$ZM"=11C4F4FFH&(B&(B+-I'4 6 6(0sd(C(C(0@@@$		"2="ABBB		-"<===!((5555NN)%'&....$%    ;*+.	` 1<D0A0AG"7++ L Lv=J&&6>+EV]F$;<=DDUKKK>>## o o% '
 '
 '
 '
 '
 '
 '
   "'844 	o 	oNE7^>(8B(>F _TT^ 
 %WU^U7A=N=N_mnnnGENN	o Nr9   c                    |                      d           d |                      d          D             }d|vr|                      d           d|vr|                      d           |                      d           d S )	Nac  CREATE TABLE IF NOT EXISTS multimodal_correlation_results (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            predictor TEXT NOT NULL,
            target TEXT NOT NULL,
            lag_days INTEGER NOT NULL,
            medication_phase TEXT NOT NULL,
            n INTEGER NOT NULL,
            eligible_target_days INTEGER NOT NULL,
            expected_target_days INTEGER NOT NULL DEFAULT 0,
            target_coverage REAL NOT NULL DEFAULT 0,
            missing_pairs INTEGER NOT NULL,
            rho REAL,
            p_value REAL,
            q_value REAL,
            status TEXT NOT NULL,
            method TEXT NOT NULL,
            quality_flags TEXT NOT NULL,
            interpretation TEXT NOT NULL,
            computed_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
            UNIQUE(predictor,target,lag_days,medication_phase)
        )c                    h | ]
}|d          S )r   r4   )r5   r   s     r7   r8   z ensure_schema.<locals>.<setcomp>8  s    iii#s1viiir9   z1PRAGMA table_info(multimodal_correlation_results)rR   zeALTER TABLE multimodal_correlation_results ADD COLUMN expected_target_days INTEGER NOT NULL DEFAULT 0rT   z]ALTER TABLE multimodal_correlation_results ADD COLUMN target_coverage REAL NOT NULL DEFAULT 0zCREATE INDEX IF NOT EXISTS idx_multimodal_correlations_status ON multimodal_correlation_results(status,target,medication_phase))r   )rk   columnss     r7   ensure_schemar     s    	  . ji!3!34g!h!hiiiGW,,s	
 	
 	
 ''k	
 	
 	
  	J    r9   r   c                   | j         t          vrt          d          | j        t          vrt          d          | j        t          vs| j        t          vrt          d          | j	        t          vs| j        t          k    rt          d          | j        | j        | j        | j        f}t#          d |D                       rt          d          | j        dk     s| j        | j        cxk    r| j        k    sn t          d          | j        | j        | j        z
  k    rt          d	          t%          | j        t(                    s!t%          | j        t*          t,          f          st          d
          | j        | j        z  }t/          j        t-          | j                            r*t/          j        t-          | j                  |dd          st          d          d4d} || j        ddd            || j        ddd            || j        ddd           d}| j        dk    ra|d z   }d!}| j        t:          k    rt          d"          t#          d# | j        | j        | j        fD                       rt          d$          n| j        d%k    ra|d&z   }d'}| j        t:          k     rt          d(          t#          d) | j        | j        | j        fD                       rt          d*          n|}| j        t:          k     s| j        t<          k     rt          d+          t#          d, | j        | j        | j        fD                       rt          d-          | j        d uo| j        d.k    o
| j        d/k    }|rd0nd1}| j        |k    rt          d2          | j         |k    rt          d3          d S )5Nzpredictor is not allowlistedztarget is not allowlistedz"phase or status is not allowlistedz lag or method is not allowlistedc              3  x   K   | ]5}t          |t                    pt          |t                     p|d k     V  6dS )r   N)
isinstanceboolrM   r5   rp   s     r7   r   z/_validate_result_for_storage.<locals>.<genexpr>V  sH      
b
bRW:eT""M*UC*@*@&@MEAI
b
b
b
b
b
br9   z$counts must be non-negative integersr   zcount invariants are invalidz"missing-pair count is inconsistentztarget coverage must be numericr   gƠ>)rel_tolabs_tolz*target coverage is invalid or inconsistentrp   rV   lowerrS   uppernamerJ   rc   rm   c                2   | d S t          | t                    st          | t          t          f          st	          | d          t          j        t          |                     r|t          |           cxk    r|k    sn t	          | d          d S )Nz must be numericz is outside its valid range)r  r  rM   rS   ry   rv   rw   )rp   r  r  r  s       r7   boundedz-_validate_result_for_storage.<locals>.boundedf  s    =FeT"" 	8*US%L*I*I 	8666777}U5\\** 	C%5<<2P2P2P2P52P2P2P2PAAABBB 3Q2Pr9   g      r   rW   rX   rY   rS  rF   )rY  rZ  zcoverage status is inconsistentc              3     K   | ]}|d uV  	d S rf   r4   r  s     r7   r   z/_validate_result_for_storage.<locals>.<genexpr>z  '      [[UuD [[[[[[r9   z8insufficient-coverage result contains inferential valuesrE   )r\  r]  z3insufficient-n status is inconsistent with coveragec              3     K   | ]}|d uV  	d S rf   r4   r  s     r7   r   z/_validate_result_for_storage.<locals>.<genexpr>  r  r9   z1insufficient-n result contains inferential valuesz8computed status is inconsistent with evidence thresholdsc              3     K   | ]}|d u V  	d S rf   r4   r  s     r7   r   z/_validate_result_for_storage.<locals>.<genexpr>  s&      WWu}WWWWWWr9   z(computed result lacks inferential valuesrq  rr  rs  rt  z2quality flags are not generated by the safe enginez2interpretation is not generated by the safe engine)
rp   rV   r  rS   r  rS   r  rJ   rc   rm   )!rK   ALLOWED_PREDICTORSry   rL   ALLOWED_TARGETSrO   ALLOWED_PHASESrZ   ALLOWED_STATUSESrN   rv  r[   r`  rP   rQ   rR   rU   r   r  rT   r  rM   rS   rv   rw   iscloserW   rX   rY   ra  rb  r\   r]   )r   countsexpected_coverager  
base_flagsexpected_flagsexpected_interpretationr  s           r7   _validate_result_for_storager  F  sW   1117888}O++4555n44M]8]8]=>>>d""fmv&=&=;<<< 	##	F 
b
b[a
b
b
bbb A?@@@"Q&&F/NNNN63NNNNN7888v:VXEEE=>>>&($// <z&BX[^`eZf7g7g <:;;;3f6QQ=v56677 Gt|f$%%'8#t@ @ @ G EFFFC C C C GFJc5)))GFNCi000GFNCi000J }///#&>>"V!%888>???[[vz6>6>.Z[[[[[ 	YWXXX	Y	*	*	*#&<<U 	  !$777RSSS[[vz6>6>.Z[[[[[ 	RPQQQ	R $!$77768i;O;OWXXXWW6:v~v~*VWWWWW 	IGHHHt+X#0EX&(VX. [PPZ 	 
 ~--MNNN 777MNNN 87r9   rp  Iterable[CorrelationResult]c                    t          |          }|D ]}t          |           t          |            |                     d           |                     dd |D                        d S )Nz*DELETE FROM multimodal_correlation_resultsaV  INSERT INTO multimodal_correlation_results
           (predictor,target,lag_days,medication_phase,n,eligible_target_days,
            expected_target_days,target_coverage,missing_pairs,rho,p_value,q_value,status,
            method,quality_flags,interpretation,computed_at)
           VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,CURRENT_TIMESTAMP)c                    g | ]v}|j         |j        |j        |j        |j        |j        |j        |j        |j        |j	        |j
        |j        |j        |j        t          j        |j                  |j        fwS r4   )rK   rL   rN   rO   rP   rQ   rR   rT   rU   rW   rX   rY   rZ   r[   jsondumpsr\   r]   r5   r   s     r7   r   z!store_results.<locals>.<listcomp>  s     		
 		
 		
   &-&BY&5v7R&(<fj&.v}
6/00&2G		
 		
 		
r9   )r   r  r  r   executemany)rk   rp  materializedr   s       r7   store_resultsr    s    ==L - -$V,,,,*CDDD	H
		
 		
 '		
 		
 		
    r9   argvlist[str] | Nonec                   t          j        t                    }|                    dt          d           |                    |           }|j                                        st          d|j                   t          |j                  }	 t          |          }t          ||           |                                 t          d |D                       }t          d |D                       }t          t          j        d||d	                     |                                 n# |                                 w xY wd
S )N)descriptionz--dbT)typerequiredzDatabase not found: c              3  ,   K   | ]}|j         d k    V  dS )rD   NrZ   r  s     r7   r   zmain.<locals>.<genexpr>  s)      IIvv}
2IIIIIIr9   c              3  ,   K   | ]}|j         d k    V  dS )rE   Nr  r  s     r7   r   zmain.<locals>.<genexpr>  s*      SS6=,<<SSSSSSr9   ok)rZ   rD   insufficientr   )argparseArgumentParser__doc__add_argumentr
   
parse_argsdbexists
SystemExitrl   r  r  commitr   printr  r  close)r  parserargsrk   rp  rD   r  s          r7   mainr    s>   $999F
TD999T""D7>> ;999:::dgJ!*--j'***IIIIIIISS7SSSSSdjDhP\]]^^___
1s   B
D1 1E__main__)rb   r
   rc   rd   )rk   rd   rc   rm   )rp   r   rc   rV   )rp   r   rc   r|   )r   rJ   r   rM   rc   rJ   )r   rJ   rc   rJ   )rk   rd   rc   r   rf   )rk   rd   r   r   rc   r   )rk   rd   rc   r   )r
  r  rc   r  )r  r  r  r  rc   rS   )r   r  r   r   rc   r!  )
r  r  r  r  r-  r   r.  rJ   rc   rS   )rK   rJ   rL   rJ   r   rM   rN  rJ   rO  rM   rP  rM   rQ  rS   r  r  r  r  r-  r   rc   rI   )rk   rd   rf  r   rc   rg  )r   rI   rc   rm   )rk   rd   rp  r  rc   rm   )r  r  rc   rM   )Hr  
__future__r   r  r:  r8  r  rv   r>  r   rg   r   collectionsr   dataclassesr   r   r   r   r	   pathlibr
   typingr   r   r   scipy.statsr   homeBASEDBrb  ra  r  rv  r`  r@  r   r   r   r   r   r  r  r  r  rI   rl   ro   r{   r   r   r   r   r   r   r   r   r   r	  r  r  r,  rM  re  r  r  r  r  r  r^   r  r4   r9   r7   <module>r     sw    # " " " " "          				  



 # # # # # # * * * * * * * * . . . . . . . . . .       * * * * * * * * * * ! ! ! ! ! !ty{{Y)L8		 uQ{{	M     *8#+/ 9 65/	 	 	 !!55}5556	c

&
&
(
())* 
 ##&b&bOa&b&b&bb]]]JJJ  $       &   ) ) ) )   % % % %&G G G G= = = =
b b b b   (! ! ! !H1 1 1 1, =A& & & & &R" " " "J   D    . . . .   / / / />: : : :~ CGQ Q Q Q Qh# # # #LNO NO NO NOb   2    & z
*TTVV

 r9   