Mercurial > hg > nsaunier > traffic-intelligence
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 |
