§
    Á^i 1  ã                  ó  — d dl mZ d dlmZ d dlmZ d dlmZmZm	Z	m
Z
 d dlZd dlZ ej        e¦  «        Ze                      ej        ¦   «         ¦  «         dd
„Zdd„Z G d„ d¦  «        Z e¦   «         Zdd„Zdd„ZdS )é    )Úannotations)Úfiles)ÚPath)ÚAnyÚDictÚOptionalÚUnionNÚvtúOptional[Union[str, int]]ÚreturnÚstrc                óà   — | €dS t          | t          ¦  «        rt          | ¦  «        S t          | ¦  «                             ¦   «                              ¦   «                              dd¦  «        S )a€  
    Normalize an observation type identifier (varType) into a canonical string.

    This function ensures that both satellite/platform identifiers (strings)
    and conventional observation codes (integers, i.e., *kx* values) are
    represented in a consistent, lowercase, hyphenated string form.

    Parameters
    ----------
    vt : str or int or None
        Observation type identifier.
        - If ``int`` (e.g., 120), it is returned as a string (``"120"``).
        - If ``str``, it is normalized: stripped, lowercased, and with
          underscores converted to hyphens.
        - If ``None``, returns an empty string.

    Returns
    -------
    str
        Normalized observation type identifier. Always a string.

    Examples
    --------
    >>> _normalize_vartype(120)
    '120'
    >>> _normalize_vartype("MetOp_B")
    'metop-b'
    >>> _normalize_vartype(None)
    ''
    NÚ Ú_ú-)Ú
isinstanceÚintr   ÚstripÚlowerÚreplace)r
   s    ú=/home/caroline.viezel/readDiagGerd/src/gsidiag/datasources.pyÚ_normalize_vartyper      s[   € ð> 
€zØˆrÝ�"•cÑÔð Ý�2‰wŒwˆÝˆr‰7Œ7�=Š=‰?Œ?× Ò Ñ"Ô"×*Ò*¨3°Ñ4Ô4Ð4ó    ÚvnúOptional[str]c                ó˜   — | €dS t          | ¦  «                             ¦   «                              ¦   «                              dd¦  «        S )aÆ  
    Normalize a variable or channel family name into a canonical string.

    This function standardizes variable names (e.g., "amsua", "uv", "t")
    to a consistent, lowercase, hyphenated format.

    Parameters
    ----------
    vn : str or None
        Variable or channel family name.
        - If ``str``, it is normalized: stripped, lowercased, and with
          underscores converted to hyphens.
        - If ``None``, returns an empty string.

    Returns
    -------
    str
        Normalized variable name. Always a string.

    Examples
    --------
    >>> _normalize_varname("Amsua")
    'amsua'
    >>> _normalize_varname("uv_wind")
    'uv-wind'
    >>> _normalize_varname(None)
    ''
    Nr   r   r   )r   r   r   r   )r   s    r   Ú_normalize_varnamer   4   s>   € ð: 
€zØˆrÝˆr‰7Œ7�=Š=‰?Œ?× Ò Ñ"Ô"×*Ò*¨3°Ñ4Ô4Ð4r   c                  ó<   — e Zd ZdZddd„Zdd„Zdd„Zdd„Zdd„ZdS )ÚDataSourcesInfoa¯  Parser and accessor for observation metadata defined in ``table.yml``.

    The YAML is expected to have the following structure:

    ```yaml
    observations:
      - kx: <platform_or_kx>        # e.g., "n19", "metop-b", "120"
        details:
          - var: <variable>         # e.g., "amsua", "uv", "t"
            abbreviation: <str>     # short label for legends
            instrument: <str>       # human-friendly instrument/platform description
            color: <hex>            # e.g., "#1f77b4"
            symbol: <str>           # plotting symbol, e.g., "x", "s", "*"
            iuse: "<-1|0|1|2>"      # keep as string for compatibility with existing code
    ```
    NÚ	yaml_fileúOptional[str | Path]r   ÚNonec           	     ó"  — i }d}|�gt          |¦  «        }t                               d|¦  «         |                     d¬¦  «        }t	          j        |¦  «        pi }t          |¦  «        }�n^	 t          d¦  «        dz  }t                               d|¦  «         |                     d¬¦  «        }t	          j        |¦  «        pi }d	}�n # t          t          t          f$ ræ}t                               d
