o
    X*j).                     @   s&  d Z ddlZddlZddlmZ ddlZdedefddZdejddfd	d
Z	g dZ
d"dedededefddZdedefddZ		d#dedededededejfddZ		d#dededededef
ddZdededefddZdedefddZ		d#dedededededefd d!ZdS )$u   
reader.py — Leitura de arquivos binários GrADS com TEMPLATE
Suporta: big-endian / little-endian, stream (direto) ou sequential (Fortran)
    N)datetimedtypereturnc                 C   s   t | dr	dS dS )zDtype do marcador de registro Fortran (4 bytes) com o mesmo endianness
    dos dados: arquivos BYTESWAPPED ("<f4") tem marcadores little-endian.<z<u4z>u4)str
startswithr    r	   =/dados/sismom/SisMOM/sismom_fig/Figuras_Eta/scripts/reader.py_marker_dtype   s   r   arrc                 C   sl   t ttj}tdt|d }tjdd tj| t| | |k < W d   dS 1 s/w   Y  dS )aC  Substitui valores UNDEF por NaN in-place.

    Usa tolerancia relativa ao magnitude do UNDEF (float32) para cobrir tanto
    o UNDEF padrao (9.99e20) quanto UNDEFs de grande magnitude negativa
    como -2.56E+33 (GPOSETA/BESM), onde a ULP do float32 e ~3e26 e a
    tolerancia fixa de 1e14 nunca identificaria o valor.
    g  ļBg-C6?ignore)invalidN)	floatnpfloat32configUNDEFmaxabserrstatenan)r   Zundef32tolr	   r	   r
   _mask_undef   s
   "r   )%Y%m%d%Hz%Y%d%Hz%Y%m%dr   data_dir	timestampfmtc                 C   s,   | |}tj | tj }tj| |S )z?Monta o nome do arquivo com um formato de timestamp especifico.)strftimer   FILE_PREFIXFILE_SUFFIXospathjoin)r   r   r   tagfnamer	   r	   r
   _build_filename,   s   
r&   c                 C   s   t tdd}|st| |d}tj|r|S dS |r(t| ||}tj|r(|S tD ]}||kr1q*t| ||}tj|rA|  S q*dS )a  
    Localiza o arquivo .bin para um dado timestamp.

    Estrategia:
      1. Usa config.FILE_TIMESTAMP_FMT (definido por file_timestamp no config.yaml)
      2. Fallback: tenta todos os formatos em _TIMESTAMP_FORMATS
    Retorna o caminho completo se encontrado, ou None.
    FILE_TIMESTAMP_FMTr    N)getattrr   r&   r!   r"   exists_TIMESTAMP_FORMATS)r   r   Zprimary_fmtfpathr   r	   r	   r
   _resolve_filename3   s    
r-   Fvar_name
sequentialc              
   C   s  t | |}|du r(|d}td| d |  d ttj d ttj d |p,tj}tjtj	}}|| }	|	d }
tj
| }t|d	M}|r~t|d
 D ]-}|d}|s_td| ttj|t|dd }||}|d ||kr||}qOn||
 }|| ||
}W d   n1 sw   Y  t||
k rtd| d| d|
 dt| tj||dtj}|||f}ttddr|dddddf }t| |S )u  
    Lê um campo 2D de uma variável em um dado instante.

    Parameters
    ----------
    data_dir   : diretório onde estão os arquivos .bin
    timestamp  : datetime do passo de tempo desejado
    var_name   : nome da variável (ex: 'TP2M')
    sequential : True se o arquivo tem marcadores Fortran (4 bytes antes/depois de cada campo)
    dtype      : override do dtype (default: config.DTYPE)

    Returns
    -------
    np.ndarray shape (NY, NX) com undef substituído por np.nan
    Nr   Arquivo nao encontrado para  em '' (prefixo=	, sufixo=)   rb   zFim inesperado do arquivo em r   r   zBytes insuficientes para 'z' em z: esperado z, lido YREVF)r-   r   FileNotFoundErrorreprr   r   r    DTYPENXNY	VAR_INDEXopenrangereadEOFErrorintr   
frombufferr   seeklen
ValueErrorastyper   reshaper)   r   )r   r   r.   r/   r   r,   r$   nxnynfloatsnbytesZvar_idxfiZrec_len_bytesrec_lenZ
data_bytesrawoffsetr   r	   r	   r
   
read_fieldS   sf   








