Ë
    B|Gj×=  ã                   óx  — d Z ddlmZ ddlZddlZddlZddlm	Z	 ddl
mZ  e	e«      Zd„ Z e«       Zddeded	ed
eeef   fd„Zd
efd„Z e«       Z	 ddededed
eeef   fd„Zdedej0                  d
eeef   fd„Zdedej0                  d
eeef   fd„Zdeded	eded
eeef   f
d„Zdededed
eeef   fd„Zy)u`  
Individual model inference functions.

Critical production principle: if Model 3 (yield) throws an exception,
the user should still get results from Models 1, 2, 4, 5, 6 â€” degraded,
clearly labeled, but not a total failure. A farmer asking about climate
risk shouldn't get a generic 500 error because the market price model
had a transient issue.

Every function here catches its own exceptions and returns a
"degraded" output with status flags, rather than raising. The orchestrator
(aggregator.py) decides what to do with partial failures â€” these
functions just guarantee they never crash the caller.
é    )ÚAnyN)Ú
get_logger)ÚModelRegistryc            
      óž  — dd l } dd l}|j                  j                  |j                  j	                  |j                  j                  t        «      ddddd«      «      }h d£}	 t        |«      5 }| j                  |«      j                  «       }d d d «       t        D �cg c]	  }||vsŒ|‘Œ c}«      S # 1 sw Y   Œ'xY wc c}w #  g cY S xY w)Nr   ú..ÚdataÚlookupú
crops.json>   ú	guar seedú
dry gingerú
pome fruitúcitrus fruitúpulses totalúother cerealsúsmall milletsúoilseeds totalúother oilseedsútotal foodgrainúother rabi pulsesúother kharif pulsesúother summer pulsesúpeas & beans (pulses)úother cereals & milletsÚkorraÚmestaÚsamaiÚvaraguÚsannhamp)ÚjsonÚosÚpathÚnormpathÚjoinÚdirnameÚ__file__ÚopenÚloadÚkeysÚsorted)r   r    r!   ÚEXCLUDEÚfÚ	all_cropsÚcs          úGC:\Crop_Prediction\Backend\crop-ai-system\app\services\model_runners.pyÚ_load_crop_candidatesr/      s«   € ßØ�7‰7×Ñ˜BŸG™GŸL™L¨¯©¯©¼Ó)BÀDÈ$ÐPVÐX`ÐbnÓoÓp€Dò	€GðÜ�$‹Zð 	,˜1ØŸ	™	 !›×)Ñ)Ó+ˆI÷	,ä )Ö@˜Q¨q¸Ò/?’qÒ@ÓAÐA÷	,ð 	,üâ@øðØŠ	ús6   Á$C Á/ B5ÂC Â 	CÂ*CÂ.C Â5B>Â:C ÃCÚregistryÚdistrictÚmonthÚreturnc                 óÖ  — 	 | j                  d«      }|j                  |«      }|€!t        j                  d|› d�«       d d ddddœS d}t        j                  j                  |«      rt        j                  |«      nt        j                  «       }|j                  s||d	   |k(  |d
   |k(  z     nt        j                  «       }|j                  �s1t        t        |d   j                  «       «      d«      }d|j                  v r&t        t        |d   j                  «       «      d«      nd }	d|j                  v r&t        t        |d   j                  «       «      d«      nd }
||d	   |k(     }|j                  st        |d   j                  «       «      n|}|j                  st        |d   j                  «       «      nd}||z
  |dz   z  }t        |«      dkD  rdnt        |«      dkD  rdnd}||	|
