mannnon commited on
Commit
cc55ec2
·
verified ·
1 Parent(s): d464ad9

Create zebris_extractor.py

Browse files
Files changed (1) hide show
  1. zebris_extractor.py +132 -0
zebris_extractor.py ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import io
2
+ import numpy as np
3
+ import pandas as pd
4
+
5
+
6
+ STANDARD_COLUMNS = [
7
+ "Nom",
8
+ "Date",
9
+ "Poids (kg)",
10
+ "Vitesse (km/h)",
11
+ "Cadence (pas/min)",
12
+ "Contact (%)",
13
+ "Flight (%)",
14
+ "Force talon G (N)",
15
+ "Force talon D (N)",
16
+ "Force avant-pied G (N)",
17
+ "Force avant-pied D (N)",
18
+ "Pression talon G (N/cm²)",
19
+ "Pression talon D (N/cm²)",
20
+ "COP G (mm)",
21
+ "COP D (mm)",
22
+ "Rotation G (°)",
23
+ "Rotation D (°)",
24
+ "Transition G (s)",
25
+ "Transition D (s)",
26
+ "Longueur foulée (cm)",
27
+ "Largeur pas (cm)",
28
+ ]
29
+
30
+
31
+ def _to_numeric(series):
32
+ return pd.to_numeric(
33
+ series.astype(str).str.replace(",", ".", regex=False),
34
+ errors="coerce"
35
+ )
36
+
37
+
38
+ def _read_csv_flex(uploaded_file):
39
+ raw = uploaded_file.read()
40
+ uploaded_file.seek(0)
41
+
42
+ for encoding in ["utf-8-sig", "utf-8", "latin1", "cp1252"]:
43
+ for sep in [",", ";", "\t"]:
44
+ try:
45
+ txt = raw.decode(encoding)
46
+ df = pd.read_csv(io.StringIO(txt), sep=sep)
47
+ if df.shape[1] > 1:
48
+ return df
49
+ except Exception:
50
+ pass
51
+
52
+ return pd.read_csv(uploaded_file)
53
+
54
+
55
+ def _pick(df, candidates):
56
+ for c in candidates:
57
+ if c in df.columns:
58
+ return c
59
+ return None
60
+
61
+
62
+ def extract_zebris_csv(uploaded_file):
63
+ df = _read_csv_flex(uploaded_file)
64
+
65
+ out = pd.DataFrame(index=df.index)
66
+ mapping = {}
67
+ manquantes = []
68
+
69
+ # Nom
70
+ first_name_col = _pick(df, ["Prénom", "First Name"])
71
+ last_name_col = _pick(df, ["Nom de famille", "Last Name"])
72
+ if first_name_col and last_name_col:
73
+ out["Nom"] = (
74
+ df[first_name_col].astype(str).str.strip() + " " +
75
+ df[last_name_col].astype(str).str.strip()
76
+ )
77
+ mapping["Nom"] = [first_name_col, last_name_col]
78
+ else:
79
+ out["Nom"] = "Inconnu"
80
+ manquantes.append("Nom")
81
+
82
+ # Mapping direct depuis ton CSV Zebris
83
+ direct_map = {
84
+ "Date": ["Measurement date", "Date"],
85
+ "Poids (kg)": ["Body weight [Kg]", "Weight (kg)", "Poids (kg)"],
86
+ "Vitesse (km/h)": ["Vitesse [km/h]", "Speed [km/h]", "Speed (km/h)"],
87
+ "Cadence (pas/min)": ["Cadence [pass/min]", "Cadence [pas/min]", "Cadence"],
88
+ "Contact (%)": ["Total contact [%]", "Contact [%]"],
89
+ "Flight (%)": ["Total flight [%]", "Flight [%]"],
90
+ "Force talon G (N)": ["Force maximale Heel (Three zones) Gauche [N]"],
91
+ "Force talon D (N)": ["Force maximale Heel (Three zones) Droite [N]"],
92
+ "Force avant-pied G (N)": ["Force maximale Forefoot (Three zones) Gauche [N]"],
93
+ "Force avant-pied D (N)": ["Force maximale Forefoot (Three zones) Droite [N]"],
94
+ "Pression talon G (N/cm²)": ["Pression maximale Heel (Three zones) Gauche [N/cm²]", "Pression maximale Heel (Three zones) Gauche [N/cm2]"],
95
+ "Pression talon D (N/cm²)": ["Pression maximale Heel (Three zones) Droite [N/cm²]", "Pression maximale Heel (Three zones) Droite [N/cm2]"],
96
+ "COP G (mm)": ["Longueur lors de la phase d'appui Gauche [mm]"],
97
+ "COP D (mm)": ["Longueur lors de la phase d'appui Droite [mm]"],
98
+ "Rotation G (°)": ["Rotation du pied Gauche [degré]"],
99
+ "Rotation D (°)": ["Rotation du pied Droite [degré]"],
100
+ "Transition G (s)": ["Instant du passage du talon vers l'avant-pied Gauche [s]"],
101
+ "Transition D (s)": ["Instant du passage du talon vers l'avant-pied Droite [s]"],
102
+ "Longueur foulée (cm)": ["Longueur de la foulée [cm]"],
103
+ "Largeur pas (cm)": ["Largeur du pas [cm]"],
104
+ }
105
+
106
+ for target, candidates in direct_map.items():
107
+ col = _pick(df, candidates)
108
+ if col is None:
109
+ out[target] = np.nan
110
+ manquantes.append(target)
111
+ else:
112
+ mapping[target] = col
113
+ if target == "Date":
114
+ out[target] = df[col]
115
+ else:
116
+ out[target] = _to_numeric(df[col])
117
+
118
+ # Garde seulement les lignes avec une vitesse
119
+ out = out[out["Vitesse (km/h)"].notna()].copy()
120
+
121
+ # Réordonne
122
+ out = out.reindex(columns=STANDARD_COLUMNS).reset_index(drop=True)
123
+
124
+ debug = {
125
+ "mapping": mapping,
126
+ "manquantes": manquantes,
127
+ "colonnes_csv": list(df.columns),
128
+ "nb_lignes_csv": len(df),
129
+ "nb_lignes_extractees": len(out),
130
+ }
131
+
132
+ return out, debug