## Consigner et calculer les paires de lectures de faible résistance

Utilisez `blank-readings.csv` pour garder les lectures réelles et leur contexte ; remplacez `FILL_REAL_ID` par l’identifiant de l’échantillon. Les trois lignes de `demo-readings.csv` sont fictives, sans mesure MTTJ ni échantillon d’acceptation. `kelvin_pair_calc.py` calcule résistance et offset pour chaque paire de courants et tensions signés.

Le script Python fonctionne hors ligne avec la bibliothèque standard, sans paquet supplémentaire. Il ne commande pas d’instrument, ne valide pas le circuit sec et ne décide pas de l’acceptation. Vérifiez séparément hypothèses et spécification produit selon l’article.

## Les 16 colonnes d’entrée

Gardez les noms de colonnes. Le script calcule avec quatre colonnes de lectures signées et conserve les autres comme contexte, sans vérifier leurs valeurs.

| Colonne | Signification et unité |
| --- | --- |
| `sample_id` | Identifiant de l’échantillon de la ligne |
| `sample_state` | État de l’échantillon lors de la mesure |
| `spec_revision` | Révision de spécification utilisée |
| `sense_A_B_drawing_ref` | Référence du schéma des points Sense A/B |
| `fixture_id` | Identifiant du montage d’essai |
| `method` | Méthode consignée ; les modèles utilisent `four_wire_current_pair` |
| `range` | Gamme de mesure de l’instrument |
| `source_limit_mV` | Limite de tension source consignée, en mV |
| `sample_history` | Historique, y compris essais mécaniques, environnementaux ou électriques précédents |
| `i_plus_mA` | Courant réel signé de la lecture positive, en mA ; supérieur à 0 pour calculer |
| `i_minus_mA` | Courant réel signé de la lecture négative, en mA ; inférieur à 0 pour calculer |
| `v_plus_uV` | Tension signée mesurée avec `i_plus_mA`, en μV |
| `v_minus_uV` | Tension signée mesurée avec `i_minus_mA`, en μV |
| `sampled_plus_at` | Heure de lecture positive, conservée comme texte |
| `sampled_minus_at` | Heure de lecture négative, conservée comme texte |
| `note` | Notes conservées avec la ligne d’origine |

Gardez les signes des courants et tensions. Zéro est une valeur de tension ; un champ vide est une lecture manquante qui doit rester vide. Si l’un des quatre champs est absent, vide ou ne contient que des espaces, le script ne remplace pas la valeur par zéro. Les champs de contexte vides le restent aussi.

## Calcul et quatre colonnes de sortie

Pour toute paire complète et valide :

`R = (V+ − V−) / (I+ − I−)`

`E = V+ − I+ R`

La seconde formule tire l’offset de `V = IR + E`. Des entrées en μV et mA donnent `R` en mΩ et `E` en μV. Le calcul suppose résistance linéaire et offset stable pendant la paire ; un résultat ne vérifie pas ces hypothèses. Les sorties utilisent au plus 12 chiffres significatifs.

| Colonne de sortie | Signification |
| --- | --- |
| `r_pair_mohm` | Résistance calculée en mΩ ; vide si paire manquante ou invalide |
| `offset_pair_uV` | Offset calculé en μV ; vide si paire manquante ou invalide |
| `calculation_status` | État du calcul : `calculated`, `missing` ou `invalid` |
| `calculation_note` | Explication de l’état et des hypothèses |

| État | Condition d’écriture |
| --- | --- |
| `calculated` | Quatre entrées numériques finies, courant positif supérieur à 0, courant négatif inférieur à 0 et deux résultats finis. Note exacte : `Assumes a linear resistor and stable offset. No acceptance judgment.` Elle suppose résistance linéaire et offset stable, sans jugement d’acceptation. |
| `missing` | Au moins une lecture absente ou vide. Deux sorties numériques vides. Note exacte : `Missing readings; no zero imputation.` Elle indique des lectures manquantes, sans remplacement par zéro. |
| `invalid` | Entrée non numérique ou non finie, signes de courant incorrects, ou résultat non fini. Deux sorties numériques vides ; la note précise la cause. |

Les notes exactes de `invalid` sont `Readings must be numeric.`, `Require finite readings and Iplus>0, Iminus<0.` ou `Non-finite calculated output.` Elles demandent des lectures numériques ou finies avec les signes indiqués, ou signalent une sortie non finie. États et notes décrivent le traitement du calcul, pas l’acceptation du produit.

## Lire les exemples fictifs

| Ligne | I+ / I− (mA) | V+ / V− (μV) | `r_pair_mohm` (mΩ) | `offset_pair_uV` (μV) | `calculation_status` |
| --- | --- | --- | ---: | ---: | --- |
| `DEMO_STABLE` | +10 / −10 | +110 / −90 | 10 | 10 | `calculated` |
| `DEMO_DRIFT` | +10 / −10 | +110 / −86 | 9.8 | 12 | `calculated` |
| `DEMO_UNEQUAL` | +12 / −8 | +130 / −70 | 10 | 10 | `calculated` |

L’exemple de dérive fait passer l’offset supposé de 10 à 14 μV entre lectures. Le calcul donne 9.8 mΩ et 12 μV d’offset. `calculated` ne détecte ni ne supprime cette dérive. Les courants inégaux réels signés +12 et −8 mA donnent 10 mΩ. Si les lectures du modèle vierge restent vides, les deux sorties numériques restent vides et l’état est `missing`.

## Calculer hors ligne et préserver l’entrée

Gardez script et CSV localement puis exécutez `python kelvin_pair_calc.py demo-readings.csv result.csv`. Pour les lectures réelles, utilisez le modèle rempli et un fichier de sortie distinct. Le script refuse les chemins d’entrée et de sortie qui se résolvent au même chemin afin de conserver l’entrée brute.

La sortie conserve les colonnes d’entrée et ajoute les quatre colonnes calculées. Si ces quatre noms existent déjà, leurs colonnes sont remplacées par les nouveaux calculs. Le résultat est un CSV UTF-8 avec marque d’ordre des octets. Les valeurs manquantes restent vides, sans décision conforme/non conforme.