t        |d«      |ddœS t        |j!                  d¬«      j"                  d   «      }|j$                  j&                  dd  }t)        |«      rt        t+        j                  |«      «      n|}||z
  |dz   z  }|dkD  rdn|dk  rdnd}t        |d«      d t        t        |«      d«      |ddœS # t,        $ r0}t        j/                  d|› d |› �d¬!«       d d dddd"d#œcY d }~S d }~ww xY w)$NÚsarimax_climatez/No SARIMAX climate model trained for district='ú'ç        ÚunknownT)Úforecast_rainfall_mmÚforecast_temp_cÚanomaly_scoreÚanomaly_labelÚdegradedz data/processed/climate_clean.csvr1   r2   Úrainfall_mmé   Útemp_cÚhumidityg      ð?ç•Ö&è.>g      ø?Úhighg      è?ÚmoderateÚlowé   F)r9   r:   rA   r;   r<   r=   )Ústepsr   iôÿÿÿç333333Ó?g333333Ó¿Únormalz-Climate model inference failed for district='ú': ©Úexc_infoÚclimate_model_failed)r9   r:   r;   r<   r=   Úerror)ÚgetÚloggerÚwarningr    r!   ÚexistsÚpdÚread_csvÚ	DataFrameÚemptyÚroundÚfloatÚmeanÚcolumnsÚstdÚabsÚforecastÚilocr   ÚendogÚlenÚnpÚ	ExceptionrN   )r0   r1   r2   Úsarimax_modelsÚmodelÚ	hist_pathÚhist_dfÚdmÚrainfallr@   rA   ÚdaÚann_meanÚann_stdÚzÚalabelr]   Úrecent_windowÚ	hist_meanÚanomalyÚlabelÚexcs                         r.   Úrun_climate_modelrs   3   sÚ  € ð8
Ø'Ÿ|™|Ð,=Ó>ˆØ×"Ñ" 8Ó,ˆØˆ=Ü�N‰NÐLÈXÈJÐVWÐXÔYà(,Ø#'Ø!$Ø!*Ø ñð ð 7ˆ	Ü,.¯G©G¯N©N¸9Ô,E”"—+‘+˜iÔ(Ì2Ï<É<Ë>ˆØY`×YfÒYfˆW�g˜jÑ)¨8Ñ3¸ÀÑ8HÈ%Ñ8OÑPÒQÔln×lxÑlxÓlzˆà�x‹xÜœU 2 mÑ#4×#9Ñ#9Ó#;Ó<¸aÓ@ˆHØ?GÈ2Ï:É:Ñ?U”uœU 2 h¡<×#4Ñ#4Ó#6Ó7¸Ô;Ð[_ˆFØAKÈrÏzÉzÑAY”uœU 2 j¡>×#6Ñ#6Ó#8Ó9¸1Ô=Ð_cˆHØ˜ Ñ,¨hÑ6Ñ7ˆBØ>@¿hºh”u˜R Ñ.×3Ñ3Ó5Ô6ÈHˆHØ>@¿hºh”u˜R Ñ.×2Ñ2Ó4Ô5ÈCˆGØ˜HÑ$¨°4©Ñ8ˆAÜ" 1›v¨š|‘V¼sÀ1»vÈº}±ÐRWˆFà(0Ø(.Ø(0Ü(-¨a°«Ø(.Ø(-ñð ô ˜Ÿ™¨a˜Ó0×5Ñ5°aÑ8Ó9ˆØŸ
™
×(Ñ(¨¨Ð.ˆÜ58¸Ô5G”Eœ"Ÿ'™' -Ó0Ô1ÈXˆ	Ø˜iÑ'¨I¸Ñ,<Ñ=ˆØ! Cš-‘°gÀ²n©UÈ(ˆä$)¨(°AÓ$6Ø#Ü"¤5¨£>°1Ó5Ø"Øñ
ð 	
øô ò 	
Ü�‰ÐDÀXÀJÈcÐRUÐQVÐWÐbfˆÔgà$(Ø#Ø Ø&ØØ+ñ
õ 	
ûð	
ús,   ‚AJ/ ÁF;J/ ÈB+J/ Ê/	K(Ê8%K#ËK(Ë#K(c            
      óX  — dd l } dd l}|j                  j                  |j                  j	                  |j                  j                  t        «      ddddd«      «      }	 t        |«      5 }t        | j                  |«      «      cd d d «       S # 1 sw Y   y xY w#  t        «       cY S xY w)Nr   r   r   r	   ztrained_crops.json)
r   r    r!   r"   r#   r$   r%   r&   Úsetr'   )r   r    r!   r+   s       r.   Ú_load_trained_cropsrv   o   s€   € ßØ�7‰7×Ñ˜BŸG™GŸL™L¨¯©¯©¼Ó)BÀDÈ$ÐPVÐX`ÐbvÓwÓx€DðÜ�$‹Zð 	%˜1Ü�t—y‘y “|Ó$÷	%÷ 	%ò 	%ûðÜ‹uŠús*   Á B Á+BÂ	B ÂBÂB ÂB ÂB)Úcropc           
      ó   — 	 dd l }dd l}|j                  j                  |j                  j	                  |j                  j                  t        «      ddddd«      «      }	 t        |«      5 }|j                  |«      }d d d «       j                  |r|j                  «       ndi «      }	|	j                  |r|j                  «       ndd «      }