|¦  «         t          t          ¦  «                             d¦  «        }|                     ¦   «         s0t                               dt          ¦  «         t          d¦  «        |‚t                               d|¦  «         |                     d¬¦  «        }t	          j        |¦  «        pi }t          |¦  «        }Y d}~nd}~ww xY wt                               dt!          |                     dg ¦  «        pg ¦  «        |pd¦  «         i | _        |                     dg ¦  «        pg D �])}	|	                     dd¦  «        }
t          |
¦  «                             ¦   «         }|st                               d|	¦  «         ŒX| j                             |i ¦  «        }|	                     dg ¦  «        pg }|st                               d|¦  «         d}|D ]`}t          |                     dd¦  «        ¦  «                             ¦   «         }|st                               d||¦  «         ŒV|||<   |dz  }Œat                               d||¦  «         �Œ+t-          d„ | j                             ¦   «         D ¦   «         ¦  «        }t                               dt!          | j        ¦  «        |¦  «         i | _        | j                             ¦   «         D ]9\  }}	 t5          |¦  «        }n# t6          t8          f$ r |}Y nw xY w|| j        |<   Œ:dS )a‡  Load observation metadata from the packaged YAML table.
    
        Parameters
        ----------
        yaml_file : str | Path | None
            Optional custom path to a YAML file. When `None`, the loader tries:
            (1) `importlib.resources.files("gsidiag") / "table.yml"` (works in wheels),
            then (2) a sibling `table.yml` next to this module as a fallback.
        r   Nz3Attempting to load table.yml from explicit path: %szutf-8)ÚencodingÚgsidiagz	table.ymlz)Attempting to load packaged table.yml: %szpkg://gsidiag/table.ymlzGPackaged resource not available (%s). Falling back to sibling table.ymlz2Missing 'table.yml' alongside %s and not packaged.zgMissing 'table.yml' inside installed package 'gsidiag'. Make sure build config includes this data file.zLoading sibling table.yml: %sz$Loaded %d observation groups from %sÚobservationsz	<unknown>Úkxz%Skipping observation without 'kx': %rÚdetailszkx=%s has no 'details' entriesr   Úvarz*Skipping detail without 'var' in kx=%s: %ré   z'Registered kx=%s with %d detail entriesc              3  ó4   K  — | ]}t          |¦  «        V — Œd S ©N)Úlen)Ú.0Úvs     r   ú	<genexpr>z+DataSourcesInfo.__init__.<locals>.<genexpr>¸   s(   è è € Ð?Ð? Q�#˜a™&œ&Ð?Ð?Ð?Ð?Ð?Ð?r   z9Built lookup with %d platforms (kx) and %d (kx,var) pairs)r   ÚloggerÚdebugÚ	read_textÚyamlÚ	safe_loadr   r   ÚFileNotFoundErrorÚModuleNotFoundErrorÚAttributeErrorÚ__file__Ú	with_nameÚis_fileÚerrorÚinfor-   ÚgetÚlookupr   ÚwarningÚ
setdefaultÚsumÚvaluesÚtabÚitemsr   Ú
ValueErrorÚ	TypeError)Úselfr    ÚdataÚsource_descÚyml_pathÚtextÚresÚeÚsiblingÚobsÚraw_kxr'   ÚbucketÚdetails_listÚcountÚdetailr)   Útotal_pairsÚkx_strÚmappingÚkx_keys                        r   Ú__init__zDataSourcesInfo.__init__h   s,  € ð  "ˆØˆàÐ Ý˜I‘”ˆHÝ�LŠLÐNÐPXÑYÔYÐYØ×%Ò%¨wÐ%Ñ7Ô7ˆDÝ”> $Ñ'Ô'Ð-¨2ˆDÝ˜h™-œ-ˆK‰Kð+Ý˜IÑ&Ô&¨Ñ4�Ý—’ÐHÈ#ÑNÔNÐNØ—}’}¨g�}Ñ6Ô6�Ý”~ dÑ+Ô+Ð1¨r�Ø7�‘øÝ%Õ':½NÐKð +ð +ð +å—’Ø]Øñô ð õ �x™.œ.×2Ò2°;Ñ?Ô?�Ø—’Ñ(Ô(ð Ý—L’LØLÝ ñô ð õ ,ðJñô ð ðõ —’Ð<¸gÑFÔFÐFØ×(Ò(°'Ð(Ñ:Ô:�Ý”~ dÑ+Ô+Ð1¨r�Ý! '™lœl������øøøøð'+øøøõ* 	�ŠØ2Ý�—’˜¨Ñ,Ô,Ð2°Ñ3Ô3ØÐ&˜;ñ	
ô 	
ð 	
ð =?ˆŒà—8’8˜N¨BÑ/Ô/Ð5°2ð 	Oñ 	OˆCØ—W’W˜T 2Ñ&Ô&ˆFÝ�V‘”×"Ò"Ñ$Ô$ˆBØð Ý—’ÐFÈÑLÔLÐLØà”[×+Ò+¨B°Ñ3Ô3ˆFØŸ7š7 9¨bÑ1Ô1Ð7°RˆLØð CÝ—’Ð=¸rÑBÔBÐBàˆEØ&ð ð �Ý˜&Ÿ*š* U¨BÑ/Ô/Ñ0Ô0×6Ò6Ñ8Ô8�Øð Ý—N’NÐ#OÐQSÐU[Ñ\Ô\Ð\ØØ$��s‘Ø˜‘
��å�LŠLÐBÀBÈÑNÔNÐNÑNåÐ?Ð?¨$¬+×*<Ò*<Ñ*>Ô*>Ð?Ñ?Ô?Ñ?Ô?ˆÝ�ŠØGÝ�”ÑÔØñ	
ô 	
ð 	
ð @BˆŒØ#œ{×0Ò0Ñ2Ô2ð 	'ð 	'‰OˆF�Gð Ý$'¨¡K¤K��øÝ¥	Ð*ð  ð  ð  Ø���ð øøøà&ˆDŒH�VÑÐð	'ð 	's,   Á/AC ÃG	Ã#CGÇG	ÏO+Ï+PÐ PÚvar_typer   Úvar_nameÚkeyc                ó²   — | j                              |i ¦  «                             |i ¦  «                             |d¦  «        }|dv rdnt          |¦  «        S )ax  Retrieve a metadata field from the lookup.

        Args:
            var_type: Observation type (e.g., "n19", "metop-a", "120").
            var_name: Variable name (e.g., "amsua", "uv", "t").
            key: Field to retrieve (e.g., "instrument", "abbreviation", "color").

        Returns:
            The field value as a string, or an empty string if not found.
        r   )Nr   )r?   r>   r   )rH   r[   r\   r]   Úvals        r   r>   zDataSourcesInfo.getÈ   sS   € ð Œk�oŠo˜h¨Ñ+Ô+×/Ò/°¸"Ñ=Ô=×AÒAÀ#ÀrÑJÔJˆØ˜JÐ&Ð&ˆrˆr­C°©H¬HÐ4r   ú	list[str]c                óN   — t          | j                             ¦   «         ¦  «        S )z8List all platforms/keys (``kx``) available in the table.)Úsortedr?   Úkeys)rH   s    r   Ú	platformszDataSourcesInfo.platformsÖ   s   € å�d”k×&Ò&Ñ(Ô(Ñ)Ô)Ð)r   c                óv   — t          | j                             |i ¦  «                             ¦   «         ¦  «        S )z;List variables available for a given ``var_type`` (``kx``).)rb   r?   r>   rc   )rH   r[   s     r   Úvariables_forzDataSourcesInfo.variables_forÚ   s,   € å�d”k—o’o h°Ñ3Ô3×8Ò8Ñ:Ô:Ñ;Ô;Ð;r   úDict[str, Any]c                óz   — t          | j                             |i ¦  «                             |i ¦  «        ¦  «        S )zHReturn the complete detail dict for a (``var_type``, ``var_name``) pair.)Údictr?   r>   )rH   r[   r\   s      r   rU   zDataSourcesInfo.detailÞ   s0   € å�D”K—O’O H¨bÑ1Ô1×5Ò5°hÀÑCÔCÑDÔDÐDr   r,   )r    r!   r   r"   )r[   r   r\   r   r]   r   r   r   )r   r`   )r[   r   r   r`   )r[   r   r\   r   r   rg   )	Ú__name__Ú
__module__Ú__qualname__Ú__doc__rZ   r>   rd   rf   rU   © r   r   r   r   V   s“   € € € € € ðð ð"^'ð ^'ð ^'ð ^'ð ^'ð@5ð 5ð 5ð 5ð*ð *ð *ð *ð<ð <ð <ð <ðEð Eð Eð Eð Eð Er   r   ÚvarTypeÚvarNameÚwhatc                óî  — t          | ¦  «        }t          |¦  «        }|pd                     ¦   «                              ¦   «         }	 t                               |||¦  «        }|r-t                               d||||¦  «         t          |¦  «        S n5# t          $ r(}t                               d||||¦  «         Y d}~nd}~ww xY w|dk    rši dd“dd	“d
d“dd“dd“dd“dd“dd“dd“dd“dd“dd“dd“d d!“d"d#“d$d%“d&d'“d(d)d*d+œ¥}|                     ||pd 
                    ¦   «         pd,¦  «        }	t          | ¦  «        › d-|	› �}
t                               d.|||
¦  «         |
S |d/v r/t          | ¦  «        }
t                               d0||||
¦  «         |
S |d1v r8|pd 
                    ¦   «         pd,}
t                               d0||||
¦  «         |
S t                               d2|||¦  «         dS )3a½  Return user-friendly metadata with YAML-first priority and robust fallbacks.

    Priority:
      1) ``table.yml`` (if an entry exists)
      2) Heuristics (e.g., "NOAA-19 AMSU-A" for ``n19``/``amsua``)

    This function never returns ``None``; it returns an empty string if nothing matches.

    Args:
        varType: Observation type identifier (e.g., "n19", "metop-b", "120").
        varName: Variable or channel family (e.g., "amsua", "uv", "t").
        what: Field to retrieve (case-insensitive), e.g., "instrument", "abbreviation",
            "platform", "sensor", "color", "symbol", "iuse".

    Returns:
        A string with the requested information, or an empty string if unknown.
    r   z%getVarInfo YAML hit: (%s,%s).%s -> %rz%YAML lookup failed for (%s,%s).%s: %sNÚ
instrumentÚamsuazAMSU-AÚamsubzAMSU-BÚairsÚAIRSÚiasiÚIASIÚhirsÚHIRSÚmhsÚMHSÚssmisÚSSMISÚatmsÚATMSÚcrisÚCrISzcris-fsrzCrIS FSRÚgomeÚGOMEÚmls30ÚMLSÚomiÚOMIÚsndrd1zGOES Sounder D1Úsndrd2zGOES Sounder D2Úsndrd3zGOES Sounder D3Úsndrd4zGOES Sounder D4z!Atmospheric Motion Vectors (AMVs)zGNSS-RO Bending AnglezGNSS-RO)ÚuvÚgps_bndÚgpsÚSENSORú z0getVarInfo fallback 'instrument' for (%s,%s): %s>   ÚplatformÚ	satellitez(getVarInfo fallback '%s' for (%s,%s): %s>   ÚsensorÚinstrument_namez-getVarInfo unknown field '%s' for (%s,%s): '')r   r   r   r   Ú_DS_INFOr>   r1   r2   r   Ú	ExceptionÚupperÚcanonical_platform)ro   rp   rq   Úvt_normÚvn_normr]   r_   rN   Ú
sensor_mapr•   Úouts              r   Ú
getVarInforŸ   ç   sá  € õ$ ! Ñ)Ô)€GÝ  Ñ)Ô)€GØˆ:�2×
Ò
Ñ
Ô
×
$Ò
$Ñ
&Ô
&€CðXÝ�lŠl˜7 G¨SÑ1Ô1ˆØð 	Ý�LŠLÐ@À'È7ÐTWÐY\Ñ]Ô]Ð]Ý�s‘8”8ˆOð	øõ ð Xð Xð XÝ�ŠÐ<¸gÀwÐPSÐUVÑWÔWÐWÐWÐWÐWÐWÐWøøøøðXøøøð ˆlÒÐð
Ø�Xð
à�Xð
ð �Fð
ð �Fð	
ð
 �Fð
ð �5ð
ð �Wð
ð �Fð
ð �Fð
ð ˜
ð
ð �Fð
ð �Uð
ð �5ð
ð Ð'ð
ð Ð'ð
ð  Ð'ð!
ð" Ð'ð#
ð$ 6Ø.Øð)
ð 
ð 
ˆ
ð, —’ ¨'¨-°R×)>Ò)>Ñ)@Ô)@Ð)LÀHÑMÔMˆÝ# GÑ,Ô,Ð7Ð7¨vÐ7Ð7ˆÝ�ŠÐGÈÐRYÐ[^Ñ_Ô_Ð_Øˆ
à
Ð'Ð'Ð'Ý  Ñ)Ô)ˆÝ�ŠÐ?ÀÀgÈwÐX[Ñ\Ô\Ð\Øˆ
à
Ð+Ð+Ð+Øˆ}˜"×#Ò#Ñ%Ô%Ð1¨ˆÝ�ŠÐ?ÀÀgÈwÐX[Ñ\Ô\Ð\Øˆ
õ ‡L‚LÐ@À#ÀwÐPWÑXÔXÐXØˆ2s   ÁA
B Â
CÂCÃCc                ó   — | €t                                d¦  «         dS t          | ¦  «                             ¦   «         }|                     ¦   «                              dd¦  «        }t          | t          ¦  «        s|                     ¦   «         r$d|› d�}t                                d| |¦  «         |S | 	                    d	¦  «        rG|d
d…                              ¦   «         r+d|d
d…         › �}t                                d| |¦  «         |S ddddœ}||v r&||         }t                                d| |¦  «         |S | 	                    d¦  «        rF| 
                    ¦   «                              dd¦  «        }t                                d| |¦  «         |S |                     ¦   «         pd}t                                d| |¦  «         |S )ak  Return a human-friendly platform name given a varType/kx.

    Examples
    --------
    "n19"     -> "NOAA-19"
    "n20"     -> "NOAA-20"
    "n21"     -> "NOAA-21"
    "npp"     -> "Suomi-NPP"
    "metop-a" -> "MetOp-A"
    "metop_b" -> "MetOp-B"
    120       -> "Conventional (kx=120)"
    "120"     -> "Conventional (kx=120)"
    None      -> "PLATFORM"
    Nz)canonical_platform: vt=None -> 'PLATFORM'ÚPLATFORMr   r   zConventional (kx=ú)z)canonical_platform: conventional %r -> %sÚnr*   zNOAA-z&canonical_platform: NOAA-like %r -> %sz	Suomi-NPPzNOAA-20zNOAA-21)ÚnppÚn20Ún21z#canonical_platform: mapped %r -> %sÚmetopÚMetopÚMetOpz'canonical_platform: MetOp-like %r -> %sz$canonical_platform: default %r -> %s)r1   r2   r   r   r   r   r   r   ÚisdigitÚ
startswithÚtitler™   )r
   Úv_rawr/   rž   rX   s        r   rš   rš   2  sÀ  € ð 
€zÝ�ŠÐ@ÑAÔAÐAØˆzå�‰GŒG�MŠM‰OŒO€EØ�Š‰Œ×Ò˜c 3Ñ'Ô'€Aõ �"•cÑÔð ˜aŸiši™kœkð Ø* %Ð*Ð*Ð*ˆÝ�ŠÐ@À"ÀcÑJÔJÐJØˆ
ð 	‡|‚|�CÑÔð ˜Q˜q˜r˜rœUŸ]š]™_œ_ð Ø�a˜˜˜”eˆoˆoˆÝ�ŠÐ=¸rÀ3ÑGÔGÐGØˆ
ð ØØðð €Gð
 	ˆG€|€|Ø�aŒjˆÝ�ŠÐ:¸BÀÑDÔDÐDØˆ
ð 	‡|‚|�GÑÔð Ø�gŠg‰iŒi×Ò ¨Ñ1Ô1ˆÝ�ŠÐ>ÀÀCÑHÔHÐHØˆ
à
�+Š+‰-Œ-Ð
%˜:€CÝ
‡L‚LÐ7¸¸SÑAÔAÐAØ€Jr   )r
   r   r   r   )r   r   r   r   )ro   r   rp   r   rq   r   r   r   )Ú
__future__r   Úimportlib.resourcesr   Úpathlibr   Útypingr   r   r   r	   Úloggingr4   Ú	getLoggerrj   r1   Ú
addHandlerÚNullHandlerr   r   r   r—   rŸ   rš   rn   r   r   ú<module>r¶      sL  ðØ "Ð "Ð "Ð "Ð "Ð "à %Ð %Ð %Ð %Ð %Ð %Ø Ð Ð Ð Ð Ð Ø -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ø €€€à €€€à	ˆÔ	˜8Ñ	$Ô	$€Ø × Ò Ð%�'Ô%Ñ'Ô'Ñ (Ô (Ð (ð#5ð #5ð #5ð #5ðL5ð 5ð 5ð 5ðDJEð JEð JEð JEð JEñ JEô JEð JEð\ ˆ?ÑÔ€ðHð Hð Hð HðV4ð 4ð 4ð 4ð 4ð 4r   