comparison trafficintelligence/pavement.py @ 1028:cc5cb04b04b0

major update using the trafficintelligence package name and install through pip
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Fri, 15 Jun 2018 11:19:10 -0400
parents python/pavement.py@933670761a57
children c6cf75a2ed08
comparison
equal deleted inserted replaced
1027:6129296848d3 1028:cc5cb04b04b0
1 #! /usr/bin/env python
2 '''Tools for processing and analyzing pavement marking data'''
3
4 from trafficintelligence import utils
5
6 import numpy as np
7
8
9 paintTypes = {0: "Non-existant",
10 1: "Eau",
11 2: "Epoxy",
12 3: "Alkyde",
13 4: "Autre"}
14
15 durabilities = {1: 98, #96 to 100
16 2: 85, #75 to 96
17 3: 62, #50 to 75
18 4: 32, #15 to 50
19 5: 7 #0 to 15
20 }
21
22 roadFunctionalClasses = {40: "Collectrice",
23 20: "Nationale",
24 30: "Regionale",
25 10: "Autoroute",
26 60: "Acces ressources",
27 51: "Local 1",
28 52: "Local 2",
29 53: "Local 3",
30 15: "Aut (PRN)",
31 25: "Nat (PRN)",
32 70: "Acces isolees",
33 99: "Autres"}
34
35 def caracteristiques(rtss, maintenanceLevel, rtssWeatherStation, fmr, paintType):
36 '''Computes characteristic data for the RTSS (class rtss)
37 maintenanceLevel = pylab.csv2rec('C:\\Users\Alexandre\Desktop\Projet_maitrise_recherche\BDD_access\\analyse_donnees_deneigement\\exigence_circuits.txt', delimiter = ';')
38 rtssWeatherStation = pylab.csv2rec('C:\\Users\Alexandre\Desktop\Projet_maitrise_recherche\stations_environnement_canada\\rtssWeatherStation\juste_pour_rtss_avec_donnees_entretien_hiv\\rtssWeatherStation_EC3.txt', delimiter = ',')
39 fmr = pylab.csv2rec('C:\\Users\Alexandre\Desktop\Projet_maitrise_recherche\BDD_access\\analyse_donnees_deneigement\\fmr.txt', delimiter = ';')
40 paintType = pylab.csv2rec('C:\\Users\Alexandre\Desktop\Projet_maitrise_recherche\BDD_access\\analyse_donnees_deneigement\\type_peinture.txt', delimiter = ';')
41 '''
42 # determination exigence deneigement
43 if rtss.id in maintenanceLevel['rtss_debut']:
44 for i in range(len(maintenanceLevel)):
45 if maintenanceLevel['rtss_debut'][i] == rtss.id:
46 exigence = maintenanceLevel['exigence'][i]
47 else:
48 exigence = ''
49
50 # determination x/y
51 if rtss.id in rtssWeatherStation['rtss']:
52 for i in range(len(rtssWeatherStation)):
53 if rtssWeatherStation['rtss'][i] == rtss.id:
54 x_moy = rtssWeatherStation['x_moy'][i]
55 y_moy = rtssWeatherStation['y_moy'][i]
56 else:
57 x_moy, y_moy = '',''
58
59 # determination info fmr
60 age_revtm, classe_fonct, type_revtm, milieu, djma, pourc_camions, vit_max = [], [], [], [], [], [], []
61 if rtss.id in fmr['rtss_debut']:
62 for i in range(len(fmr)):
63 if fmr['rtss_debut'][i] == rtss.id:
64 age_revtm.append(fmr['age_revtm'][i])
65 classe_fonct.append(fmr['des_clasf_fonct'][i])
66 type_revtm.append(fmr['des_type_revtm'][i])
67 milieu.append(fmr['des_cod_mil'][i])
68 djma.append(fmr['val_djma'][i])
69 pourc_camions.append(fmr['val_pourc_camns'][i])
70 vit_max.append(fmr['val_limt_vitss'][i])
71 age_revtm = utils.mostCommon(age_revtm)
72 classe_fonct = utils.mostCommon(classe_fonct)
73 type_revtm = utils.mostCommon(type_revtm)
74 milieu = utils.mostCommon(milieu)
75 djma = utils.mostCommon(djma)
76 vit_max = utils.mostCommon(vit_max)
77 if vit_max < 0:
78 vit_max = ''
79 pourc_camions = utils.mostCommon(pourc_camions)
80 if pourc_camions == "" or pourc_camions < 0:
81 djma_camions = ""
82 else:
83 djma_camions = pourc_camions*djma/100
84 else:
85 age_revtm, classe_fonct, type_revtm, milieu, djma, djma_camions, vit_max = '','','','','','',''
86
87 # determination type peinture
88 peinture_rd, peinture_rg, peinture_cl = [], [], []
89 peinture_lrd, peinture_lrg, peinture_lc = 0,0,0
90 if rtss.id in paintType['rtss_debut_orig']:
91 for i in range(len(paintType)):
92 if paintType['rtss_debut_orig'][i] == rtss.id:
93 peinture_rd.append((paintType['peinture_rd'][i]))
94 peinture_rg.append((paintType['peinture_rg'][i]))
95 peinture_cl.append((paintType['peinture_cl'][i]))
96 peinture_lrd = utils.mostCommon(peinture_rd)
97 peinture_lrg = utils.mostCommon(peinture_rg)
98 peinture_lc = utils.mostCommon(peinture_cl)
99 else:
100 peinture_lrd, peinture_lrg, peinture_lc = '','',''
101
102 return (exigence, x_moy, y_moy, age_revtm, classe_fonct, type_revtm, milieu, djma, djma_camions, vit_max, peinture_lrd, peinture_lrg, peinture_lc)
103
104 def winterMaintenanceIndicators(data, startDate, endDate, circuitReference, snowThreshold):
105 '''Computes several winter maintenance indicators
106 data = entretien_hivernal = pylab.csv2rec('C:\\Users\Alexandre\Documents\Cours\Poly\Projet\mesures_entretien_hivernal\mesures_deneigement.txt', delimiter = ',')'''
107 import datetime
108 somme_eau, somme_neige, somme_abrasif, somme_sel, somme_lc, somme_lrg, somme_lrd, compteur_premiere_neige, compteur_somme_abrasif = 0,0,0,0,0,0,0,0,0
109
110 if circuitReference in data['ref_circuit']:
111 for i in range(len(data)):
112 if data['ref_circuit'][i] == circuitReference and (data['date'][i] + datetime.timedelta(days = 6)) <= endDate and (data['date'][i] + datetime.timedelta(days = 6)) > startDate:
113 compteur_premiere_neige += float(data['premiere_neige'][i])
114 somme_neige += float(data['neige'][i])
115 somme_eau += float(data['eau'][i])
116 somme_abrasif += float(data['abrasif'][i])
117 somme_sel += float(data['sel'][i])
118 somme_lc += float(data['lc'][i])
119 somme_lrg += float(data['lrg'][i])
120 somme_lrd += float(data['lrd'][i])
121 compteur_somme_abrasif += float(data['autre_abrasif_binaire'][i])
122 if compteur_premiere_neige >= 1:
123 premiere_neige = 1
124 else:
125 premiere_neige = 0
126 if compteur_somme_abrasif >= 1:
127 autres_abrasifs = 1
128 else:
129 autres_abrasifs = 0
130 if somme_neige < snowThreshold:
131 neigeMTQ_sup_seuil = 0
132 else:
133 neigeMTQ_sup_seuil = 1
134 else:
135 somme_eau, somme_neige, somme_abrasif, somme_sel, somme_lc, somme_lrg, somme_lrd, premiere_neige, autres_abrasifs, neigeMTQ_sup_seuil = '','','','','','','','','',''
136
137 return (somme_eau, somme_neige, neigeMTQ_sup_seuil, somme_abrasif, somme_sel, somme_lc, somme_lrg, somme_lrd, premiere_neige, autres_abrasifs)
138
139 def weatherIndicators(data, startDate, endDate, snowThreshold, weatherDatatype, minProportionMeasures = 0.):
140 '''Computes the indicators from Environment Canada files
141 (loaded as a recarray using csv2rec in data),
142 between start and end dates (datetime.datetime objects)
143
144 weatherDataType is to indicate Environnement Canada data ('ec') or else MTQ
145 minProportionMeasures is proportion of measures necessary to consider the indicators'''
146 from matplotlib.mlab import find
147 nbre_jours_T_negatif,nbre_jours_gel_degel,pluie_tot,neige_tot,ecart_type_T = 0,0,0,0,0
148 compteur,nbre_jours_gel_consecutifs=0,0
149 tmoys = []
150 seuils_T = [20,15,10,5]
151 deltas_T = [0,0,0,0]
152 startIndex = find(data['date'] == startDate)
153 nDays = int((endDate - startDate).days)+1
154 if len(startIndex) > 0 and startIndex+nDays <= len(data):
155 startIndex = startIndex[0]
156 for i in range(startIndex, startIndex+nDays):
157 if not np.isnan(data['tmax'][i]):
158 tmax = data['tmax'][i]
159 else:
160 tmax = None
161 if not np.isnan(data['tmin'][i]):
162 tmin = data['tmin'][i]
163 else:
164 tmin = None
165 if weatherDatatype == 'ec':
166 if data['pluie_tot'][i] is not None and not np.isnan(data['pluie_tot'][i]):
167 pluie_tot += data['pluie_tot'][i]
168 if data['neige_tot'][i] is not None and not np.isnan(data['neige_tot'][i]):
169 neige_tot += data['neige_tot'][i]
170 if tmax is not None:
171 if tmax < 0:
172 nbre_jours_T_negatif += 1
173 if tmax is not None and tmin is not None:
174 if tmax > 0 and tmin < 0:
175 nbre_jours_gel_degel += 1
176 for l in range(len(seuils_T)):
177 if tmax - tmin >=seuils_T[l]:
178 deltas_T[l] += 1
179 if not np.isnan(data['tmoy'][i]):
180 tmoys.append(data['tmoy'][i])
181 if tmax is not None:
182 if tmax < 0:
183 compteur += 1
184 elif tmax >= 0 and compteur >= nbre_jours_gel_consecutifs:
185 nbre_jours_gel_consecutifs = compteur
186 compteur = 0
187 else:
188 compteur = 0
189 nbre_jours_gel_consecutifs = max(nbre_jours_gel_consecutifs,compteur)
190 if len(tmoys) > 0 and float(len(tmoys))/nDays >= minProportionMeasures:
191 if tmoys != []:
192 ecart_type_T = np.std(tmoys)
193 else:
194 ecart_type = None
195 if neige_tot < snowThreshold:
196 neigeEC_sup_seuil = 0
197 else:
198 neigeEC_sup_seuil = 1
199 return (nbre_jours_T_negatif,nbre_jours_gel_degel, deltas_T, nbre_jours_gel_consecutifs, pluie_tot, neige_tot, neigeEC_sup_seuil, ecart_type_T)
200 else:
201 return [None]*2+[[None]*len(seuils_T)]+[None]*5
202
203 def mtqWeatherIndicators(data, startDate, endDate,tmax,tmin,tmoy):
204 print("Deprecated, use weatherIndicators")
205 from matplotlib.mlab import find
206 nbre_jours_T_negatif,nbre_jours_gel_degel,ecart_type_T = 0,0,0
207 compteur,nbre_jours_gel_consecutifs=0,0
208 tmoys = []
209 seuils_T = [20,15,10,5]
210 deltas_T = [0,0,0,0]
211 startIndex = find(data['date'] == startDate)
212 nDays = (endDate - startDate).days+1
213 for i in range(startIndex, startIndex+nDays):
214 if tmax[i] < 0:
215 nbre_jours_T_negatif += 1
216 if tmax[i] > 0 and tmin[i] < 0:
217 nbre_jours_gel_degel += 1
218 for l in range(len(seuils_T)):
219 if tmax[i] - tmin[i] >=seuils_T[l]:
220 deltas_T[l] += 1
221 tmoys.append(tmoy[i])
222 if tmax[i] < 0:
223 compteur += 1
224 elif tmax[i] >= 0 and compteur >= nbre_jours_gel_consecutifs:
225 nbre_jours_gel_consecutifs = compteur
226 compteur = 0
227 else:
228 compteur = 0
229 nbre_jours_gel_consecutifs = max(nbre_jours_gel_consecutifs,compteur)
230 if tmoys != []:
231 ecart_type_T = np.std(tmoys)
232 else:
233 ecart_type = None
234
235 return (nbre_jours_T_negatif,nbre_jours_gel_degel, deltas_T, nbre_jours_gel_consecutifs, ecart_type_T)
236
237 class RTSS(object):
238 '''class for data related to a RTSS:
239 - agregating pavement marking measurements
240 - RTSS characteristics from FMR: pavement type, age, AADT, truck AADT
241 - winter maintenance level from V155
242
243 If divided highway, the RTSS ends with G or D and are distinct: there is no ambiguity
244 - retroreflectivity types: there are CB, RJ and RB
245 If undivided, ending with C
246 - durability is fine: ETAT_MARQG_RG ETAT_MARQG_CL ETAT_MARQG_RD (+SG/SD, but recent)
247 - retroreflectivity: CJ is center line, RB and SB are left/right if DEBUT-FIN>0 or <0
248 '''
249
250 def __init__(self, _id, name, data):
251 self.id = _id
252 self.name = name
253 self.data = data
254
255 class MarkingTest(object):
256 '''class for a test site for a given product
257
258 including the series of measurements over the years'''
259
260 def __init__(self, _id, paintingDate, paintingType, color, data):
261 self.id = _id
262 self.paintingDate = paintingDate
263 self.paintingType = paintingType
264 self.color = color
265 self.data = data
266 self.nMeasures = len(data)
267
268 def getSite(self):
269 return int(self.id[:2])
270
271 def getTestAttributes(self):
272 return [self.paintingType, self.color, self.paintingDate.year]
273
274 def plot(self, measure, options = 'o', dayRatio = 1., **kwargs):
275 from matplotlib.pyplot import plot
276 plot(self.data['jours']/float(dayRatio),
277 self.data[measure], options, **kwargs)
278
279 def getMarkingMeasures(self, dataLabel):
280 nonZeroIndices = ~np.isnan(self.data[dataLabel])
281 return self.data[nonZeroIndices]['jours'], self.data[nonZeroIndices][dataLabel]
282
283 def plotMarkingMeasures(self, measure, options = 'o', dayRatio = 1., **kwargs):
284 for i in range(1,7):
285 self.plot('{}_{}'.format(measure, i), options, dayRatio, **kwargs)
286
287 def computeMarkingMeasureVariations(self, dataLabel, lanePositions, weatherData, snowThreshold, weatherDataType = 'ec', minProportionMeasures = 0.):
288 '''Computes for each successive measurement
289 lanePositions = None
290 measure variation, initial measure, time duration, weather indicators
291
292 TODO if measurements per lane, add a variable for lane position (position1 to 6)
293 lanePositions = list of integers (range(1,7))
294 measure variation, initial measure, time duration, lane position1, weather indicators
295 measure variation, initial measure, time duration, lane position2, weather indicators
296 ...'''
297 variationData = []
298 if lanePositions is None:
299 nonZeroIndices = ~np.isnan(self.data[dataLabel])
300 days = self.data[nonZeroIndices]['jours']
301 dates = self.data[nonZeroIndices]['date_mesure']
302 measures = self.data[nonZeroIndices][dataLabel]
303 for i in range(1, len(dates)):
304 nDaysTNegative, nDaysThawFreeze, deltaTemp, nConsecutiveFrozenDays, totalRain, totalSnow, snowAboveThreshold, stdevTemp = weatherIndicators(weatherData, dates[i-1], dates[i], snowThreshold, weatherDataType, minProportionMeasures)
305 if dates[i-1].year+1 == dates[i].year:
306 winter = 1
307 if days[i-1]<365:
308 firstWinter = 1
309 else:
310 winter = 0
311 firstWinter = 0
312 variationData.append([measures[i-1]-measures[i], measures[i-1], days[i]-days[i-1], days[i-1], winter, firstWinter, nDaysTNegative, nDaysThawFreeze] + deltaTemp + [nConsecutiveFrozenDays, totalRain, totalSnow, snowAboveThreshold, stdevTemp])
313 return variationData