|
�|
d   }|dd	gd
ddœS 	 |r$t        r|j                  «       t        vrdddgd
dœS | j                  d«      }|d   |d   }}|j                  |j!                  dd«      «      d   }t#        t%        j&                  |«      «      }|j)                  |g«      d   }|j                  dg «      }g }t+        |d«      r>|r<|j,                  }t/        t1        ||«      d„ d¬«      }|d d D ��cg c]  \  }}|‘Œ	 }}}t3        |«      t5        t7        |j9                  «       «      d«      |d
dœS # 1 sw Y   �ŒŠxY w# t        $ r#}t        j                  d|› �«       Y d }~�Œ[d }~ww xY wc c}}w # t        $ r,}t        j;                  d|› �d¬«       d d!g dd"d#œcY d }~S d }~ww xY w)$Nr   r   r   r	   zdistrict_crop_suitability.jsonÚ Úsuitabilitygffffffî?Útnau_ground_truthFÚtnau_district_data)rq   Ú
confidenceÚtop_factorsr=   Úsourcez/Could not load district_crop_suitability.json: Únot_suitablegÍÌÌÌÌÌì?Úno_training_data)rq   r}   r~   r=   Úxgb_feasibilityrd   Úlabel_encoderr?   éÿÿÿÿÚfeature_colsÚfeature_importances_c                 ó   — | d   S )Nr?   © )Úxs    r.   ú<lambda>z'run_feasibility_model.<locals>.<lambda>§   s
   € È!ÈAÉ$€ ó    T©ÚkeyÚreverserF   g®Gáz®ï?z$Feasibility model inference failed: rK   r8   r7   Úfeasibility_model_failed)rq   r}   r~   r=   rN   )r   r    r!   r"   r#   r$   r%   r&   r'   rO   Úlowerrb   rP   rQ   Ú_TRAINED_CROPSÚpredict_probaÚreshapeÚintra   ÚargmaxÚinverse_transformÚhasattrr†   r)   ÚzipÚstrÚminrX   ÚmaxrN   )r0   Úfeature_vectorrw   r1   Ú_jsonÚ_osÚ