rT   c                    s  t | |}|du r(|d}td| d |  d ttj d ttj d |p,tj}tjtj	  t
tdttj}|rg }t|d	<}t|D ]/}	ttj|d
t|dd }
||
}|d
 |tj||dtjf qOW d   n1 sw   Y  n1tj||d|  }j|k rtd| d tj d t|  fddt|D }i }tjD ]~}t|tr|d n|d }t|trt|ddpdnd}tj| }t
tdd}|dkr'g }t|D ]!}|||    }|r|dddddf }t!| || qtj"|dd||< q||   }|r;|dddddf }t!| |||< q|S )u   
    Lê todos os campos de um arquivo de uma vez (mais eficiente que leituras individuais).

    Returns
    -------
    dict {var_name: np.ndarray (NY, NX)}
    Nr   r0   r1   r2   r3   r4   NVARS_FIELDSr6   r5   r   r   zArquivo z tem z valores, esperado >= c                    s.   g | ]}|  |d      fqS )r7   )rJ   ).0rP   rM   rK   rL   Zraw_allr	   r
   
<listcomp>   s     z#read_all_fields.<locals>.<listcomp>namenlevr8   Fr9   )axis)#r-   r   r:   r;   r   r   r    r<   r=   r>   r)   rG   	VARIABLESr@   rA   rD   r   rE   rB   r   appendrI   r   rJ   fromfilesizerH   r   
isinstancedictgetr?   copyr   stack)r   r   r/   r   r,   r$   n_fieldsZall_rawrO   _rQ   rR   expectedresultvrY   rZ   idx_yrevarrskr   r	   rW   r
   read_all_fields   s~   


 

	

"


rn   c                 C   s   t | |duS )zLVerifica se o arquivo correspondente ao timestamp existe (qualquer formato).N)r-   )r   r   r	   r	   r
   file_exists   s   ro   c                    s    fddt jD S )z@Retorna lista de timestamps para os quais existem arquivos .bin.c                    s   g | ]	}t  |r|qS r	   )ro   )rV   tr   r	   r
   rX      s    z-list_available_timestamps.<locals>.<listcomp>)r   
TIMESTAMPSrq   r	   rq   r
   list_available_timestamps   s   rs   var_level_mapc                    s  t | |}|du r(|d}td| d |  d ttj d ttj d |p,tj}tjtj	 }|d }t
td	d
  fdd}	i }
|ri }| D ]!\}}tj| }|du rh|df||< qT|D ]
}||f||| < qjqTt
tdttj}i }t|dP}t|D ]@}ttj|dt|dd }||}|d ||v r|| \}}|	tj||d}|du r|||< q|||i |< qW d   |}
|
S 1 sw   Y  |}
|
S t|dY}| D ]K\}}tj| }|du r|||  ||}|	tj||d|
|< qi }|D ]}||| |  ||}|	tj||d||< q||
|< qW d   |
S 1 sDw   Y  |
S )aM  
    Le apenas os campos especificos solicitados (minimo uso de memoria).

    Ao inves de ler todos os nlev niveis de cada variavel 3D, le apenas os
    niveis necessarios para gerar as figuras (plot_levels).

    Parameters
    ----------
    var_level_map : dict
        {var_name: None}           -> variavel 2D: le 1 campo
        {var_name: [k0, k1, ...]}  -> variavel 3D: le apenas esses indices de nivel

    Returns
    -------
    dict:
        {var_name: np.ndarray(NY, NX)}       para vars 2D
        {var_name: {k: np.ndarray(NY, NX)}}  para vars 3D (k = indice do nivel)
    Nr   r0   r1   r2   r3   r4   r5   r8   Fc                    s>   |  tj }  r| d d dd d f } t|  | S )Nr9   )rI   r   r   rJ   rc   r   )r   rk   rK   rL   r	   r
   _clean  s   z%read_fields_selective.<locals>._cleanrU   r6   r   r   )r-   r   r:   r;   r   r   r    r<   r=   r>   r)   itemsr?   rG   r\   r@   rA   rD   r   rE   rB   r   
setdefaultrF   )r   r   rt   r/   r   r,   r$   rM   rN   rv   rh   ZneededvarZlevel_ksbaserm   re   tmprO   firQ   rR   Zlev_kr   Zlev_dictr	   ru   r
   read_fields_selective   s   



 









r}   )r   )FN)__doc__r!   numpyr   r   r   r   r   ndarrayr   r+   r&   r-   boolrT   ra   rn   ro   listrs   r}   r	   r	   r	   r
   <module>   sn    $
L
M	