Ë
    KµCjP  ã                   ó¤   — d Z ddlmZ ddlZddlZddlmZ ddl	m
Z
  ee«      Z ed«      Zddddddddddddd	œZg d
¢Z G d„ d«      Z e«       Zy)uC  
Feature vector builder.

Converts (district, crop, month) into the exact numeric feature vectors
each model was trained on. This is the single source of truth for
feature order and meaning â€” if you change this, you MUST retrain every
model that consumes it, because XGBoost/RandomForest/DecisionTree have
no concept of column names at inference time, only column position.

The historical climate stats CSV referenced here is produced by the
ml_pipeline/feature_engineering scripts and must be present in
data/processed/ before the API can serve real (non-fallback) features.
é    )ÚPathN)Ú
get_logger)Úreference_dataz data/processed/climate_clean.csvé   é   )é   é   é   é	   é
   é   é   r   r   é   é   é   )Úrainfall_mmÚtemp_cÚhumidityÚseason_indexÚrainfall_anomalyÚrainfall_ma3Úrainfall_lag1Úwater_req_mmÚ
min_temp_cÚ
max_temp_cÚdrought_tolerantÚgrowth_daysc                   ód   — e Zd Zdd„Zdd„Zdd„Zdededefd„Z	ded	edede
j                  fd
„Zy)ÚFeatureBuilderÚreturnNc                 ó    — d | _         d| _        y )NF)Ú_climate_historyÚ_loaded©Úselfs    úIC:\Crop_Prediction\Backend\crop-ai-system\app\services\feature_builder.pyÚ__init__zFeatureBuilder.__init__/   s   € Ø59ˆÔØˆ�ó    c                 óø   — t         j                  «       sAt        j                  t         › d�«       t	        j
                  g d¢¬«      | _        d| _        y t	        j                  t         «      | _        d| _        y )Nu¥    not found â€” feature builder will use fallback climate estimates. Real predictions require this file to be generated by the ml_pipeline before going to production.)ÚdistrictÚmonthr   r   r   )ÚcolumnsT)	ÚCLIMATE_HISTORY_PATHÚexistsÚloggerÚwarningÚpdÚ	DataFramer"   Úread_csvr#   r$   s    r&   ÚloadzFeatureBuilder.load3   sf   € Ü#×*Ñ*Ô,Ü�N‰NÜ'Ð(ð )Qð Rôô
 %'§L¡LÚRô%ˆDÔ!ð ˆ�ô %'§K¡KÔ0DÓ$EˆDÔ!àˆ�r(   c                 ó2   — | j                   st        d«      ‚y )NzQFeatureBuilder used before load() was called. This indicates a startup-order bug.)r#   ÚRuntimeErrorr$   s    r&   Ú_ensure_loadedzFeatureBuilder._ensure_loadedB   s    € Ø�|Š|Üð6óð ð r(   r*   r+   c                 ó†  — | j                   | j                   d   |k(  | j                   d   |k(  z     }|j                  r"t        j                  d|› d|› d�«       dddd	œS t	        |d
   j                  «       «      d|v rt	        |d   j                  «       «      ndd|v rt	        |d   j                  «       «      d	œS dd	œS )zKReturns mean rainfall/temp/humidity for this district+month across history.r*   r+   z)No historical climate data for district='z' month=z, using generic fallback valuesg      Y@g      >@g     €Q@)r   r   r   r   r   r   )r"   Úemptyr/   r0   ÚfloatÚmean)r%   r*   r+   Úhists       r&   Ú_historical_climatez"FeatureBuilder._historical_climateI   så   € à×$Ñ$Ø×"Ñ" :Ñ.°(Ñ:Ø×$Ñ$ WÑ-°Ñ6ñ8ñ
ˆð �:Š:ä�N‰NØ;¸H¸:ÀXÈeÈWð U0ð 1ôð $)°DÀdÑKÐKä   mÑ!4×!9Ñ!9Ó!;Ó<Ø6>À$Ñ6F”e˜D ™N×/Ñ/Ó1Ô2ÈDØ:DÈÑ:Lœ˜d :Ñ.×3Ñ3Ó5Ó6ñ
ð 	
ð SWñ
ð 	
r(   Úcropc                 ód  — | j                  «        t        j                  |«      }t        j                  |«       | j	                  ||«      }|dkD  r|dz
  nd}| j	                  ||«      }|d   }|d   |z   dz  }	d}
t
        j                  |d«      }t        j                  |d   |d   |d   ||
|	||d	   |d
   |d   t        |d   «      |d   gt        j                  ¬«      }|j                  d   t        t        «      k7  r,t        d|j                  d   › dt        t        «      › d�«      ‚|S )u  
        Builds the feature vector for a single (district, crop, month) query.
        Raises UnsupportedCropError / UnsupportedDistrictError via
        reference_data if either input is invalid â€” callers should let
        that propagate, not catch it here.
        r   r   r   r   g        r   r   r   r   r   r   r   r   )ÚdtypezFeature vector length z does not match expected z columns)r7   r   Úget_cropÚget_districtr=   Ú
SEASON_MAPÚgetÚnpÚarrayr:   Úfloat64ÚshapeÚlenÚFEATURE_COLUMNSr6   )r%   r*   r>   r+   Ú
crop_propsÚcurrentÚ
prev_monthÚprevr   r   r   r   Úvectors                r&   ÚbuildzFeatureBuilder.build\   s[  € ð 	×ÑÔä#×,Ñ,¨TÓ2ˆ
Ü×#Ñ# HÔ-à×*Ñ*¨8°UÓ;ˆà"'¨!¢)�U˜Q’Y°ˆ
Ø×'Ñ'¨°*Ó=ˆà˜]Ñ+ˆØ Ñ.°Ñ>À!ÑCˆð Ðä!—~‘~ e¨QÓ/ˆä—‘Ø�MÑ"Ø�HÑØ�JÑØØØØØ�~Ñ&Ø�|Ñ$Ø�|Ñ$Ü�*Ð/Ñ0Ó1Ø�}Ñ%ð
ô —‘ôˆð �<‰<˜‰?œc¤/Ó2Ò2ô Ø(¨¯©°a©Ð(9ð :Ü¤Ó0Ð1°ð;óð ð
 ˆr(   )r    N)Ú__name__Ú
__module__Ú__qualname__r'   r4   r7   ÚstrÚintÚdictr=   rE   ÚndarrayrP   © r(   r&   r   r   .   sP   „ óóóð
¨Cð 
¸ð 
Àó 
ð&5˜cð 5¨ð 5°Sð 5¸R¿Z¹Zô 5r(   r   )Ú__doc__Úpathlibr   ÚnumpyrE   Úpandasr1   Úapp.core.logging_configr   Úapp.services.reference_datar   rQ   r/   r-   rC   rJ   r   Úfeature_builderrX   r(   r&   ú<module>r`      ss   ðñõ ã Û å .Ý 6á	�HÓ	€áÐ>Ó?Ð ð
 	ˆQ�1˜Ø	ˆq�a˜AØˆQ�1˜ñ€
ò€÷cñ cñN !Ó"�r(   