_suit_pathÚ_fÚ
_suit_dataÚ_district_dataÚ
_crop_dataÚ_suit_labelÚ_eÚbundlerd   rƒ   ÚprobaÚidxrq   r…   r~   ÚimportancesÚrankedÚnameÚ_rr   s                             r.   Úrun_feasibility_modelr­   z   sŒ  € ð:
÷ 	(Ø—X‘X×&Ñ& s§x¡x§}¡}°S·X±X×5EÑ5EÄhÓ5OÐQUÐW[Ð]cÐemð  pPó  (Qó  Rˆ
ð	SÜ�jÓ!ð , RØ"ŸZ™Z¨›^�
÷,à'Ÿ^™^Á¨H¯N©NÔ,<ÈbÐRTÓUˆNØ'×+Ñ+¹D¨D¯J©J¬LÀbÈ$ÓOˆJØÐ%Ø(¨Ñ7�à(Ø"&Ø$7Ð#8Ø %Ø2ñð ð &ñ •N t§z¡z£|¼>Ñ'Ià'Ø"Ø 2Ð3Ø!ñ	ð ð —‘Ð/Ó0ˆØ% g™°°Ñ0Gˆ}ˆà×#Ñ# N×$:Ñ$:¸1¸bÓ$AÓBÀ1ÑEˆÜ”"—)‘)˜EÓ"Ó#ˆØ×/Ñ/°°Ó6°qÑ9ˆà—z‘z .°"Ó5ˆØ!#ˆÜ�5Ð0Ô1±lØ×4Ñ4ˆKÜœC ¨kÓ:ÁÐX\Ô]ˆFØ/5°b°q¨z×:¡G D¨!š4Ð:ˆKÑ:ô ˜“ZÜœe E§I¡I£KÓ0°$Ó7ÐS^Øñ
ð 	
÷M,ñ ,ûô ò 	SÜ�N‰NÐLÈRÈDÐQ×RÒRûð	Süó. ;øô ò 
Ü�‰Ð;¸C¸5ÐAÈDˆÔQàØØØØ/ñ
õ 	
ûð
úst   ‚AI Á!H Á,HÁ>AH Ã&I ÄCI ÇIÇ3I ÈHÈH È	H?ÈH:È4I È:H?È?	I É	I=É!I8É2I=É8I=rœ   c                 óv  — 	 | j                  d«      }|d   }t        |j                  |j                  dd«      «      d   «      }|dk  rt        j                  d|› d�«       d}t        |d	«      t        |d
z  d	«      dddœS # t        $ r,}t        j                  d|› �d¬«       ddddddœcY d }~S d }~ww xY w)NÚ	xgb_yieldrd   r?   r„   r   z)Yield model produced negative prediction z, clamping to 0r7   é   ç333333Ã?ztonnes per hectareF)Úexpected_yield_ton_haÚuncertainty_ton_haÚunitr=   zYield model inference failed: TrK   Úyield_model_failed)r²   r³   r´   r=   rN   )	rO   rX   Úpredictr“   rP   rQ   rW   rb   rN   )r0   rœ   r¦   rd   Úpredrr   s         r.   Úrun_yield_modelr¸   º   sÕ   € ð
Ø—‘˜kÓ*ˆØ�w‘ˆÜ�U—]‘] >×#9Ñ#9¸!¸RÓ#@ÓAÀ!ÑDÓEˆà�!Š8ô �N‰NÐFÀtÀfÈOÐ\Ô]ØˆDô &+¨4°£^Ü"'¨¨t©°QÓ"7ð )Øñ
ð 	
øô ò 
Ü�‰Ð5°c°UÐ;ÀdˆÔKà%(Ø"%Ø(ØØ)ñ
õ 	
ûð
ús   ‚B B Â	B8Â!B3Â-B8Â3B8c           	      óœ  — 	 | j                  d«      }|d   }|j                  |j                  dd«      «      d   }|j                  |j                  dd«      «      d   }t	        |«      d t        t        t        j                  |«      «      d«      ddœS # t        $ r,}t        j                  d	|› �d
¬«       dd dd
ddœcY d }~S d }~ww xY w)NÚdt_trendrd   r?   r„   r   rF   F)ÚtrendÚsloper}   r=   zTrend model inference failed: TrK   r8   r7   Útrend_model_failed)r»   r¼   r}   r=   rN   )rO   r¶   r“   r’   r™   rW   rX   ra   r›   rb   rP   rN   )r0   rœ   r¦   rd   r·   r§   rr   s          r.   Úrun_trend_modelr¾   Ù   sÕ   € ð
Ø—‘˜jÓ)ˆØ�w‘ˆð �}‰}˜^×3Ñ3°A°rÓ:Ó;¸AÑ>ˆØ×#Ñ# N×$:Ñ$:¸1¸bÓ$AÓBÀ1ÑEˆô ˜“YØÜ¤¤b§f¡f¨U£mÓ 4°aÓ8Øñ	
ð 	
øô ò 
Ü�‰Ð5°c°UÐ;ÀdˆÔKàØØØØ)ñ
õ 	
ûð
ús   ‚BB Â	CÂ!CÃ CÃCÚexclude_cropc           
      óœ  — 	 | j                  d«      }|d   }|j                  dt        |j                  «      «      }d|v r|j                  d«      }n1d|v r|j                  d«      }nt        j                  d«       g ddd	œS g }	d
d l}
d
d l}d
d l}|j                  j                  |j                  j                  |j                  j                  t        «      ddddd«      «      }|j                  j                  |j                  j                  |j                  j                  t        «      ddddd«      «      }	 t        |«      5 }|
j                  |«      }d d d «       |j!                  |«      }t#        ||d   |k(     d   j%                  «       «      }t&        D �]  }||k(  rŒ
j                  |i «      }|j                  dd
«      }|j                  dd«      }||cxk  r|k  sn ŒN	  ||||«      }|j)                  |j+                  dd«      «      d
   }d|v rt#        ||   «      }n`d|v r|j                  d«      n|}d|v r|j                  d«      nd}t#        ||   «      }|d
