
    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    77BGGLL)BD$PVX`bnopD	G$Z 	,1		!))+I	,)@Qq/?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   i333333?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,=NNLXJVWXY(,#'!$!*   7	,.GGNN9,E"++i(2<<>Y`YfYfWgj)838H%8OPQlnlxlxlzxxU2m#4#9#9#;<a@H?G2::?UuU2h<#4#4#67;[_FAKrzzAYuU2j>#6#6#891=_cH,h67B>@hhuR.3356HH>@hhuR.2245CGH$48A"1v|Vs1v}RWF(0(.(0(-a(.(-  a055a89

((.585GE"''-01X	i'I,<=!C-gnU($)(A$6#"5>15"
 	
  	
DXJcRUQVWbf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    77BGGLL)BD$PVX`bvwxD$Z 	%1tyy|$	% 	% 	%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   gGz?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   :
 	(XX&&sxx}}SXX5E5Eh5OQUW[]cem  pP  (Q  R
	Sj! ,R"ZZ^
,'^^HNN,<bRTUN'++DDJJLb$OJ%(7("&$7#8 %2  & Ntzz|>'I'" 23!	  /0%g0G}##N$:$:1b$AB1E"))E"#//6q9zz."5!#501l44KCk:X\]F/5bqz:GD!4:K: ZeEIIK0$7S^
 	
M, ,  	SNNLRDQRR	S. ;  
;C5AD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 NNFtfO\]D &+4^"'tQ"7 )
 	
  
5cU;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3Ar:;A>##N$:$:1b$AB1E YbffUm 4a8	
 	
  
5cU;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_c2   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LLRS$&DCghh 	76hh''chh6F6Fx6PRVX\^dfnp|(}~))#((--8H8H8RTXZ^`fhs  vI  +J  K	"k" -b#jjn-,,}5K";{:/F/P#QRZ#[#`#`#bcN
 A 	N- __^R8FZZa0FZZb1Fn66&xG++CKK2,>?BW$ y!125 <Dw;Nh 7T]:5:g5EW]]5127"'j(9":<8?1uU7^4!9 	!91=5ua\`ab)	2 %94H!L( &H==G- -	"K!N.  !I.IYY\]f\ghi  ^>seDt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
?tX.
.2"&"+$-W   ##78"#56"#56"#<= vo(T/:
J$#JJ +8& & &( *!(+!&)

 
	
  	
,SE2T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
QUVY[^V^Q_ 9
xS  %& NP=
=
36=
GJ=
	#s(^=
@
m 
RZZ 
DQTVYQYN 
>
m 
RZZ 
DQTVYQYN 
:E^E^E^ E^
 E^ 
#s(^E^L3
3
'*3
253
	#s(^3
r   