{
"metadata": {
"name": "",
"signature": "sha256:d68cb32e45f35678915f231bca347651b613410e2ed13d276fe071647446d092"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Example Race Charts"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Quick sketches using the race data from https://prize.tatacommunications.com/home\n",
"\n",
"The aim of the competion, (I think) is to work with live timing feeds, but I'm more interested in being able to do analyses across the history of the session, which means building up timeseries and getting them represented usefully somehow."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**The top half of this notebook is a bit all over the place... My improved second thoughts being at the the \"*Starting Over* section**"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#Grab the data as parsed XML elements in a list\n",
"\n",
"race='data/F1 Race.txt'\n",
"\n",
"from lxml import etree\n",
"\n",
"pl=[]\n",
"for el in open(race, 'r'):\n",
" pl.append(etree.fromstring(el))"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#Column mappings for the timing screen\n",
"raceMap={\n",
" '1':'classpos',\n",
" '2':'racingNumber',\n",
" '3':'name',\n",
" '4':'gap',\n",
" '5':'interval',\n",
" '6':'laptime',\n",
" '7':'sector1',\n",
" '9':'sector2',\n",
" '11':'sector3',\n",
" '12':'pitlap',\n",
" '13':'pitcount'\n",
"}\n",
"\n",
"raceUnMap = { raceMap[k]: k for k in raceMap}\n",
"raceUnMap"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#Make use of row semantics (row is classification position)\n",
"#Generate a classification position/time datastructure for each driverNumber\n",
"\n",
"def parse_race_pos_all(r,pos,c):\n",
" '''r is data element; pos is dataframe; c is column'''\n",
" if r.attrib['identifier']=='101' and 'sessionstate' not in r[0].attrib:\n",
" cn=raceMap[c]\n",
" if r[0].attrib['column']==c:\n",
" tt=r.attrib['timestamp'].replace('.',':').split(':')\n",
" ttx=datetime.time(int(tt[0]),int(tt[1]),int(tt[2]),int(tt[3])*1000)#.strftime(\"%H:%M:%S:%f\")\n",
" pos=pd.concat([ pos,pd.DataFrame( {\n",
" cn:r[0].attrib['value'],\n",
" cn+\"_colour\":r[0].attrib['colour'],\n",
" \"pos\":r[0].attrib['row']\n",
" },index=[ttx]) ])\n",
" return pos\n",
"\n",
"#This is a bit quirkier - driverNumber over time for a particular classification number\n",
"def parse_race_pos_num(r,pos,c,p):\n",
" '''r is data element; pos is dataframe; c is column; p is position we're interested in'''\n",
" if r.attrib['identifier']=='101' and 'sessionstate' not in r[0].attrib:\n",
" cn=raceMap[c]\n",
" if r[0].attrib['column'] ==c and r[0].attrib['row'] ==p:\n",
" tt=r.attrib['timestamp'].replace('.',':').split(':')\n",
" ttx=datetime.time(int(tt[0]),int(tt[1]),int(tt[2]),int(tt[3])*1000)#.strftime(\"%H:%M:%S:%f\")\n",
" pos=pd.concat([ pos,pd.DataFrame( {cn:r[0].attrib['value'], cn+\"_colour\":r[0].attrib['colour']},index=[ttx]) ])\n",
" return pos\n"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import pandas as pd\n",
"\n",
"pnum=pd.DataFrame()\n",
"for l in pl:\n",
" pnum=parse_race_pos_all(l,pnum,raceUnMap['racingNumber'])\n",
"pnum['time'] = pnum.index\n",
"pnum['pos']=pnum['pos'].astype(int)\n",
"pnum=pnum[pnum.racingNumber!='']\n",
"pnum[:3]"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from ggplot import *\n",
"ggplot(pnum[pnum.pos<23],aes(x='time',y='pos',colour='racingNumber'))+geom_line()+ylim(0,23)"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"When it comes to working out laptimes, we maybe need to do some grouping. The *pandas* group by operation will let us group on a particular value, which would be one way. Or maybe we can chuck data into MongoDB and just *set* on a compound time/row key?\n",
"\n",
"Let's simplify the data stream to 101s as dicts and generate a unique key."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"plj=[]\n",
"for el in open(race, 'r'):\n",
" r=etree.fromstring(el)\n",
" d={}\n",
" for a in r.attrib: d[a]=r.attrib[a]\n",
" for a in r[0].attrib: d[a]=r[0].attrib[a]\n",
" if d['identifier']=='101' and 'row' in d and d['column'] in ['1','2','3','4','5','6','7','9','11','12','13']:\n",
" cn=raceMap[d['column']]\n",
" did= '_'.join([ d['row'],d['timestamp'].replace(':','_').replace('.','_') ])\n",
" dd={cn:d['value'], cn+\"_colour\":d['colour'],'id':did,'row': d['row'],'strtime':d['timestamp']}\n",
" plj.append(dd)\n",
"plj[:3]"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import pymongo\n",
"from pymongo import MongoClient\n",
"import json"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#Connect to the MongoDB server\n",
"conn = MongoClient('localhost', 27017)"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#Create a new database\n",
"db = conn.tataracedb"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"db.drop_collection('test1')"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#Create a new collection\n",
"collection = db.test1\n",
"collection"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"for i in plj:\n",
" collection.update({'_id':i['id']},{\"$set\":i},upsert=True)"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"collection.find_one()"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"results=collection.find({'$and': [ { 'racingNumber': '3' }, { 'gap': { '$exists': True } } ]})"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"results.count()"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"df=pd.DataFrame(list(results))\n",
"df[:3]"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def timeify(x):\n",
" x=x.replace(':','_').replace('.','_')\n",
" tt=x.split('_')\n",
" return datetime.time(int(tt[0]),int(tt[1]),int(tt[2]),int(tt[3])*1000)\n",
"\n",
"df['time']=df['strtime'].apply(lambda x: timeify(x))\n",
"ggplot(df,aes(x='time',y='gap'))+geom_line()"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"results=collection.find({'$and': [ \n",
" #{ 'racingNumber': { '$exists': True } },\n",
" { 'gap': { '$exists': True } },\n",
" { '$or': [ {'row':'2'}, {'row':'3'},{'row':'4'},{'row':'5'}]}\n",
" ]})\n",
"df=pd.DataFrame(list(results))\n",
"df['time']=df['strtime'].apply(lambda x: timeify(x))\n",
"df.gap=df.gap.convert_objects(convert_numeric=True)\n",
"#df.dropna(subset=['gap','racingNumber'],inplace=True)\n",
"ggplot(df,aes(x='time',y='gap',colour='row'))+geom_line()"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"df.gap.unique()"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Grouping changes to a row that happen close in time to each other"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"What happens if we just look at a particular row? If changes to a row happen close in time (say, within half a second), can we group this as an atomic chahange to a row?\n",
"\n",
"Let's grab the records for a particular row:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#results=collection.find({'$and': [{'row': '3'}, {'racingNumber': '3'}] },{'row':1,'strtime':1} )\n",
"results=collection.find({'row': '3' },{'row':1,'strtime':1} )\n",
"results.count()"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"df=pd.DataFrame(list(results))\n",
"df[:3]"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def itimeify(x):\n",
" tt=x.split('_')\n",
" return (int(tt[0])*3600000+int(tt[1])*60000+int(tt[2])*1000+int(tt[3]))/1000\n",
"\n",
"df['itime']=df['time'].apply(lambda x: itimeify(x))\n",
"df['time']=df['time'].apply(lambda x: timeify(x))\n",
"\n",
"df[:3]"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"ggplot(df[11:-5], aes(x='itime',y=1))+geom_point()"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#Is there anything we can do based around events on the same row that are within a short time of each other?\n",
"\n",
"#If there is a position change, details will refer to what in the row? Just the new driver?\n",
"\n",
"#Let's try to group close in time items...\n",
"#Based on http://stackoverflow.com/a/10017017/454773\n",
"d=list(df['itime'][11:-5])\n",
"\n",
"diff = [y - x for x, y in zip(*[iter(d)] * 2)]\n",
"#avg = sum(diff) / len(diff)\n",
"\n",
"m = [[d[0]]]\n",
"\n",
"for x in d[1:]:\n",
" #if x - m[-1][0] < avg:\n",
" if x - m[-1][0] < 0.5: #this is the threshold\n",
" m[-1].append(x)\n",
" else:\n",
" m.append([x])\n",
"\n",
"\n",
"print(m)"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now what do we do??? Make a common index for grouped elements and add them to a new MongoDB collection?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Taking the wrong approach - if a row updates, it does so in column order? - so we can use this as a crib...?**\n",
"\n",
"It doesn't... eg col 13 may update before col 2 within a given row...\n",
"\n",
"How about we start thing about:\n",
"\n",
"- useful dynamic, live state tracker objects\n",
"- history objects?"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Starting Over..."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from numpy import nan as NA\n",
"\n",
"race='data/F1 Race.txt'\n",
"\n",
"from lxml import etree"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 1
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#not used\n",
"class Driver:\n",
" \n",
" sectors=[NA,NA,NA]\n",
" prev_sectors=[NA,NA,NA]\n",
" history_sectors=[[],[],[]]\n",
" \n",
" def __init__(self, name,driverNum):\n",
" self.name = name\n",
" self.driverNum = driverNum\n",
" \n",
" def update_sector(self,sectorNum,sectorTime):\n",
" self.prev_sectors[sectorNum-1]=self.sectors[sectorNum-1]\n",
" self.sectors[sectorNum-1]=sectorTime\n",
" self.history_sectors[sectorNum-1].append(sectorTime)\n",
" \n",
" \n",
"ham=Driver(\"hamilton\",\"44\")\n",
"ham.name"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"ham.update_sector(1,33.12)\n",
"print(ham.sectors,ham.prev_sectors,ham.history_sectors)"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#not used\n",
"class Classification:\n",
" def __init__(self):\n",
" self.rank={}\n",
"\n",
"ranks=Classification()\n",
"ranks"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Pits:\n",
" \n",
" def __init__(self):\n",
" self._items={}\n",
" self.history=[]\n",
" self._logger=[]\n",
" #self._driverNum=NA\n",
" #self._lap=NA\n",
" #self._strtime=None\n",
" #self._count=NA\n",
" \n",
" def updateRacePits(self,raceObj,data):\n",
" #Need 2, 6 and 13 then commit\n",
" #This doesn't work if there is a position change while someone is IN PIT?\n",
" #SO: car has to go OUT before it can come back in?\n",
" #Also need to catch if car IN PIT then goes to RETIRED\n",
" driverNum=raceObj.getDriverNumFromPos(data)\n",
" if data['column'] in ['2','6','13']:\n",
" if driverNum not in self._items:\n",
" self._items[driverNum]={'out':True}\n",
" if data['column']=='2' and data['colour']=='RED':\n",
" self._logger.append(data)\n",
" self._items[driverNum]['driverNum']=str(driverNum)+'_'+data['value']\n",
" self._items[driverNum]['strtime']=data['strtime']\n",
" #Note: driverNum should == int(data['value'])\n",
" elif data['column']=='6':\n",
" if data['value']=='IN PIT':\n",
" self._logger.append(data)\n",
" self._items[driverNum]['status']=data['value']\n",
" elif data['value']=='OUT':\n",
" self._items[driverNum]={'out':True}\n",
" elif data['column']=='13' and data['value']!='':\n",
" self._logger.append(data)\n",
" self._items[driverNum]['lap']=raceObj.lap\n",
" self._items[driverNum]['count']=int(data['value'])\n",
" if len ( self._items[driverNum].keys()) ==6 and self._items[driverNum]['out'] :\n",
" #print('dd')\n",
" self.history.append(self._items[driverNum].copy())\n",
" raceObj.drivers[driverNum].appendPit(self._items[driverNum].copy())\n",
" self._items[driverNum]={'out':False}\n",
" "
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 2
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Purples:\n",
" \n",
" def __init__(self): \n",
" self.lap={}\n",
" self.sector1={}\n",
" self.sector2={}\n",
" self.sector3={}\n",
" \n",
" self._lap = {'driverNum':'',\"name\":'','laptime':'','classRank':'','lap':'','strtime':''}\n",
" \n",
" self._sector1={'driverNum':'',\"name\":'','laptime':'','classRank':'','lap':'','strtime':''}\n",
" self._sector2={'driverNum':'',\"name\":'','laptime':'','classRank':'','lap':'','strtime':''}\n",
" self._sector3={'driverNum':'',\"name\":'','laptime':'','classRank':'','lap':'','strtime':''}\n",
" \n",
" self.history=[]\n",
" \n",
" \n",
" def updateLapPurples(self,raceObj,data):\n",
" ''' '''\n",
" if data['column']=='2':\n",
" self._lap['driverNum']=data['value']\n",
" self._lap['strtime']=data['strtime']\n",
" self._lap['classRank']=int(data['row'])\n",
"\n",
" elif data['column']=='3':\n",
" self._lap['name']=data['value']\n",
"\n",
" elif data['column']=='6':\n",
" self._lap['laptime']=data['value']\n",
" self._lap['lap']=raceObj.lap-1\n",
"\n",
" self.lap=self._lap.copy()\n",
" self.history.append(self.lap)\n",
" \n",
" def updateSectorPurples(self,raceObj,sector,data):\n",
" pass\n",
" "
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 3
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class DriverHistory:\n",
" def __init__(self,driverNum=''):\n",
" self.driverNum=driverNum\n",
" self.pits=[]\n",
" \n",
" self._laptime=''\n",
" self._sector1time=''\n",
" self._sector2time=''\n",
" self._sector3time=''\n",
" self._gap=''\n",
" self._interval=''\n",
" self.lapdata=[]\n",
" \n",
" def setname(self,name):\n",
" self.name=name\n",
" \n",
" def appendPit(self,data):\n",
" self.pits.append(data)\n",
" \n",
" def trackLaptime(self,data):\n",
" if data['row']=='1':\n",
" self._gap='0'\n",
" self._interval='0'\n",
" if data['column'] == '6':\n",
" self._laptime=data['value']\n",
" self._timeofday=data['strtime']\n",
" elif data['column'] == '7': self._sector1time=data['value']\n",
" elif data['column'] =='9': self._sector2time=data['value']\n",
" elif data['column'] =='11': self._sector3time=data['value']\n",
" elif data['column'] =='4': self._gap=data['value']\n",
" elif data['column'] =='5': self._interval=data['value']\n",
" \n",
" if self._laptime != '' and self._sector1time!='' and self._sector2time!='' \\\n",
" and self._sector3time!='' and self._gap!='' and self._interval!='':\n",
" if raceObj.lap > (len(self.lapdata)+1):\n",
" #if len(self.lapdata)==0 or (self._timeofday != self.lapdata[-1]['timeofday'] ):\n",
" self.lapdata.append({\n",
" 'timeofday':self._timeofday,\n",
" 'pos':int(data['row']),\n",
" 'lap':raceObj.lap-1,\n",
" 'laptime':self._laptime,\n",
" 's1':self._sector1time,\n",
" 's2':self._sector2time,\n",
" 's3':self._sector3time,\n",
" 'gap':self._gap,\n",
" 'interval':self._interval})\n",
" self._laptime=''\n",
" self._sector1time=''\n",
" self._sector2time=''\n",
" self._sector3time=''\n",
" self._gap=''\n",
" self._interval='' \n",
" "
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 4
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Race:\n",
" def __init__(self):\n",
" self.lap=-1\n",
" self.pos={} #Contains the driver number for the current classification position\n",
" self.lapPurples=Purples()\n",
" self.pits=Pits()\n",
" self.drivers={}\n",
" self.driverNames={}\n",
" self._namesSet=False\n",
" \n",
" def setDriverNumForPos(self,data):\n",
" self.pos[data['row']]=data['value']\n",
" \n",
" def getDriverNumFromPos(self,data):\n",
" return self.pos[data['row']]\n",
" \n",
" def setupDriverDetails(self,data):\n",
" if data['column']=='2' and data['value'].strip()!='' and data['value'] not in self.drivers:\n",
" self.setDriverNumForPos(data)\n",
" self.drivers[data['value']]=DriverHistory(data['value'])\n",
" elif data['column']=='3' and data['value'].strip()!='':\n",
" driverNum=self.getDriverNumFromPos(data)\n",
" self.drivers[driverNum].setname(data['value'])\n",
" self.driverNames[data['value']]=driverNum\n",
"\n",
" def trackDriverNumForPos(self,data):\n",
" if data['column']=='2':\n",
" self.setDriverNumForPos(data)\n",
"\n",
" def trackLapCount(self,data):\n",
" if data['row']=='1' and data['column']=='5' and data['value']!='':\n",
" self.lap=int(data['value'])\n",
"\n",
" def trackPurples(self,raceObj,data):\n",
" if data['colour']=='PURPLE' and data['column'] in ['2','3','6']:\n",
" self.lapPurples.updateLapPurples(raceObj,data)\n",
" \n",
" def trackPits(self,raceObj,data):\n",
" if data['column'] in ['2','6','13']:\n",
" self.pits.updateRacePits(raceObj,data)\n",
" \n",
" def trackLaptimes(self,raceObj,data):\n",
" if data['column'] in ['4','5','6','7','9','11']:\n",
" driverNum=self.getDriverNumFromPos(data)\n",
" self.drivers[driverNum].trackLaptime(data)\n",
" "
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 5
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Weather:\n",
" def __init__(self):\n",
" self.stamps={}\n",
" \n",
" def setWeather(self,data):\n",
" if data['strtime'] not in self.stamps:\n",
" self.stamps[data['strtime']]={}\n",
" d=self.stamps[data['strtime']]\n",
" if data['row']=='1':\n",
" d['trackTemp']=data['value']\n",
" elif data['row']=='2':\n",
" d['airTemp']=data['value']\n",
" elif data['row']=='3':\n",
" d['rainfall']=data['value']\n",
" elif data['row']=='4':\n",
" d['windSpeed']=data['value']\n",
" elif data['row']=='5':\n",
" d['humidity']=data['value']\n",
" elif data['row']=='6':\n",
" d['airpressure']=data['value']\n",
" elif data['row']=='7':\n",
" d['windDir']=data['value']\n",
" "
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 6
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"plf=[]\n",
"wlf=[]\n",
"for el in open(race, 'r'):\n",
" r=etree.fromstring(el)\n",
" d={}\n",
" for a in r.attrib: d[a]=r.attrib[a]\n",
" for a in r[0].attrib: d[a]=r[0].attrib[a]\n",
" if d['identifier']=='101' and 'row' in d and d['column'] in ['1','2','3','4','5','6','7','9','11','12','13']:\n",
" dd={\"value\":d['value'], \"colour\":d['colour'],'row': d['row'],'column': d['column'],'strtime':d['timestamp']}\n",
" #did= '_'.join([ d['row'],d['timestamp'].replace(':','_').replace('.','_') ])\n",
" #dd={\"value\":d['value'], \"colour\":d['colour'],'id':did,'row': d['row'],'column': d['column'],'strtime':d['timestamp']}\n",
" plf.append(dd)\n",
" elif d['identifier']=='101' and 'sessionstate' in d:\n",
" plf.append(d)\n",
" elif d['identifier']=='103' and d['column']=='1':\n",
" dd={'strtime':d['timestamp'],'row': d['row'],\"value\":d['value']}\n",
" wlf.append(dd)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 7
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"plf[:3]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 8,
"text": [
"[{'messagecount': '107488',\n",
" 'informationvalid': 'true',\n",
" 'identifier': '101',\n",
" 'timestamp': '14:34:21.668',\n",
" 'sessionstate': 'inactive'},\n",
" {'column': '1',\n",
" 'value': '1',\n",
" 'colour': 'CYAN',\n",
" 'strtime': '14:34:21.669',\n",
" 'row': '1'},\n",
" {'column': '1',\n",
" 'value': '2',\n",
" 'colour': 'CYAN',\n",
" 'strtime': '14:34:21.669',\n",
" 'row': '2'}]"
]
}
],
"prompt_number": 8
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def checkSessionState(data):\n",
" if ('sessionstate' in data):\n",
" return data['sessionstate']\n",
" return"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 9
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"raceObj=Race()\n",
"startedRunning=False\n",
"finishedRunning=False\n",
"#raceHistory=RaceHistory()\n",
"for x in plf:\n",
" sessionstate=checkSessionState(x)\n",
" if sessionstate != None: print(sessionstate)\n",
" if sessionstate==\"started\":\n",
" startedRunning=True\n",
" elif startedRunning and sessionstate==\"inactive\":\n",
" finishedRunning=True\n",
" if not startedRunning and sessionstate == None:\n",
" raceObj.setupDriverDetails(x)\n",
" elif startedRunning and not finishedRunning and sessionstate == None:\n",
" raceObj.trackLapCount(x)\n",
" raceObj.trackDriverNumForPos(x)\n",
" raceObj.trackPurples(raceObj,x)\n",
" raceObj.trackPits(raceObj,x)\n",
" raceObj.trackLaptimes(raceObj,x)\n",
"#raceHistory.lapPurples.history"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"inactive\n",
"started\n",
"finished"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n",
"inactive\n",
"inactive\n"
]
}
],
"prompt_number": 10
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"weather=Weather()\n",
"for w in wlf:\n",
" weather.setWeather(w)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 11
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"weather.stamps['14:34:21.752']"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 15,
"text": [
"{'windDir': '129',\n",
" 'airpressure': '1002.3',\n",
" 'airTemp': '23',\n",
" 'trackTemp': '37',\n",
" 'windSpeed': '3.2',\n",
" 'rainfall': '0',\n",
" 'humidity': '45'}"
]
}
],
"prompt_number": 15
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"raceObj.drivers['1'].lapdata[-3:]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 17,
"text": [
"[{'interval': '25.2',\n",
" 'pos': 4,\n",
" 's2': '34.6',\n",
" 's3': '31.1',\n",
" 'laptime': '1:31.017',\n",
" 's1': '25.2',\n",
" 'gap': '73.8',\n",
" 'lap': 63,\n",
" 'timeofday': '16:17:43.612'},\n",
" {'interval': '26.0',\n",
" 'pos': 4,\n",
" 's2': '34.1',\n",
" 's3': '31.3',\n",
" 'laptime': '1:30.801',\n",
" 's1': '25.3',\n",
" 'gap': '74.2',\n",
" 'lap': 64,\n",
" 'timeofday': '16:19:14.387'},\n",
" {'interval': '27.6',\n",
" 'pos': 4,\n",
" 's2': '34.7',\n",
" 's3': '33.2',\n",
" 'laptime': '1:33.392',\n",
" 's1': '25.4',\n",
" 'gap': '76.7',\n",
" 'lap': 65,\n",
" 'timeofday': '16:20:47.843'}]"
]
}
],
"prompt_number": 17
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"raceObj.drivers['1'].lapdata[:5]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 18,
"text": [
"[{'interval': '0.4',\n",
" 'pos': 14,\n",
" 's2': '36.0',\n",
" 's3': '33.0',\n",
" 'laptime': '1:35.224',\n",
" 's1': '26.1',\n",
" 'gap': '12.4',\n",
" 'lap': 1,\n",
" 'timeofday': '14:41:46.378'},\n",
" {'interval': '0.3',\n",
" 'pos': 14,\n",
" 's2': '35.9',\n",
" 's3': '32.9',\n",
" 'laptime': '1:34.674',\n",
" 's1': '25.7',\n",
" 'gap': '18.0',\n",
" 'lap': 3,\n",
" 'timeofday': '14:44:55.894'},\n",
" {'interval': '0.3',\n",
" 'pos': 14,\n",
" 's2': '35.8',\n",
" 's3': '32.7',\n",
" 'laptime': '1:34.306',\n",
" 's1': '25.7',\n",
" 'gap': '20.3',\n",
" 'lap': 4,\n",
" 'timeofday': '14:46:30.222'},\n",
" {'interval': '0.4',\n",
" 'pos': 14,\n",
" 's2': '35.7',\n",
" 's3': '32.7',\n",
" 'laptime': '1:34.449',\n",
" 's1': '25.8',\n",
" 'gap': '22.7',\n",
" 'lap': 5,\n",
" 'timeofday': '14:48:04.589'},\n",
" {'interval': '0.6',\n",
" 'pos': 14,\n",
" 's2': '35.9',\n",
" 's3': '32.7',\n",
" 'laptime': '1:34.356',\n",
" 's1': '25.6',\n",
" 'gap': '24.9',\n",
" 'lap': 6,\n",
" 'timeofday': '14:49:39.101'}]"
]
}
],
"prompt_number": 18
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"raceObj.lapPurples.history[:3]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 21,
"text": [
"[{'classRank': 1,\n",
" 'lap': 1,\n",
" 'laptime': '1:32.010',\n",
" 'name': 'L. HAMILTON',\n",
" 'strtime': '14:41:34.205',\n",
" 'driverNum': '44'},\n",
" {'classRank': 1,\n",
" 'lap': 3,\n",
" 'laptime': '1:31.913',\n",
" 'name': 'L. HAMILTON',\n",
" 'strtime': '14:44:38.478',\n",
" 'driverNum': '44'},\n",
" {'classRank': 1,\n",
" 'lap': 8,\n",
" 'laptime': '1:31.876',\n",
" 'name': 'L. HAMILTON',\n",
" 'strtime': '14:52:18.197',\n",
" 'driverNum': '44'}]"
]
}
],
"prompt_number": 21
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"raceObj.drivers['1'].pits"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 22,
"text": [
"[{'lap': 12,\n",
" 'status': 'IN PIT',\n",
" 'count': 1,\n",
" 'out': True,\n",
" 'strtime': '14:57:29.852',\n",
" 'driverNum': '1_1'},\n",
" {'lap': 33,\n",
" 'status': 'IN PIT',\n",
" 'count': 2,\n",
" 'out': True,\n",
" 'strtime': '15:30:19.373',\n",
" 'driverNum': '1_1'},\n",
" {'lap': 52,\n",
" 'status': 'IN PIT',\n",
" 'count': 3,\n",
" 'out': True,\n",
" 'strtime': '15:59:25.171',\n",
" 'driverNum': '1_1'}]"
]
}
],
"prompt_number": 22
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"raceObj.drivers['1'].name"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 23,
"text": [
"'S. VETTEL'"
]
}
],
"prompt_number": 23
},
{
"cell_type": "raw",
"metadata": {},
"source": [
"In this example, row 17 starts to update high columns before the lower ones\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
""
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"raceObj.pits._logger[:3]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 26,
"text": [
"[{'column': '2',\n",
" 'value': '44',\n",
" 'colour': 'RED',\n",
" 'strtime': '14:42:56.839',\n",
" 'row': '1'},\n",
" {'column': '6',\n",
" 'value': 'IN PIT',\n",
" 'colour': 'YELLOW',\n",
" 'strtime': '14:42:56.839',\n",
" 'row': '1'},\n",
" {'column': '13',\n",
" 'value': '1',\n",
" 'colour': 'YELLOW',\n",
" 'strtime': '14:57:29.847',\n",
" 'row': '13'}]"
]
}
],
"prompt_number": 26
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"raceObj.pits.history[:3]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 28,
"text": [
"[{'lap': 12,\n",
" 'status': 'IN PIT',\n",
" 'count': 1,\n",
" 'out': True,\n",
" 'strtime': '14:57:29.852',\n",
" 'driverNum': '1_1'},\n",
" {'lap': 14,\n",
" 'status': 'IN PIT',\n",
" 'count': 1,\n",
" 'out': True,\n",
" 'strtime': '15:00:18.871',\n",
" 'driverNum': '3_3'},\n",
" {'lap': 15,\n",
" 'status': 'IN PIT',\n",
" 'count': 1,\n",
" 'out': True,\n",
" 'strtime': '15:01:59.009',\n",
" 'driverNum': '8_8'}]"
]
}
],
"prompt_number": 28
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"raceObj.pos"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 29,
"text": [
"{'2': '6',\n",
" '1': '44',\n",
" '4': '1',\n",
" '8': '8',\n",
" '16': '21',\n",
" '6': '14',\n",
" '18': '17',\n",
" '19': '4',\n",
" '12': '20',\n",
" '10': '27',\n",
" '14': '26',\n",
" '20': '9',\n",
" '21': '10',\n",
" '9': '11',\n",
" '3': '3',\n",
" '17': '99',\n",
" '15': '13',\n",
" '7': '7',\n",
" '5': '77',\n",
" '13': '19',\n",
" '11': '22',\n",
" '22': '25'}"
]
}
],
"prompt_number": 29
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"gource"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import csv\n",
"from time import *\n",
"#f=open('openurlgource.csv', 'rb')\n",
" \n",
"#reader = csv.reader(f, delimiter='\\t')\n",
"writer = csv.writer(open('openurlgource.txt','wb'),delimiter='|')\n",
"headerline = reader.next()\n",
"for row in reader:\n",
" if row[4].strip() !='':\n",
" t=int(mktime(strptime(row[0]+\" \"+row[1], \"%Y-%m-%d %H:%M:%S\")))\n",
" writer.writerow([t,row[3],'A',row[4].rstrip(':').replace(':','/')])\n"
],
"language": "python",
"metadata": {},
"outputs": []
}
],
"metadata": {}
}
]
}