k\  rt#        ||   «      nd
}t-        ||z
  d«      }|	j/                  |t-        |d«      d dœ«       �Œ t5        |	d„ d¬«      d d  }d|v} || d!œS # 1 sw Y   �ŒsxY w#  i }d}Y �ŒIxY w# t0        $ r&}t        j3                  d|› d|› �«       Y d }~�Œpd }~ww xY w# t0        $ r*}!t        j                  d"|!› �d¬#«       g dd$d	œcY d }!~!S d }!~!ww xY w)%NÚrf_recommendationrd   ÚclassesrC   Úmediumz7rf_recommendation model has no usable suitability classTÚ"recommendation_model_misconfigured)Úalternativesr=   rN   r   r   r   r	   r
   Ú	processedzclimate_clean.csvr1   r@   g      <@Ú
min_temp_cÚ
max_temp_cé2   r?   r„   rE   rF   )rw   ÚscoreÚreasonz(Recommendation scoring failed for crop='rJ   c                 ó   — | d   S )NrÊ   rˆ   )Úrs    r.   rŠ   z*run_recommendation_model.<locals>.<lambda>6  s
   € ¨q°©z€ r‹   rŒ   é   )rÅ   r=   z'Recommendation model inference failed: rK   Úrecommendation_model_failed)rO   ÚlistÚclasses_ÚindexrP   rN   r   r    Úpandasr!   r"   r#   r$   r%   r&   r'   rT   rX   rY   Ú"CROP_CANDIDATES_FOR_RECOMMENDATIONr’   r“   rW   Úappendrb   rQ   r)   )"r0   r1   r2   Úbuild_feature_fnr¿   r¦   rd   rÂ   Ú	score_idxÚresultsr�   rž   Ú_pdÚ_crops_pathÚ_climate_pathr    Ú_crops_dataÚ_climate_dfÚ_district_tempÚcandidate_cropÚ_propsÚ_min_tÚ_max_tÚvecr§   rÊ   Ú
medium_idxÚlow_idxÚmedium_scoreÚ	low_scoreÚ	inner_excrª   r=   rr   s"                                     r.   Úrun_recommendation_modelré   ö   sP  € ð>^Ø—‘Ð1Ó2ˆØ�w‘ˆØ—*‘*˜Y¬¨U¯^©^Ó(<Ó=ˆð �WÑØŸ™ fÓ-‰IØ˜Ñ ØŸ™ hÓ/‰Iä�L‰LÐRÔSØ$&°DÐCgÑhÐhàˆ÷ 	7Ó6Ø—h‘h×'Ñ'¨¯©¯©°c·h±h×6FÑ6FÄxÓ6PÐRVÐX\Ð^dÐfnÐp|Ó(}Ó~ˆØŸ™×)Ñ)¨#¯(©(¯-©-¸¿¹×8HÑ8HÌÓ8RÐTXÐZ^Ð`fÐhsð  vIó  +Jó  Kˆð	"Ü�kÓ"ð - bØ#Ÿj™j¨›n�÷-àŸ,™, }Ó5ˆKÜ" ;¨{¸:Ñ/FÈÑ/PÑ#QÐRZÑ#[×#`Ñ#`Ó#bÓcˆNô
 Aó 	ˆNØ Ò-ØØ —_‘_ ^°RÓ8ˆFØ—Z‘Z ¨aÓ0ˆFØ—Z‘Z ¨bÓ1ˆFØ˜nÔ6°Ô6ØðÙ& x°ÀÓG�Ø×+Ñ+¨C¯K©K¸¸2Ó,>Ó?ÀÑB�Ø˜WÑ$Ü   yÑ!1Ó2‘5ð <DÀwÑ;N §¡¨hÔ 7ÐT]�:Ø5:¸gÑ5E˜WŸ]™]¨5Ô1È2�7Ü"'¨¨jÑ(9Ó":�<Ø8?À1ºœu U¨7¡^Ô4È!�9Ü  °	Ñ!9¸1Ó=�5Ø—‘¨ÄÀuÈaÃÐ\`ÑaÖbð)	ô2 ˜Ñ%9À4ÔHÈÈ!ÐLˆØ Ð(ˆØ &°HÑ=Ð=÷G-ñ -ûð	"ØˆKØ!‹Nûô. ò Ü—‘Ð!IÈ.ÐIYÐY\Ð]fÐ\gÐhÔiÝûðûô ò ^Ü�‰Ð>¸s¸eÐDÈtˆÔTØ "°Ð?\Ñ]Õ]ûð^ús�   ‚BL ÂB:L Ä?K Å
KÅ>K ÆAL Ç/C K&Ê/L ËKËK ËK#Ë L Ë&	LË/LÌ
L ÌLÌL Ì	MÌ!MÍ MÍMc           
      ó0  — 	 ddl m}  |||«      }|€	d d dddddœS |d   }|d   }|d	   }|d
   }||z
  |dz   z  }	|	dkD  rd}
n
|	dkD  rd}
nd}
||||d|
|d   |d   ddœ	S # t        $ r-}t        j	                  d|› �d¬«       d d dddddœcY d }~S d }~ww xY w)Nr   )Ú	get_pricer8   u:   Market price unavailable â€” no recent data for this crop.T)Úprice_forecast_per_quintalÚprice_per_kgÚdemand_levelÚprice_volatilityÚmessager=   Úmodal_price_per_kgÚmin_price_per_kgÚmax_price_per_kgÚmodal_price_per_quintalrB   rH   rC   r±   rD   rE   r   ÚdateF)	rì   rí   rò   ró   rî   rï   r   rõ   r=   zMarket model failed: rK   zMarket price unavailable.)Ú!app.services.market_price_servicerë   rb   rP   rN   )r0   r1   rw   rë   Ú
price_dataÚmodal_kgÚmin_kgÚmax_kgÚmodal_quintalÚ
spread_pctÚ
volatilityrr   s               r.   Úrun_market_modelrþ   <  s  € ð0
Ý?Ù˜t XÓ.ˆ
àÐà.2Ø"&Ø"+Ø$-ØWØ ñð ð #Ð#7Ñ8ˆØ"Ð#5Ñ6ˆØ"Ð#5Ñ6ˆØ"Ð#<Ñ=ˆð ˜v‘o¨(°T©/Ñ:ˆ
Ø˜ÒØ‰JØ˜$ÒØ#‰JàˆJð +8Ø&Ø &Ø &Ø(Ø *Ø! (Ñ+Ø! &Ñ)Øñ

ð 
	
øô ò 	
Ü�‰Ð,¨S¨EÐ2¸TˆÔBà*.Ø"Ø'Ø )Ø2Øñ
õ 	
ûð	
ús#   ‚A œAA Á	BÁ("BÂ
BÂB)é   )ry   ry   )Ú__doc__Útypingr   Únumpyra   rÓ   rS   r    Úapp.core.logging_configr   Úapp.models_loader.registryr   Ú__name__rP   r/   rÔ   r™   r”   Údictrs   ru   rv   r‘   r­   Úndarrayr¸   r¾   ré   rþ   rˆ   r‹   r.   ú<module>r     sv  ðñõ ã ß å .Ý 4á	�HÓ	€òñ, &;Ó%<Ð "ñ9
 ð 9
¸ð 9
ÀSð 9
ÐQUÐVYÐ[^ÐV^ÑQ_ó 9
ðx˜Só ñ %Ó&€ð NPñ=
Øð=
Ø36ð=
ØGJð=
à	ˆ#ˆsˆ(�^ó=
ð@
˜mð 
¸R¿Z¹Zð 
ÈDÐQTÐVYÐQYÉNó 
ð>
˜mð 
¸R¿Z¹Zð 
ÈDÐQTÐVYÐQYÉNó 
ð:E^ØðE^àðE^ð ðE^ð
 ðE^ð 
ˆ#ˆsˆ(�^óE^ðL3
Øð3
Ø'*ð3
Ø25ð3
à	ˆ#ˆsˆ(�^ô3
r‹   