├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── main.yml ├── .gitignore ├── CONTRIBUTING.md ├── Ch02 ├── 02_01 │ ├── test_transformers.py │ └── transformers.py ├── 02_02 │ ├── pyproject.toml │ ├── test_model.py │ └── test_windows.py ├── 02_03 │ ├── test_transformers_param.py │ └── transformers.py ├── 02_04 │ ├── api_client.py │ ├── conftest.py │ └── test_api.py ├── 02_05 │ ├── db_client.py │ └── test_client.py ├── 02_06 │ ├── split_cases.yml │ └── splitter.py └── 02_07 │ ├── split_cases.yml │ ├── splitter.py │ └── test_splitter.py ├── Ch03 ├── 03_02 │ ├── activation.py │ └── test_activation.py ├── 03_03 │ ├── freq.py │ └── test_freq.py ├── 03_04 │ ├── stocks.py │ └── test_stocks.py ├── 03_05 │ ├── sales.py │ └── test_sales.py ├── 03_06 │ └── geo.py └── 03_07 │ ├── geo.py │ └── test_geo.py ├── Ch04 ├── 04_01 │ ├── loaders.py │ ├── sales.csv │ ├── schema.py │ └── test_loaders.py ├── 04_02 │ └── truth.py ├── 04_03 │ └── floats.py ├── 04_04 │ └── close.py ├── 04_05 │ └── randomness.py ├── 04_06 │ └── test_fraud.py ├── 04_07 │ ├── metrics.jsonl │ └── metrics.py └── 04_08 │ ├── metrics.jsonl │ └── metrics.py ├── Ch05 ├── 05_04 │ ├── conftest.py │ └── test_regression.py └── 05_06 │ ├── conftest.py │ └── test_performance.py ├── Ch06 ├── 06_02 │ ├── test_track_nb.py │ ├── track.csv │ └── track.ipynb ├── 06_03 │ ├── test_tracklib.py │ ├── track.csv │ ├── track.ipynb │ ├── track_before.ipynb │ └── tracklib.py └── 06_04 │ ├── test_track.py │ └── track.ipynb ├── LICENSE ├── NOTICE ├── README.md ├── create_env.py └── requirements.txt /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Codeowners for these exercise files: 2 | # * (asterisk) deotes "all files and folders" 3 | # Example: * @producer @instructor 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | ## Issue Overview 9 | 10 | 11 | ## Describe your environment 12 | 13 | 14 | ## Steps to Reproduce 15 | 16 | 1. 17 | 2. 18 | 3. 19 | 4. 20 | 21 | ## Expected Behavior 22 | 23 | 24 | ## Current Behavior 25 | 26 | 27 | ## Possible Solution 28 | 29 | 30 | ## Screenshots / Video 31 | 32 | 33 | ## Related Issues 34 | 35 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Copy To Branches 2 | on: 3 | workflow_dispatch: 4 | jobs: 5 | copy-to-branches: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@v2 9 | with: 10 | fetch-depth: 0 11 | - name: Copy To Branches Action 12 | uses: planetoftheweb/copy-to-branches@v1 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | .tmp 4 | npm-debug.log 5 | 6 | # Python 7 | .hypothesis 8 | .ipynb_checkpoints 9 | .pytest_cache 10 | __pycache__ 11 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 2 | Contribution Agreement 3 | ====================== 4 | 5 | This repository does not accept pull requests (PRs). All pull requests will be closed. 6 | 7 | However, if any contributions (through pull requests, issues, feedback or otherwise) are provided, as a contributor, you represent that the code you submit is your original work or that of your employer (in which case you represent you have the right to bind your employer). By submitting code (or otherwise providing feedback), you (and, if applicable, your employer) are licensing the submitted code (and/or feedback) to LinkedIn and the open source community subject to the BSD 2-Clause license. 8 | -------------------------------------------------------------------------------- /Ch02/02_01/test_transformers.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import transformers as tr 3 | 4 | 5 | def test_scale(): 6 | v = np.array([0.1, 1.0, 1.1]) 7 | out = tr.scale(v, 1, 1.1) 8 | expected = np.array([0.1, 1.1, 1.21]) 9 | assert np.allclose(expected, out) 10 | -------------------------------------------------------------------------------- /Ch02/02_01/transformers.py: -------------------------------------------------------------------------------- 1 | def scale(v, cutoff, factor): 2 | """Scale values above cutoff by factor""" 3 | v = v.copy() 4 | v[v>=cutoff] *= factor 5 | return v 6 | -------------------------------------------------------------------------------- /Ch02/02_02/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.pytest.ini_options] 2 | 3 | markers = [ 4 | "web", 5 | ] 6 | -------------------------------------------------------------------------------- /Ch02/02_02/test_model.py: -------------------------------------------------------------------------------- 1 | from os import environ 2 | 3 | import pytest 4 | 5 | in_ci = 'CI' in environ 6 | ci_only = pytest.mark.skipif(not in_ci, reason='not in CI') 7 | 8 | 9 | def test_always(): 10 | pass 11 | 12 | 13 | @ci_only 14 | def test_in_ci(): 15 | pass 16 | 17 | 18 | @pytest.mark.web 19 | def test_web(): 20 | pass 21 | -------------------------------------------------------------------------------- /Ch02/02_02/test_windows.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | import pytest 4 | 5 | pytestmark = pytest.mark.skipif( 6 | sys.platform != 'win32', 7 | reason='Windows only tests', 8 | ) 9 | 10 | 11 | def test_windows(): 12 | pass 13 | -------------------------------------------------------------------------------- /Ch02/02_03/test_transformers_param.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | import transformers as tr 4 | 5 | v = np.array([0.1, 1.0, 1.1]) 6 | scale_cases = [ 7 | # v, cutoff, factor, expected 8 | [v, 1, 1.1, [0.1, 1.1, 1.21]], 9 | [v, v.max() + 1, 0, v], 10 | # ... 11 | ] 12 | 13 | 14 | @pytest.mark.parametrize('v, cutoff, factor, expected', scale_cases) 15 | def test_scale_many(v, cutoff, factor, expected): 16 | out = tr.scale(v, cutoff, factor) 17 | 18 | assert np.allclose(expected, out) 19 | -------------------------------------------------------------------------------- /Ch02/02_03/transformers.py: -------------------------------------------------------------------------------- 1 | def scale(v, cutoff, factor): 2 | """Scale values above cutoff by factor""" 3 | v = v.copy() 4 | v[v>=cutoff] *= factor 5 | return v 6 | -------------------------------------------------------------------------------- /Ch02/02_04/api_client.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | logging.basicConfig( 4 | level=logging.INFO, 5 | format='%(asctime)s - %(levelname)s - %(message)s', 6 | datefmt='%Y-%m-%dT%H:%M:%S', 7 | ) 8 | 9 | 10 | class APIClient: 11 | def __init__(self, host): 12 | self.host = host 13 | logging.info('client connected to %r', host) 14 | # TODO: connect to host 15 | 16 | def metrics(self): 17 | # FIXME: Call real server 18 | return data 19 | 20 | def close(self): 21 | logging.info('client (%r) closing', self.host) 22 | 23 | 24 | data = [ 25 | {"time":"2021-07-13T14:36:52.380Z","metric":"mem","value":227551548.0}, 26 | {"time":"2021-07-13T14:36:52.380Z","metric":"cpu","value":30.04}, 27 | {"time":"2021-07-13T14:36:53.337Z","metric":"mem","value":227567864.0}, 28 | {"time":"2021-07-13T14:36:53.337Z","metric":"cpu","value":30.93}, 29 | {"time":"2021-07-13T14:36:54.294Z","metric":"mem","value":227574696.0}, 30 | {"time":"2021-07-13T14:36:54.294Z","metric":"cpu","value":32.61}, 31 | {"time":"2021-07-13T14:36:55.251Z","metric":"mem","value":227567135.0}, 32 | {"time":"2021-07-13T14:36:55.251Z","metric":"cpu","value":32.24}, 33 | {"time":"2021-07-13T14:36:56.208Z","metric":"mem","value":227561333.0}, 34 | {"time":"2021-07-13T14:36:56.208Z","metric":"cpu","value":31.27}, 35 | {"time":"2021-07-13T14:36:57.165Z","metric":"cpu","value":31.33}, 36 | {"time":"2021-07-13T14:36:57.165Z","metric":"mem","value":227586440.0}, 37 | ] 38 | 39 | -------------------------------------------------------------------------------- /Ch02/02_04/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from api_client import APIClient 3 | 4 | 5 | @pytest.fixture 6 | def client(): 7 | # setup 8 | client = APIClient('localhost') 9 | 10 | yield client 11 | 12 | # teardown 13 | client.close() 14 | -------------------------------------------------------------------------------- /Ch02/02_04/test_api.py: -------------------------------------------------------------------------------- 1 | def test_metrics(client): 2 | rows = client.metrics() 3 | assert len(rows) > 0 -------------------------------------------------------------------------------- /Ch02/02_05/db_client.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | 3 | 4 | def db_connect(dsn): 5 | conn = sqlite3.connect(dsn, detect_types=sqlite3.PARSE_DECLTYPES) 6 | conn.row_factory = sqlite3.Row 7 | return conn 8 | 9 | 10 | class DBClient: 11 | def __init__(self, dsn): 12 | self.conn = db_connect(dsn) 13 | 14 | def metrics(self, start_time, end_time): 15 | params = {'start': start_time, 'end': end_time} 16 | sql = 'SELECT * FROM metrics WHERE time >= :start AND time <= :end' 17 | return self.conn.execute(sql, params) -------------------------------------------------------------------------------- /Ch02/02_05/test_client.py: -------------------------------------------------------------------------------- 1 | from unittest.mock import MagicMock 2 | 3 | import db_client 4 | 5 | def test_metrics(monkeypatch): 6 | mock_conn = MagicMock() 7 | mock_conn.cursor.return_value = mock_conn 8 | mock_conn.execute.return_value = data 9 | monkeypatch.setattr(db_client, 'db_connect', lambda dsn: mock_conn) 10 | 11 | client = db_client.DBClient('/path/to/metrics.db') 12 | 13 | rows = client.metrics('2021-07-13', '2021-07-14') 14 | assert mock_conn.execute.called 15 | assert len(rows) == len(data) 16 | 17 | 18 | data = [ 19 | {"time":"2021-07-13T14:36:52.380Z","metric":"mem","value":227551548.0}, 20 | {"time":"2021-07-13T14:36:52.380Z","metric":"cpu","value":30.04}, 21 | {"time":"2021-07-13T14:36:53.337Z","metric":"mem","value":227567864.0}, 22 | {"time":"2021-07-13T14:36:53.337Z","metric":"cpu","value":30.93}, 23 | {"time":"2021-07-13T14:36:54.294Z","metric":"mem","value":227574696.0}, 24 | {"time":"2021-07-13T14:36:54.294Z","metric":"cpu","value":32.61}, 25 | {"time":"2021-07-13T14:36:55.251Z","metric":"mem","value":227567135.0}, 26 | {"time":"2021-07-13T14:36:55.251Z","metric":"cpu","value":32.24}, 27 | {"time":"2021-07-13T14:36:56.208Z","metric":"mem","value":227561333.0}, 28 | {"time":"2021-07-13T14:36:56.208Z","metric":"cpu","value":31.27}, 29 | {"time":"2021-07-13T14:36:57.165Z","metric":"cpu","value":31.33}, 30 | {"time":"2021-07-13T14:36:57.165Z","metric":"mem","value":227586440.0}, 31 | ] 32 | 33 | -------------------------------------------------------------------------------- /Ch02/02_06/split_cases.yml: -------------------------------------------------------------------------------- 1 | - size: 10 2 | chunk_size: 3 3 | chunks: 4 | - [0, 3] 5 | - [3, 6] 6 | - [6, 9] 7 | - [9, 10] 8 | 9 | - size: 10 10 | chunk_size: 10 11 | chunks: 12 | - [0, 10] 13 | 14 | - size: 10 15 | chunk_size: 100 16 | chunks: 17 | - [0, 10] 18 | -------------------------------------------------------------------------------- /Ch02/02_06/splitter.py: -------------------------------------------------------------------------------- 1 | def split_to_chunks(size, chunk_size): 2 | """Return half-open ranges of (start, end) chunks up to size, 3 | each chunk <= chunk_size. 4 | 5 | >>> list(split_to_chunks(10, 3)) 6 | [(0, 3), (3, 6), (6, 9), (9, 10)] 7 | """ 8 | if chunk_size <= 0: 9 | raise ValueError(f'chunk_size must be > 0, got {chunk_size}') 10 | 11 | if size < 0: 12 | raise ValueError(f'size must be >= 0, got {size}') 13 | 14 | # Return iterator *after* we check arguments 15 | return _split_to_chunks(size, chunk_size) 16 | 17 | 18 | def _split_to_chunks(size, chunk_size): 19 | start = 0 20 | while start < size: 21 | end = min(start + chunk_size, size) 22 | yield start, end 23 | start = end 24 | -------------------------------------------------------------------------------- /Ch02/02_07/split_cases.yml: -------------------------------------------------------------------------------- 1 | - size: 10 2 | chunk_size: 3 3 | chunks: 4 | - [0, 3] 5 | - [3, 6] 6 | - [6, 9] 7 | - [9, 10] 8 | 9 | - size: 10 10 | chunk_size: 10 11 | chunks: 12 | - [0, 10] 13 | 14 | - size: 10 15 | chunk_size: 100 16 | chunks: 17 | - [0, 10] 18 | -------------------------------------------------------------------------------- /Ch02/02_07/splitter.py: -------------------------------------------------------------------------------- 1 | def split_to_chunks(size, chunk_size): 2 | """Return half-open ranges of (start, end) chunks up to size, 3 | each chunk <= chunk_size. 4 | 5 | >>> list(split_to_chunks(10, 3)) 6 | [(0, 3), (3, 6), (6, 9), (9, 10)] 7 | """ 8 | if chunk_size <= 0: 9 | raise ValueError(f'chunk_size must be > 0, got {chunk_size}') 10 | 11 | if size < 0: 12 | raise ValueError(f'size must be >= 0, got {size}') 13 | 14 | # Return iterator *after* we check arguments 15 | return _split_to_chunks(size, chunk_size) 16 | 17 | 18 | def _split_to_chunks(size, chunk_size): 19 | start = 0 20 | while start < size: 21 | end = min(start + chunk_size, size) 22 | yield start, end 23 | start = end 24 | -------------------------------------------------------------------------------- /Ch02/02_07/test_splitter.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | import pytest 4 | import yaml 5 | 6 | import splitter 7 | 8 | here = Path(__file__).absolute().parent 9 | 10 | 11 | def load_split_cases(): 12 | cases_file = here / 'split_cases.yml' 13 | with cases_file.open() as fp: 14 | data = yaml.safe_load(fp) 15 | 16 | for tc in data: 17 | yield tc['size'], tc['chunk_size'], tc['chunks'] 18 | 19 | 20 | @pytest.mark.parametrize('size, chunk_size, expected', load_split_cases()) 21 | def test_split_to_chunks(size, chunk_size, expected): 22 | chunks = splitter.split_to_chunks(size, chunk_size) 23 | # split_to_chunks returns tuples generator, test case has lists 24 | chunks = [list(c) for c in chunks] 25 | assert chunks == expected 26 | -------------------------------------------------------------------------------- /Ch03/03_02/activation.py: -------------------------------------------------------------------------------- 1 | def relu(n): 2 | if n < 0: 3 | return 0 4 | return n 5 | -------------------------------------------------------------------------------- /Ch03/03_02/test_activation.py: -------------------------------------------------------------------------------- 1 | import activation 2 | from hypothesis import given 3 | from hypothesis.strategies import floats 4 | import numpy as np 5 | 6 | 7 | @given(floats()) 8 | def test_relu(n): 9 | print(n) 10 | v = activation.relu(n) 11 | if not np.isnan(n): 12 | assert v >= 0 13 | -------------------------------------------------------------------------------- /Ch03/03_03/freq.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def first_digit(n): 5 | return str(n)[0] 6 | 7 | 8 | def first_digit_freq(values): 9 | """Return frequency of first digits in values. 10 | 11 | >>> first_digit_freq([18, 19, 20, 21, 22]) 12 | array([0. , 0.4, 0.6, 0. , 0. , 0. , 0. , 0. , 0. , 0. ]) 13 | """ 14 | firsts = [first_digit(n) for n in values] 15 | freqs = np.bincount(firsts, minlength=10) 16 | return freqs / len(values) -------------------------------------------------------------------------------- /Ch03/03_03/test_freq.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from freq import first_digit_freq 3 | from hypothesis import given 4 | from hypothesis.extra.numpy import arrays 5 | from hypothesis.strategies import integers 6 | 7 | strategy = arrays( 8 | dtype=np.int64, 9 | shape=integers(min_value=1, max_value=10_000), 10 | elements=integers(min_value=0, max_value=np.iinfo(np.int64).max-1), 11 | ) 12 | 13 | @given(strategy) 14 | def test_freq(values): 15 | freqs = first_digit_freq(values) 16 | assert freqs.shape == (10,) 17 | assert ((freqs>=0) & (freqs<=1)).all() 18 | assert np.allclose(freqs.sum(), 1) 19 | -------------------------------------------------------------------------------- /Ch03/03_04/stocks.py: -------------------------------------------------------------------------------- 1 | def max_drop(stocks): 2 | """Return max drop per stocks. 3 | 4 | stocks is a data frame with symbol, high, low. 5 | """ 6 | df = stocks.copy() 7 | df['diff'] = df['high'] - df['low'] 8 | return df.groupby('symbol')['diff'].max() -------------------------------------------------------------------------------- /Ch03/03_04/test_stocks.py: -------------------------------------------------------------------------------- 1 | from hypothesis import given 2 | from hypothesis.extra.pandas import column, data_frames 3 | from hypothesis.strategies import floats, from_regex 4 | from stocks import max_drop 5 | 6 | strategy = data_frames([ 7 | column('symbol', elements=from_regex(r'[A-Z]{2,7}', fullmatch=True)), 8 | column('high', elements=floats(min_value=1, max_value=10_000)), 9 | column('low', elements=floats(min_value=1, max_value=10_000)), 10 | ]) 11 | 12 | 13 | @given(strategy) 14 | def test_max_drop(df): 15 | out = max_drop(df) 16 | unknown = set(out.index) - set(df['symbol']) 17 | assert not unknown 18 | -------------------------------------------------------------------------------- /Ch03/03_05/sales.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | 4 | @dataclass 5 | class Sale: 6 | sku: str 7 | price: int # US cents 8 | 9 | 10 | def sku_sales(sales: list[Sale]): 11 | by_sku = {} # sku -> amount 12 | for sale in sales: 13 | by_sku[sale.sku] = by_sku.get(sale.sku, 0) + sale.price 14 | return by_sku 15 | -------------------------------------------------------------------------------- /Ch03/03_05/test_sales.py: -------------------------------------------------------------------------------- 1 | from hypothesis import given 2 | from hypothesis.strategies import composite, from_regex, integers, lists 3 | from sales import Sale, sku_sales 4 | 5 | 6 | @composite 7 | def sales(draw): 8 | sku = draw(from_regex(r'[A-F0-9]{8}', fullmatch=True)) 9 | amout = draw(integers(min_value=1, max_value=10_000)) 10 | return Sale(sku, amout) 11 | 12 | 13 | @given(lists(elements=sales())) 14 | def test_sku_sales(sales): 15 | by_sku = sku_sales(sales) 16 | unknown = set(by_sku) - set(sale.sku for sale in sales) 17 | assert not unknown -------------------------------------------------------------------------------- /Ch03/03_06/geo.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | earth_radius_km = 6373 4 | 5 | 6 | def haversine(lat1, lng1, lat2, lng2): 7 | """Return distance in km between two coordinates.""" 8 | phi1 = np.deg2rad(90 - lat1) 9 | phi2 = np.deg2rad(90 - lat2) 10 | 11 | theta1 = np.deg2rad(lng1) 12 | theta2 = np.deg2rad(lng2) 13 | 14 | cos = (np.sin(phi1) * np.sin(phi2) * np.cos(theta1 - theta2) + 15 | np.cos(phi1) * np.cos(phi2)) 16 | arc = np.arccos(cos) 17 | return arc * earth_radius_km 18 | -------------------------------------------------------------------------------- /Ch03/03_07/geo.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | earth_radius_km = 6373 4 | 5 | 6 | def haversine(lat1, lng1, lat2, lng2): 7 | """Return distance in km between two coordinates.""" 8 | phi1 = np.deg2rad(90 - lat1) 9 | phi2 = np.deg2rad(90 - lat2) 10 | 11 | theta1 = np.deg2rad(lng1) 12 | theta2 = np.deg2rad(lng2) 13 | 14 | cos = (np.sin(phi1) * np.sin(phi2) * np.cos(theta1 - theta2) + 15 | np.cos(phi1) * np.cos(phi2)) 16 | arc = np.arccos(cos) 17 | return arc * earth_radius_km 18 | -------------------------------------------------------------------------------- /Ch03/03_07/test_geo.py: -------------------------------------------------------------------------------- 1 | # Test geo.haversine using hypothesis 2 | # - Latitudes are between -90 to 90 3 | # - Longitudes are between -180 to 180 4 | # - No NaN 5 | import numpy as np 6 | from hypothesis import given 7 | from hypothesis.strategies import floats, composite 8 | 9 | import geo 10 | 11 | 12 | @composite 13 | def lats(draw): 14 | return draw(floats(min_value=-90, max_value=90, allow_nan=False)) 15 | 16 | 17 | @composite 18 | def lngs(draw): 19 | return draw(floats(min_value=-180, max_value=180, allow_nan=False)) 20 | 21 | 22 | @given(lats(), lngs(), lats(), lngs()) 23 | def test_haversine_fuzz(lat1, lng1, lat2, lng2): 24 | dist = geo.haversine(lat1, lng1, lat2, lng2) 25 | 26 | if not np.isnan(dist): 27 | assert dist >= 0 28 | -------------------------------------------------------------------------------- /Ch04/04_01/loaders.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | 4 | def load_sales(file_name): 5 | return pd.read_csv(file_name, parse_dates=['time']) -------------------------------------------------------------------------------- /Ch04/04_01/sales.csv: -------------------------------------------------------------------------------- 1 | time,value,ip 2 | 2022-08-05T07:17:23,150,172.27.219.236 3 | 2022-08-05T07:19:39,114,242.112.145.134 4 | 2022-08-05T07:21:55,122,127.100.156.137 5 | 2022-08-05T07:24:11,210,198.51.100.68 6 | 2022-08-05T07:26:27,64,192.168.164.136 7 | 2022-08-05T07:28:44,209,141.53.200.19 8 | 2022-08-05T07:31:00,91,96.210.219.80 9 | 2022-08-05T07:33:16,142,192.0.0.8 10 | 2022-08-05T07:35:32,190,70.37.55.77 11 | 2022-08-05T07:37:48,211,61.186.180.152 12 | 2022-08-05T07:40:05,84,41.24.185.159 13 | 2022-08-05T07:42:21,216,75.136.178.10 14 | 2022-08-05T07:44:37,181,79.77.36.162 15 | 2022-08-05T07:46:53,217,192.175.48.126 16 | 2022-08-05T07:49:09,49,60.159.41.98 17 | 2022-08-05T07:51:26,18,157.115.55.205 18 | 2022-08-05T07:53:42,151,148.180.137.234 19 | 2022-08-05T07:55:58,50,0.24.73.106 20 | 2022-08-05T07:58:14,80,127.175.169.14 21 | 2022-08-05T08:00:30,165,192.31.196.176 22 | 2022-08-05T08:02:47,211,192.0.0.6 23 | 2022-08-05T08:05:03,37,240.0.0.99 24 | 2022-08-05T08:07:19,108,0.25.20.129 25 | 2022-08-05T08:09:35,184,76.199.227.91 26 | 2022-08-05T08:11:51,97,0.0.0.0 27 | 2022-08-05T08:14:08,102,191.146.60.50 28 | 2022-08-05T08:16:24,54,192.0.0.85 29 | 2022-08-05T08:18:40,40,203.0.113.188 30 | 2022-08-05T08:20:56,54,203.0.113.179 31 | 2022-08-05T08:23:12,126,45.110.155.132 32 | 2022-08-05T08:25:29,168,240.0.0.0 33 | 2022-08-05T08:27:45,55,67.39.51.158 34 | 2022-08-05T08:30:01,136,127.117.12.78 35 | 2022-08-05T08:32:17,191,12.77.198.41 36 | 2022-08-05T08:34:33,143,0.129.252.218 37 | 2022-08-05T08:36:50,194,207.58.50.150 38 | 2022-08-05T08:39:06,214,3.46.112.246 39 | 2022-08-05T08:41:22,162,192.175.48.193 40 | 2022-08-05T08:43:38,79,0.0.0.0 41 | 2022-08-05T08:45:54,143,0.191.180.40 42 | 2022-08-05T08:48:11,78,192.0.0.112 43 | 2022-08-05T08:50:27,30,14.95.143.137 44 | 2022-08-05T08:52:43,169,127.225.176.228 45 | 2022-08-05T08:54:59,21,159.238.74.73 46 | 2022-08-05T08:57:15,105,146.192.144.199 47 | 2022-08-05T08:59:32,156,35.100.226.170 48 | 2022-08-05T09:01:48,127,64.165.151.254 49 | 2022-08-05T09:04:04,11,138.57.250.8 50 | 2022-08-05T09:06:20,10,192.0.0.49 51 | 2022-08-05T09:08:36,56,203.0.113.170 52 | -------------------------------------------------------------------------------- /Ch04/04_01/schema.py: -------------------------------------------------------------------------------- 1 | from ipaddress import IPv4Address 2 | 3 | import pandas as pd 4 | import pandera as pa 5 | 6 | 7 | def is_ipv4(v): 8 | try: 9 | IPv4Address(v) 10 | return True 11 | except ValueError: 12 | return False 13 | 14 | 15 | sales_schema = pa.DataFrameSchema({ 16 | 'time': pa.Column(pd.Timestamp), 17 | 'value': pa.Column(pd.Int64Dtype, checks=pa.Check.greater_than(0)), 18 | 'ip': pa.Column(str, pa.Check(is_ipv4, element_wise=True)), 19 | }) 20 | -------------------------------------------------------------------------------- /Ch04/04_01/test_loaders.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | import loaders 4 | from schema import sales_schema 5 | 6 | here = Path(__file__).absolute().parent 7 | 8 | 9 | def test_load_sales(): 10 | csv_file = here / 'sales.csv' 11 | df = loaders.load_sales(csv_file) 12 | sales_schema.validate(df) 13 | -------------------------------------------------------------------------------- /Ch04/04_02/truth.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | 4 | x = 20 5 | assert x > 10, 'x too small' 6 | 7 | x > 10 8 | 9 | assert x > 100, 'x too small' 10 | x > 100 11 | 12 | # 0 numbers are False 13 | for n in [0, 0.0, 0+0j]: 14 | print(f'{n!r} -> {bool(n)}') 15 | 16 | # Empty collections are False 17 | for c in [(), {}, '']: 18 | print(f'{c!r} -> {bool(c)}') 19 | 20 | # None is False 21 | print(f'None -> {bool(None)}') 22 | 23 | # False is False (doh!) 24 | print(f'False -> {bool(False)}') 25 | 26 | # Everything else is True 27 | objs = ['Hi', 3.4, (5, 7), object(), np.nan] 28 | for obj in objs: 29 | print(f'{obj!r} -> {bool(obj)}') 30 | 31 | 32 | # However 33 | v = np.array([-1, 2, 3]) 34 | assert v > 0, 'not positive' 35 | 36 | cond = v > 0 37 | print(cond) 38 | 39 | cond.all() 40 | cond.any() 41 | 42 | s = pd.Series(v) 43 | assert s > 0, 'not positive' -------------------------------------------------------------------------------- /Ch04/04_03/floats.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | 4 | # Floating points are inexact 5 | 0.1 + 0.1 6 | 7 | # NaN is ... interesting 8 | np.nan == np.nan 9 | 10 | # To ∞ and beyond 11 | np.inf > np.inf - 1 12 | 13 | # NaN functions 14 | v = np.array([1.1, np.nan, 3.3]) 15 | v.sum() 16 | 17 | s = pd.Series(v) 18 | s.sum() 19 | 20 | # Float info 21 | np.finfo(np.float64) 22 | -------------------------------------------------------------------------------- /Ch04/04_04/close.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | v = np.array([0.1, np.nan, 1.1]) 4 | n = 1.1 5 | expected = np.array([0.11, np.nan, 1.21]) 6 | out = v * n 7 | out == expected 8 | 9 | out 10 | 11 | np.allclose(expected, out) -------------------------------------------------------------------------------- /Ch04/04_05/randomness.py: -------------------------------------------------------------------------------- 1 | from sklearn.datasets import load_digits 2 | from sklearn.model_selection import train_test_split 3 | from sklearn.svm import SVC 4 | 5 | digits = load_digits() 6 | X, y = digits.data, digits.target 7 | X_train, X_test, y_train, y_test = \ 8 | train_test_split(X, y) 9 | 10 | clf = SVC() 11 | clf.fit(X_train, y_train) 12 | clf.score(X_test, y_test) -------------------------------------------------------------------------------- /Ch04/04_06/test_fraud.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from pandas.testing import assert_frame_equal 3 | 4 | 5 | def test_model(): 6 | # Calling model on data redacted 7 | out = pd.DataFrame({ 8 | 'id': [1, 2, 3, 4], 9 | 'is_fraud': [0.1, 0.97, 0.3, 0.2], 10 | }) 11 | 12 | expected = pd.DataFrame({ 13 | 'id': [1, 2, 3, 4], 14 | 'is_fraud': [0.1, 0.972, 0.3, 0.2], 15 | }) 16 | 17 | assert_frame_equal(out, expected, atol=0.01) 18 | -------------------------------------------------------------------------------- /Ch04/04_07/metrics.jsonl: -------------------------------------------------------------------------------- 1 | {"time":"2021-07-13T14:36:52.380Z","metric":"mem","value":227542823.0} 2 | {"time":"2021-07-13T14:36:52.380Z","metric":"cpu","value":30.3} 3 | {"time":"2021-07-13T14:36:53.337Z","metric":"mem","value":227538529.0} 4 | {"time":"2021-07-13T14:36:53.337Z","metric":"cpu","value":31.34} 5 | {"time":"2021-07-13T14:36:54.294Z","metric":"mem","value":227526145.0} 6 | {"time":"2021-07-13T14:36:54.294Z","metric":"cpu","value":31.05} 7 | {"time":"2021-07-13T14:36:55.251Z","metric":"mem","value":227523318.0} 8 | {"time":"2021-07-13T14:36:55.251Z","metric":"cpu","value":31.75} 9 | {"time":"2021-07-13T14:36:56.208Z","metric":"mem","value":227516337.0} 10 | {"time":"2021-07-13T14:36:56.208Z","metric":"cpu","value":32.35} 11 | {"time":"2021-07-13T14:36:57.165Z","metric":"cpu","value":33.92} 12 | {"time":"2021-07-13T14:36:57.165Z","metric":"mem","value":227515701.0} 13 | {"time":"2021-07-13T14:36:58.122Z","metric":"mem","value":227514161.0} 14 | {"time":"2021-07-13T14:36:58.122Z","metric":"cpu","value":32.88} 15 | {"time":"2021-07-13T14:36:59.079Z","metric":"cpu","value":32.12} 16 | {"time":"2021-07-13T14:36:59.079Z","metric":"mem","value":227509565.0} 17 | {"time":"2021-07-13T14:37:00.036Z","metric":"cpu","value":30.76} 18 | {"time":"2021-07-13T14:37:00.036Z","metric":"mem","value":227517481.0} 19 | {"time":"2021-07-13T14:37:00.993Z","metric":"cpu","value":31.83} 20 | {"time":"2021-07-13T14:37:00.993Z","metric":"mem","value":227518867.0} 21 | {"time":"2021-07-13T14:37:01.950Z","metric":"cpu","value":31.86} 22 | {"time":"2021-07-13T14:37:01.950Z","metric":"mem","value":227500567.0} 23 | {"time":"2021-07-13T14:37:02.907Z","metric":"cpu","value":30.65} 24 | {"time":"2021-07-13T14:37:02.907Z","metric":"mem","value":227521119.0} 25 | {"time":"2021-07-13T14:37:03.864Z","metric":"cpu","value":30.04} 26 | {"time":"2021-07-13T14:37:03.864Z","metric":"mem","value":227535940.0} 27 | {"time":"2021-07-13T14:37:04.821Z","metric":"mem","value":227549493.0} 28 | {"time":"2021-07-13T14:37:04.821Z","metric":"cpu","value":30.05} 29 | {"time":"2021-07-13T14:37:05.778Z","metric":"mem","value":227569276.0} 30 | {"time":"2021-07-13T14:37:05.778Z","metric":"cpu","value":30.95} 31 | {"time":"2021-07-13T14:37:06.735Z","metric":"mem","value":227573345.0} 32 | {"time":"2021-07-13T14:37:06.735Z","metric":"cpu","value":31.63} 33 | {"time":"2021-07-13T14:37:07.692Z","metric":"mem","value":227568259.0} 34 | {"time":"2021-07-13T14:37:07.692Z","metric":"cpu","value":32.16} 35 | {"time":"2021-07-13T14:37:08.649Z","metric":"cpu","value":32.31} 36 | {"time":"2021-07-13T14:37:08.649Z","metric":"mem","value":227575545.0} 37 | {"time":"2021-07-13T14:37:09.606Z","metric":"cpu","value":32.04} 38 | {"time":"2021-07-13T14:37:09.606Z","metric":"mem","value":227584385.0} 39 | {"time":"2021-07-13T14:37:10.563Z","metric":"cpu","value":32.84} 40 | {"time":"2021-07-13T14:37:10.563Z","metric":"mem","value":227586024.0} 41 | {"time":"2021-07-13T14:37:11.520Z","metric":"mem","value":227584949.0} 42 | {"time":"2021-07-13T14:37:11.520Z","metric":"cpu","value":34.4} 43 | {"time":"2021-07-13T14:37:12.477Z","metric":"mem","value":227583997.0} 44 | {"time":"2021-07-13T14:37:12.477Z","metric":"cpu","value":35.02} 45 | {"time":"2021-07-13T14:37:13.434Z","metric":"mem","value":227587363.0} 46 | {"time":"2021-07-13T14:37:13.434Z","metric":"cpu","value":35.74} 47 | {"time":"2021-07-13T14:37:14.391Z","metric":"mem","value":227600862.0} 48 | {"time":"2021-07-13T14:37:14.391Z","metric":"cpu","value":37.35} 49 | {"time":"2021-07-13T14:37:15.348Z","metric":"cpu","value":36.88} 50 | {"time":"2021-07-13T14:37:15.348Z","metric":"mem","value":227598700.0} 51 | {"time":"2021-07-13T14:37:16.305Z","metric":"cpu","value":36.03} 52 | {"time":"2021-07-13T14:37:16.305Z","metric":"mem","value":227613060.0} 53 | {"time":"2021-07-13T14:37:17.262Z","metric":"cpu","value":34.41} 54 | {"time":"2021-07-13T14:37:17.262Z","metric":"mem","value":227630458.0} 55 | {"time":"2021-07-13T14:37:18.219Z","metric":"cpu","value":34.12} 56 | {"time":"2021-07-13T14:37:18.219Z","metric":"mem","value":227630742.0} 57 | {"time":"2021-07-13T14:37:19.176Z","metric":"cpu","value":33.65} 58 | {"time":"2021-07-13T14:37:19.176Z","metric":"mem","value":227634904.0} 59 | {"time":"2021-07-13T14:37:20.133Z","metric":"cpu","value":34.65} 60 | {"time":"2021-07-13T14:37:20.133Z","metric":"mem","value":227643047.0} 61 | {"time":"2021-07-13T14:37:21.090Z","metric":"mem","value":227630973.0} 62 | {"time":"2021-07-13T14:37:21.090Z","metric":"cpu","value":33.04} 63 | {"time":"2021-07-13T14:37:22.047Z","metric":"cpu","value":32.1} 64 | {"time":"2021-07-13T14:37:22.047Z","metric":"mem","value":227645699.0} 65 | {"time":"2021-07-13T14:37:23.004Z","metric":"mem","value":227627905.0} 66 | {"time":"2021-07-13T14:37:23.004Z","metric":"cpu","value":31.85} 67 | {"time":"2021-07-13T14:37:23.961Z","metric":"cpu","value":30.96} 68 | {"time":"2021-07-13T14:37:23.961Z","metric":"mem","value":227610178.0} 69 | {"time":"2021-07-13T14:37:24.918Z","metric":"cpu","value":30.25} 70 | {"time":"2021-07-13T14:37:24.918Z","metric":"mem","value":227606298.0} 71 | {"time":"2021-07-13T14:37:25.875Z","metric":"cpu","value":30.33} 72 | {"time":"2021-07-13T14:37:25.875Z","metric":"mem","value":227613589.0} 73 | {"time":"2021-07-13T14:37:26.832Z","metric":"mem","value":227624948.0} 74 | {"time":"2021-07-13T14:37:26.832Z","metric":"cpu","value":30.83} 75 | {"time":"2021-07-13T14:37:27.789Z","metric":"cpu","value":30.52} 76 | {"time":"2021-07-13T14:37:27.789Z","metric":"mem","value":227669536.0} 77 | {"time":"2021-07-13T14:37:28.746Z","metric":"cpu","value":31.52} 78 | {"time":"2021-07-13T14:37:28.746Z","metric":"mem","value":227651612.0} 79 | {"time":"2021-07-13T14:37:29.703Z","metric":"cpu","value":34.06} 80 | {"time":"2021-07-13T14:37:29.703Z","metric":"mem","value":227633557.0} 81 | {"time":"2021-07-13T14:37:30.660Z","metric":"cpu","value":34.5} 82 | {"time":"2021-07-13T14:37:30.660Z","metric":"mem","value":227618088.0} 83 | {"time":"2021-07-13T14:37:31.617Z","metric":"cpu","value":33.64} 84 | {"time":"2021-07-13T14:37:31.617Z","metric":"mem","value":227617904.0} 85 | {"time":"2021-07-13T14:37:32.574Z","metric":"cpu","value":33.54} 86 | {"time":"2021-07-13T14:37:32.574Z","metric":"mem","value":227620917.0} 87 | {"time":"2021-07-13T14:37:33.531Z","metric":"cpu","value":32.57} 88 | {"time":"2021-07-13T14:37:33.531Z","metric":"mem","value":227609849.0} 89 | {"time":"2021-07-13T14:37:34.488Z","metric":"mem","value":227618625.0} 90 | {"time":"2021-07-13T14:37:34.488Z","metric":"cpu","value":32.83} 91 | {"time":"2021-07-13T14:37:35.445Z","metric":"cpu","value":32.64} 92 | {"time":"2021-07-13T14:37:35.445Z","metric":"mem","value":227621413.0} 93 | {"time":"2021-07-13T14:37:36.402Z","metric":"cpu","value":32.54} 94 | {"time":"2021-07-13T14:37:36.402Z","metric":"mem","value":227626269.0} 95 | {"time":"2021-07-13T14:37:37.359Z","metric":"cpu","value":32.47} 96 | {"time":"2021-07-13T14:37:37.359Z","metric":"mem","value":227627359.0} 97 | {"time":"2021-07-13T14:37:38.316Z","metric":"cpu","value":31.24} 98 | {"time":"2021-07-13T14:37:38.316Z","metric":"mem","value":227629485.0} 99 | {"time":"2021-07-13T14:37:39.273Z","metric":"mem","value":227635181.0} 100 | {"time":"2021-07-13T14:37:39.273Z","metric":"cpu","value":31.5} 101 | -------------------------------------------------------------------------------- /Ch04/04_07/metrics.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | 4 | def load_metrics(jsonl_file): 5 | return pd.read_json( 6 | jsonl_file, 7 | orient='records', 8 | lines=True, 9 | convert_dates=['time'], 10 | ) 11 | 12 | 13 | # testing 14 | if __name__ == '__main__': 15 | from pathlib import Path 16 | 17 | here = Path(__file__).absolute().parent 18 | jsonl_file = here / 'metrics.jsonl' 19 | 20 | load_metrics(jsonl_file) 21 | -------------------------------------------------------------------------------- /Ch04/04_08/metrics.jsonl: -------------------------------------------------------------------------------- 1 | {"time":"2021-07-13T14:36:52.380Z","metric":"mem","value":227542823.0} 2 | {"time":"2021-07-13T14:36:52.380Z","metric":"cpu","value":30.3} 3 | {"time":"2021-07-13T14:36:53.337Z","metric":"mem","value":227538529.0} 4 | {"time":"2021-07-13T14:36:53.337Z","metric":"cpu","value":31.34} 5 | {"time":"2021-07-13T14:36:54.294Z","metric":"mem","value":227526145.0} 6 | {"time":"2021-07-13T14:36:54.294Z","metric":"cpu","value":31.05} 7 | {"time":"2021-07-13T14:36:55.251Z","metric":"mem","value":227523318.0} 8 | {"time":"2021-07-13T14:36:55.251Z","metric":"cpu","value":31.75} 9 | {"time":"2021-07-13T14:36:56.208Z","metric":"mem","value":227516337.0} 10 | {"time":"2021-07-13T14:36:56.208Z","metric":"cpu","value":32.35} 11 | {"time":"2021-07-13T14:36:57.165Z","metric":"cpu","value":33.92} 12 | {"time":"2021-07-13T14:36:57.165Z","metric":"mem","value":227515701.0} 13 | {"time":"2021-07-13T14:36:58.122Z","metric":"mem","value":227514161.0} 14 | {"time":"2021-07-13T14:36:58.122Z","metric":"cpu","value":32.88} 15 | {"time":"2021-07-13T14:36:59.079Z","metric":"cpu","value":32.12} 16 | {"time":"2021-07-13T14:36:59.079Z","metric":"mem","value":227509565.0} 17 | {"time":"2021-07-13T14:37:00.036Z","metric":"cpu","value":30.76} 18 | {"time":"2021-07-13T14:37:00.036Z","metric":"mem","value":227517481.0} 19 | {"time":"2021-07-13T14:37:00.993Z","metric":"cpu","value":31.83} 20 | {"time":"2021-07-13T14:37:00.993Z","metric":"mem","value":227518867.0} 21 | {"time":"2021-07-13T14:37:01.950Z","metric":"cpu","value":31.86} 22 | {"time":"2021-07-13T14:37:01.950Z","metric":"mem","value":227500567.0} 23 | {"time":"2021-07-13T14:37:02.907Z","metric":"cpu","value":30.65} 24 | {"time":"2021-07-13T14:37:02.907Z","metric":"mem","value":227521119.0} 25 | {"time":"2021-07-13T14:37:03.864Z","metric":"cpu","value":30.04} 26 | {"time":"2021-07-13T14:37:03.864Z","metric":"mem","value":227535940.0} 27 | {"time":"2021-07-13T14:37:04.821Z","metric":"mem","value":227549493.0} 28 | {"time":"2021-07-13T14:37:04.821Z","metric":"cpu","value":30.05} 29 | {"time":"2021-07-13T14:37:05.778Z","metric":"mem","value":227569276.0} 30 | {"time":"2021-07-13T14:37:05.778Z","metric":"cpu","value":30.95} 31 | {"time":"2021-07-13T14:37:06.735Z","metric":"mem","value":227573345.0} 32 | {"time":"2021-07-13T14:37:06.735Z","metric":"cpu","value":31.63} 33 | {"time":"2021-07-13T14:37:07.692Z","metric":"mem","value":227568259.0} 34 | {"time":"2021-07-13T14:37:07.692Z","metric":"cpu","value":32.16} 35 | {"time":"2021-07-13T14:37:08.649Z","metric":"cpu","value":32.31} 36 | {"time":"2021-07-13T14:37:08.649Z","metric":"mem","value":227575545.0} 37 | {"time":"2021-07-13T14:37:09.606Z","metric":"cpu","value":32.04} 38 | {"time":"2021-07-13T14:37:09.606Z","metric":"mem","value":227584385.0} 39 | {"time":"2021-07-13T14:37:10.563Z","metric":"cpu","value":32.84} 40 | {"time":"2021-07-13T14:37:10.563Z","metric":"mem","value":227586024.0} 41 | {"time":"2021-07-13T14:37:11.520Z","metric":"mem","value":227584949.0} 42 | {"time":"2021-07-13T14:37:11.520Z","metric":"cpu","value":34.4} 43 | {"time":"2021-07-13T14:37:12.477Z","metric":"mem","value":227583997.0} 44 | {"time":"2021-07-13T14:37:12.477Z","metric":"cpu","value":35.02} 45 | {"time":"2021-07-13T14:37:13.434Z","metric":"mem","value":227587363.0} 46 | {"time":"2021-07-13T14:37:13.434Z","metric":"cpu","value":35.74} 47 | {"time":"2021-07-13T14:37:14.391Z","metric":"mem","value":227600862.0} 48 | {"time":"2021-07-13T14:37:14.391Z","metric":"cpu","value":37.35} 49 | {"time":"2021-07-13T14:37:15.348Z","metric":"cpu","value":36.88} 50 | {"time":"2021-07-13T14:37:15.348Z","metric":"mem","value":227598700.0} 51 | {"time":"2021-07-13T14:37:16.305Z","metric":"cpu","value":36.03} 52 | {"time":"2021-07-13T14:37:16.305Z","metric":"mem","value":227613060.0} 53 | {"time":"2021-07-13T14:37:17.262Z","metric":"cpu","value":34.41} 54 | {"time":"2021-07-13T14:37:17.262Z","metric":"mem","value":227630458.0} 55 | {"time":"2021-07-13T14:37:18.219Z","metric":"cpu","value":34.12} 56 | {"time":"2021-07-13T14:37:18.219Z","metric":"mem","value":227630742.0} 57 | {"time":"2021-07-13T14:37:19.176Z","metric":"cpu","value":33.65} 58 | {"time":"2021-07-13T14:37:19.176Z","metric":"mem","value":227634904.0} 59 | {"time":"2021-07-13T14:37:20.133Z","metric":"cpu","value":34.65} 60 | {"time":"2021-07-13T14:37:20.133Z","metric":"mem","value":227643047.0} 61 | {"time":"2021-07-13T14:37:21.090Z","metric":"mem","value":227630973.0} 62 | {"time":"2021-07-13T14:37:21.090Z","metric":"cpu","value":33.04} 63 | {"time":"2021-07-13T14:37:22.047Z","metric":"cpu","value":32.1} 64 | {"time":"2021-07-13T14:37:22.047Z","metric":"mem","value":227645699.0} 65 | {"time":"2021-07-13T14:37:23.004Z","metric":"mem","value":227627905.0} 66 | {"time":"2021-07-13T14:37:23.004Z","metric":"cpu","value":31.85} 67 | {"time":"2021-07-13T14:37:23.961Z","metric":"cpu","value":30.96} 68 | {"time":"2021-07-13T14:37:23.961Z","metric":"mem","value":227610178.0} 69 | {"time":"2021-07-13T14:37:24.918Z","metric":"cpu","value":30.25} 70 | {"time":"2021-07-13T14:37:24.918Z","metric":"mem","value":227606298.0} 71 | {"time":"2021-07-13T14:37:25.875Z","metric":"cpu","value":30.33} 72 | {"time":"2021-07-13T14:37:25.875Z","metric":"mem","value":227613589.0} 73 | {"time":"2021-07-13T14:37:26.832Z","metric":"mem","value":227624948.0} 74 | {"time":"2021-07-13T14:37:26.832Z","metric":"cpu","value":30.83} 75 | {"time":"2021-07-13T14:37:27.789Z","metric":"cpu","value":30.52} 76 | {"time":"2021-07-13T14:37:27.789Z","metric":"mem","value":227669536.0} 77 | {"time":"2021-07-13T14:37:28.746Z","metric":"cpu","value":31.52} 78 | {"time":"2021-07-13T14:37:28.746Z","metric":"mem","value":227651612.0} 79 | {"time":"2021-07-13T14:37:29.703Z","metric":"cpu","value":34.06} 80 | {"time":"2021-07-13T14:37:29.703Z","metric":"mem","value":227633557.0} 81 | {"time":"2021-07-13T14:37:30.660Z","metric":"cpu","value":34.5} 82 | {"time":"2021-07-13T14:37:30.660Z","metric":"mem","value":227618088.0} 83 | {"time":"2021-07-13T14:37:31.617Z","metric":"cpu","value":33.64} 84 | {"time":"2021-07-13T14:37:31.617Z","metric":"mem","value":227617904.0} 85 | {"time":"2021-07-13T14:37:32.574Z","metric":"cpu","value":33.54} 86 | {"time":"2021-07-13T14:37:32.574Z","metric":"mem","value":227620917.0} 87 | {"time":"2021-07-13T14:37:33.531Z","metric":"cpu","value":32.57} 88 | {"time":"2021-07-13T14:37:33.531Z","metric":"mem","value":227609849.0} 89 | {"time":"2021-07-13T14:37:34.488Z","metric":"mem","value":227618625.0} 90 | {"time":"2021-07-13T14:37:34.488Z","metric":"cpu","value":32.83} 91 | {"time":"2021-07-13T14:37:35.445Z","metric":"cpu","value":32.64} 92 | {"time":"2021-07-13T14:37:35.445Z","metric":"mem","value":227621413.0} 93 | {"time":"2021-07-13T14:37:36.402Z","metric":"cpu","value":32.54} 94 | {"time":"2021-07-13T14:37:36.402Z","metric":"mem","value":227626269.0} 95 | {"time":"2021-07-13T14:37:37.359Z","metric":"cpu","value":32.47} 96 | {"time":"2021-07-13T14:37:37.359Z","metric":"mem","value":227627359.0} 97 | {"time":"2021-07-13T14:37:38.316Z","metric":"cpu","value":31.24} 98 | {"time":"2021-07-13T14:37:38.316Z","metric":"mem","value":227629485.0} 99 | {"time":"2021-07-13T14:37:39.273Z","metric":"mem","value":227635181.0} 100 | {"time":"2021-07-13T14:37:39.273Z","metric":"cpu","value":31.5} 101 | -------------------------------------------------------------------------------- /Ch04/04_08/metrics.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import pandera as pa 3 | 4 | metrics_schema = pa.DataFrameSchema({ 5 | 'time': pa.Column(pd.DatetimeTZDtype('ns', 'UTC')), 6 | 'metric': pa.Column(pa.String, checks=pa.Check.isin({'cpu', 'mem'})), 7 | 'value': pa.Column(pa.Float, checks=pa.Check.greater_than(0)), 8 | }) 9 | 10 | 11 | @pa.check_output(metrics_schema) 12 | def load_metrics(jsonl_file): 13 | return pd.read_json( 14 | jsonl_file, 15 | orient='records', 16 | lines=True, 17 | convert_dates=['time'], 18 | ) 19 | 20 | 21 | # testing 22 | if __name__ == '__main__': 23 | from pathlib import Path 24 | 25 | here = Path(__file__).absolute().parent 26 | jsonl_file = here / 'metrics.jsonl' 27 | 28 | load_metrics(jsonl_file) 29 | -------------------------------------------------------------------------------- /Ch05/05_04/conftest.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | 3 | import pytest 4 | from sklearn.datasets import load_digits 5 | from sklearn.ensemble import RandomForestClassifier 6 | from sklearn.model_selection import train_test_split 7 | 8 | Data = namedtuple('Data', 'version X y') 9 | 10 | 11 | def _load_data(): 12 | digits = load_digits() 13 | return digits['data'], digits['target'] 14 | 15 | 16 | @pytest.fixture 17 | def regression_data(): 18 | # TODO: Load from regression database 19 | X, y = _load_data() 20 | return Data( 21 | version='2022-02-17', 22 | X=X, 23 | y=y, 24 | ) 25 | 26 | 27 | Model = namedtuple('Model', 'version clf') 28 | 29 | 30 | @pytest.fixture 31 | def model(): 32 | # TODO: Load model from model store 33 | X, y = _load_data() 34 | X_train, _, y_train, _ = train_test_split(X, y, random_state=123) 35 | 36 | clf = RandomForestClassifier(random_state=353) 37 | clf.fit(X_train, y_train) 38 | return Model(version='2022-03-24', clf=clf) 39 | -------------------------------------------------------------------------------- /Ch05/05_04/test_regression.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from sklearn.metrics import accuracy_score 4 | 5 | 6 | def test_regression(model, regression_data): 7 | out = model.clf.predict(regression_data.X) 8 | score = accuracy_score(regression_data.y, out) 9 | report = { 10 | 'model_version': model.version, 11 | 'data_version': regression_data.version, 12 | 'accuracy': score, 13 | } 14 | print(f'regression: {json.dumps(report)}') 15 | # TODO: Report to regression database (Prometheus, InfluxDB ...) -------------------------------------------------------------------------------- /Ch05/05_06/conftest.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | 3 | import pytest 4 | from sklearn.datasets import load_digits 5 | from sklearn.decomposition import PCA 6 | from sklearn.model_selection import train_test_split 7 | from sklearn.pipeline import Pipeline 8 | from sklearn.svm import SVC 9 | 10 | Data = namedtuple('Data', 'version X y') 11 | 12 | 13 | def _load_data(): 14 | digits = load_digits() 15 | return digits['data'], digits['target'] 16 | 17 | 18 | @pytest.fixture 19 | def regression_data(): 20 | # TODO: Load from regression database 21 | X, y = _load_data() 22 | return Data( 23 | version='2022-02-17', 24 | X=X, 25 | y=y, 26 | ) 27 | 28 | 29 | Model = namedtuple('Model', 'version clf') 30 | 31 | @pytest.fixture 32 | def model(): 33 | # TODO: Load model from model store 34 | X, y = _load_data() 35 | X_train, _, y_train, _ = train_test_split(X, y, random_state=123) 36 | 37 | clf = Pipeline(steps=[ 38 | ('pca', PCA(n_components=10)), 39 | ('svc', SVC(random_state=353)) 40 | ]) 41 | 42 | clf.fit(X_train, y_train) 43 | return Model(version='2022-03-24', clf=clf) -------------------------------------------------------------------------------- /Ch05/05_06/test_performance.py: -------------------------------------------------------------------------------- 1 | import json 2 | from timeit import timeit 3 | 4 | from psutil import Process 5 | 6 | 7 | def test_memory(model, regression_data): 8 | proc = Process() 9 | mem_before = proc.memory_info().rss 10 | model.clf.predict(regression_data.X) 11 | mem_after = proc.memory_info().rss 12 | report = { 13 | 'model_version': model.version, 14 | 'data_version': regression_data.version, 15 | 'mem_usage': mem_after - mem_before 16 | } 17 | print(f'memory: {json.dumps(report)}') 18 | # TODO: Report to regression database (Prometheus, InfluxDB ...) 19 | 20 | 21 | def test_performance(model, regression_data): 22 | n_times = 100 23 | duration = timeit( 24 | 'model.clf.predict(regression_data.X)', 25 | number=n_times, 26 | globals=locals(), 27 | ) 28 | report = { 29 | 'model_version': model.version, 30 | 'data_version': regression_data.version, 31 | 'avg_time': duration / n_times, 32 | 'n_times': n_times, 33 | } 34 | print(f'performance: {json.dumps(report)}') 35 | # TODO: Report to regression database (Prometheus, InfluxDB ...) -------------------------------------------------------------------------------- /Ch06/06_02/test_track_nb.py: -------------------------------------------------------------------------------- 1 | import json 2 | from os import environ 3 | from pathlib import Path 4 | from subprocess import run 5 | from sys import executable 6 | 7 | import numpy as np 8 | 9 | here = Path(__file__).absolute().parent 10 | 11 | 12 | def test_track_nb(tmp_path): 13 | csv_file = here / 'track.csv' 14 | nb_file = here / 'track.ipynb' 15 | out_file = tmp_path / 'output.json' 16 | 17 | cmd = [ 18 | executable, '-m', 'jupyter', 'nbconvert', 19 | '--execute', 20 | '--stdout', 21 | '--to', 'notebook', 22 | nb_file, 23 | ] 24 | env = environ.copy() 25 | env['CSV_FILE'] = csv_file 26 | env['OUT_FILE'] = out_file 27 | run(cmd, env=env, check=True) 28 | 29 | with out_file.open() as fp: 30 | output = json.load(fp) 31 | 32 | assert np.allclose(9.580444, output['mean_speed']) 33 | -------------------------------------------------------------------------------- /Ch06/06_02/track.csv: -------------------------------------------------------------------------------- 1 | time,lat,lng,height 2 | 2015-08-20T03:48:07.235Z,32.519585,35.015021,136.1999969482422 3 | 2015-08-20T03:48:24.734Z,32.519606,35.014954,126.5999984741211 4 | 2015-08-20T03:48:25.660Z,32.519612,35.014871,123.0 5 | 2015-08-20T03:48:26.819Z,32.519654,35.014824,120.5 6 | 2015-08-20T03:48:27.828Z,32.519689,35.014776,118.9000015258789 7 | 2015-08-20T03:48:29.720Z,32.519691,35.014704,119.9000015258789 8 | 2015-08-20T03:48:30.669Z,32.519734,35.014657,120.9000015258789 9 | 2015-08-20T03:48:33.793Z,32.519719,35.014563,121.69999694824219 10 | 2015-08-20T03:48:34.869Z,32.519694,35.014549,121.19999694824219 11 | 2015-08-20T03:48:37.708Z,32.519625,35.014515,121.69999694824219 12 | 2015-08-20T03:48:38.839Z,32.519599,35.014505,121.80000305175781 13 | 2015-08-20T03:48:41.980Z,32.519514,35.014481,122.5999984741211 14 | 2015-08-20T03:48:42.725Z,32.519486,35.014472,123.0 15 | 2015-08-20T03:48:45.896Z,32.519405,35.014439,122.69999694824219 16 | 2015-08-20T03:48:46.662Z,32.519379,35.014432,122.69999694824219 17 | 2015-08-20T03:48:49.829Z,32.519309,35.014414,122.69999694824219 18 | 2015-08-20T03:48:50.665Z,32.519287,35.0144,123.30000305175781 19 | 2015-08-20T03:48:53.692Z,32.519211,35.014372,122.30000305175781 20 | 2015-08-20T03:48:54.662Z,32.519187,35.014365,122.5999984741211 21 | 2015-08-20T03:48:58.869Z,32.519106,35.014337,122.0 22 | 2015-08-20T03:48:59.663Z,32.519084,35.014331,121.80000305175781 23 | 2015-08-20T03:49:03.861Z,32.519009,35.014303,122.9000015258789 24 | 2015-08-20T03:49:04.663Z,32.518989,35.014306,122.9000015258789 25 | 2015-08-20T03:49:07.742Z,32.518916,35.01434,123.0999984741211 26 | 2015-08-20T03:50:13.679Z,32.517636,35.013531,115.19999694824219 27 | 2015-08-20T03:50:16.767Z,32.517589,35.013606,114.30000305175781 28 | 2015-08-20T03:50:17.719Z,32.517574,35.01363,114.19999694824219 29 | 2015-08-20T03:50:20.748Z,32.517529,35.013705,113.80000305175781 30 | 2015-08-20T03:50:21.681Z,32.517512,35.01373,114.19999694824219 31 | 2015-08-20T03:50:24.735Z,32.517459,35.013809,114.0 32 | 2015-08-20T03:50:25.677Z,32.517442,35.013834,113.0999984741211 33 | 2015-08-20T03:50:28.738Z,32.517389,35.013903,112.5999984741211 34 | 2015-08-20T03:50:29.673Z,32.517373,35.013925,113.5 35 | 2015-08-20T03:50:32.816Z,32.517323,35.013991,113.5999984741211 36 | 2015-08-20T03:50:33.682Z,32.517306,35.014012,113.4000015258789 37 | 2015-08-20T03:50:36.749Z,32.517254,35.014075,114.5999984741211 38 | 2015-08-20T03:50:37.744Z,32.517236,35.014095,114.19999694824219 39 | 2015-08-20T03:50:40.735Z,32.517183,35.014148,115.5 40 | 2015-08-20T03:50:41.682Z,32.517164,35.014167,116.0 41 | 2015-08-20T03:50:44.757Z,32.517111,35.014235,116.5999984741211 42 | 2015-08-20T03:50:45.674Z,32.517095,35.014257,116.5999984741211 43 | 2015-08-20T03:50:48.716Z,32.517044,35.014332,115.30000305175781 44 | 2015-08-20T03:50:49.684Z,32.517026,35.014357,115.0 45 | 2015-08-20T03:50:52.757Z,32.516972,35.014431,114.9000015258789 46 | 2015-08-20T03:50:53.688Z,32.516954,35.014456,114.9000015258789 47 | 2015-08-20T03:50:56.782Z,32.516891,35.014519,115.69999694824219 48 | 2015-08-20T03:50:57.731Z,32.516868,35.014522,114.0 49 | 2015-08-20T03:51:00.870Z,32.516818,35.01447,113.5999984741211 50 | 2015-08-20T03:51:01.772Z,32.516803,35.014442,113.0 51 | 2015-08-20T03:51:04.744Z,32.516752,35.01436,112.0 52 | 2015-08-20T03:51:05.747Z,32.516734,35.014335,112.30000305175781 53 | 2015-08-20T03:51:08.831Z,32.516677,35.014257,110.9000015258789 54 | 2015-08-20T03:51:09.744Z,32.516657,35.014233,110.80000305175781 55 | 2015-08-20T03:51:12.743Z,32.516591,35.014176,108.69999694824219 56 | 2015-08-20T03:51:13.702Z,32.516568,35.014162,108.4000015258789 57 | 2015-08-20T03:51:16.777Z,32.516506,35.014103,109.19999694824219 58 | 2015-08-20T03:51:17.729Z,32.516486,35.014084,108.4000015258789 59 | 2015-08-20T03:51:20.733Z,32.516421,35.014026,108.5 60 | 2015-08-20T03:51:21.670Z,32.5164,35.014006,108.5999984741211 61 | 2015-08-20T03:51:24.691Z,32.516338,35.013941,107.5999984741211 62 | 2015-08-20T03:51:25.672Z,32.516318,35.01392,107.9000015258789 63 | 2015-08-20T03:51:28.745Z,32.516253,35.013869,108.0 64 | 2015-08-20T03:51:29.677Z,32.51623,35.013852,108.0 65 | 2015-08-20T03:51:32.707Z,32.516174,35.013795,105.5999984741211 66 | 2015-08-20T03:51:33.674Z,32.516156,35.013775,104.80000305175781 67 | 2015-08-20T03:51:36.758Z,32.516108,35.01371,105.30000305175781 68 | 2015-08-20T03:51:37.675Z,32.516089,35.01369,103.9000015258789 69 | 2015-08-20T03:51:40.733Z,32.516033,35.013633,103.69999694824219 70 | 2015-08-20T03:51:41.674Z,32.516014,35.013615,103.5 71 | 2015-08-20T03:51:44.744Z,32.51596,35.013559,102.80000305175781 72 | 2015-08-20T03:51:45.679Z,32.515943,35.01354,103.0 73 | 2015-08-20T03:51:48.760Z,32.515891,35.013482,102.0 74 | 2015-08-20T03:51:49.684Z,32.515873,35.013463,102.0 75 | 2015-08-20T03:51:52.709Z,32.515826,35.013403,102.0 76 | 2015-08-20T03:51:53.672Z,32.515812,35.013382,102.0 77 | 2015-08-20T03:51:56.894Z,32.515761,35.013325,101.80000305175781 78 | 2015-08-20T03:51:57.767Z,32.515743,35.013307,101.30000305175781 79 | 2015-08-20T03:52:00.768Z,32.515693,35.013246,100.5 80 | 2015-08-20T03:52:01.676Z,32.515675,35.013226,100.80000305175781 81 | 2015-08-20T03:52:04.866Z,32.515622,35.013162,101.0999984741211 82 | 2015-08-20T03:52:05.780Z,32.515605,35.013139,100.69999694824219 83 | 2015-08-20T03:52:08.753Z,32.51555,35.013074,99.19999694824219 84 | 2015-08-20T03:52:09.700Z,32.515531,35.013055,99.19999694824219 85 | 2015-08-20T03:52:12.855Z,32.515471,35.012994,99.30000305175781 86 | 2015-08-20T03:52:13.780Z,32.515451,35.012974,99.0 87 | 2015-08-20T03:52:16.775Z,32.515388,35.012912,99.69999694824219 88 | 2015-08-20T03:52:17.704Z,32.515368,35.012891,99.69999694824219 89 | 2015-08-20T03:52:20.907Z,32.515311,35.012826,99.0999984741211 90 | 2015-08-20T03:52:21.779Z,32.515291,35.012806,98.80000305175781 91 | 2015-08-20T03:52:24.813Z,32.515226,35.01276,98.5 92 | 2015-08-20T03:52:25.698Z,32.515203,35.012747,97.9000015258789 93 | 2015-08-20T03:52:28.748Z,32.515136,35.012709,97.4000015258789 94 | 2015-08-20T03:52:29.672Z,32.515113,35.012694,97.0 95 | 2015-08-20T03:52:32.719Z,32.515052,35.012636,96.30000305175781 96 | 2015-08-20T03:52:33.698Z,32.515034,35.012617,96.30000305175781 97 | 2015-08-20T03:52:37.790Z,32.514986,35.012537,96.0999984741211 98 | 2015-08-20T03:52:38.678Z,32.514964,35.012521,96.5999984741211 99 | 2015-08-20T03:52:41.752Z,32.514901,35.01246,95.19999694824219 100 | 2015-08-20T03:52:42.684Z,32.514882,35.012438,94.69999694824219 101 | 2015-08-20T03:52:45.758Z,32.514836,35.012371,94.30000305175781 102 | 2015-08-20T03:52:46.679Z,32.514813,35.012367,94.9000015258789 103 | 2015-08-20T03:52:49.764Z,32.514761,35.012418,95.0 104 | 2015-08-20T03:52:50.678Z,32.514746,35.012445,95.4000015258789 105 | 2015-08-20T03:52:54.323Z,32.514689,35.012516,96.4000015258789 106 | 2015-08-20T03:52:54.673Z,32.514671,35.01254,96.5 107 | 2015-08-20T03:52:57.937Z,32.514631,35.012615,98.0 108 | 2015-08-20T03:52:58.682Z,32.514619,35.012636,97.69999694824219 109 | 2015-08-20T03:53:02.766Z,32.514562,35.012717,99.0999984741211 110 | 2015-08-20T03:53:03.678Z,32.514545,35.012741,99.19999694824219 111 | 2015-08-20T03:53:05.884Z,32.514507,35.012782,99.4000015258789 112 | 2015-08-20T03:53:33.775Z,32.514134,35.013324,105.19999694824219 113 | 2015-08-20T03:53:36.808Z,32.514092,35.013393,105.80000305175781 114 | 2015-08-20T03:53:37.677Z,32.514077,35.013417,106.19999694824219 115 | 2015-08-20T03:53:40.734Z,32.514028,35.013493,106.30000305175781 116 | 2015-08-20T03:53:41.686Z,32.514011,35.013514,107.19999694824219 117 | 2015-08-20T03:53:44.713Z,32.513947,35.013472,106.69999694824219 118 | 2015-08-20T03:53:45.682Z,32.513928,35.013445,107.30000305175781 119 | 2015-08-20T03:53:49.290Z,32.513882,35.013363,103.9000015258789 120 | 2015-08-20T03:53:49.679Z,32.513869,35.013336,102.5999984741211 121 | 2015-08-20T03:53:52.831Z,32.513823,35.01327,105.4000015258789 122 | 2015-08-20T03:53:53.737Z,32.513807,35.013251,105.0999984741211 123 | 2015-08-20T03:53:56.820Z,32.513777,35.013178,105.19999694824219 124 | 2015-08-20T03:53:57.772Z,32.513769,35.013153,104.69999694824219 125 | 2015-08-20T03:54:00.947Z,32.513739,35.013078,104.19999694824219 126 | 2015-08-20T03:54:01.713Z,32.513726,35.013053,103.9000015258789 127 | 2015-08-20T03:54:04.796Z,32.513683,35.012981,102.80000305175781 128 | 2015-08-20T03:54:05.739Z,32.513666,35.012958,102.30000305175781 129 | 2015-08-20T03:54:08.837Z,32.513614,35.012891,100.4000015258789 130 | 2015-08-20T03:54:09.736Z,32.513598,35.012869,100.4000015258789 131 | 2015-08-20T03:54:12.795Z,32.513558,35.012791,100.5999984741211 132 | 2015-08-20T03:54:13.691Z,32.513546,35.012765,100.4000015258789 133 | 2015-08-20T03:54:17.425Z,32.513513,35.012687,99.69999694824219 134 | 2015-08-20T03:54:17.724Z,32.513502,35.01266,99.9000015258789 135 | 2015-08-20T03:54:20.759Z,32.513469,35.012578,102.0 136 | 2015-08-20T03:54:21.692Z,32.51346,35.01255,102.0999984741211 137 | 2015-08-20T03:54:24.813Z,32.513433,35.012471,101.5999984741211 138 | 2015-08-20T03:54:25.692Z,32.513426,35.012445,100.9000015258789 139 | 2015-08-20T03:54:28.783Z,32.513402,35.012367,100.0999984741211 140 | 2015-08-20T03:54:29.687Z,32.513394,35.012338,99.19999694824219 141 | 2015-08-20T03:54:32.827Z,32.513355,35.01226,99.5 142 | 2015-08-20T03:54:33.691Z,32.51334,35.012236,99.4000015258789 143 | 2015-08-20T03:54:36.774Z,32.513301,35.012159,98.30000305175781 144 | 2015-08-20T03:54:37.686Z,32.513288,35.012135,96.69999694824219 145 | 2015-08-20T03:54:40.787Z,32.513249,35.012063,95.19999694824219 146 | 2015-08-20T03:54:41.686Z,32.513237,35.012037,95.0 147 | 2015-08-20T03:54:44.769Z,32.513199,35.011961,94.69999694824219 148 | 2015-08-20T03:54:45.688Z,32.513184,35.011937,95.19999694824219 149 | 2015-08-20T03:54:48.745Z,32.51314,35.011868,93.30000305175781 150 | 2015-08-20T03:54:49.689Z,32.513126,35.011844,93.19999694824219 151 | 2015-08-20T03:54:52.757Z,32.513097,35.011766,92.5 152 | 2015-08-20T03:54:53.684Z,32.513088,35.011741,91.4000015258789 153 | 2015-08-20T03:54:57.781Z,32.513055,35.011644,91.19999694824219 154 | 2015-08-20T03:54:58.688Z,32.513048,35.011618,90.9000015258789 155 | 2015-08-20T03:55:01.904Z,32.513024,35.011538,90.69999694824219 156 | 2015-08-20T03:55:02.695Z,32.513016,35.01151,91.0 157 | 2015-08-20T03:55:05.766Z,32.512991,35.011432,90.0 158 | 2015-08-20T03:55:06.696Z,32.512982,35.011409,88.9000015258789 159 | 2015-08-20T03:55:10.766Z,32.512965,35.01131,88.0 160 | 2015-08-20T03:55:11.690Z,32.512962,35.011284,88.0999984741211 161 | 2015-08-20T03:55:14.787Z,32.512944,35.011205,87.9000015258789 162 | 2015-08-20T03:55:15.692Z,32.512936,35.011179,87.80000305175781 163 | 2015-08-20T03:55:18.789Z,32.512908,35.0111,86.80000305175781 164 | 2015-08-20T03:55:19.724Z,32.512897,35.011073,87.69999694824219 165 | 2015-08-20T03:55:22.747Z,32.512862,35.010991,88.0 166 | 2015-08-20T03:55:23.801Z,32.51285,35.010963,88.30000305175781 167 | 2015-08-20T03:55:26.824Z,32.51282,35.010873,88.0999984741211 168 | 2015-08-20T03:55:27.730Z,32.51281,35.010844,87.30000305175781 169 | 2015-08-20T03:55:30.791Z,32.512774,35.010765,87.4000015258789 170 | 2015-08-20T03:55:31.786Z,32.512762,35.010739,87.5999984741211 171 | 2015-08-20T03:55:34.837Z,32.512726,35.010661,86.80000305175781 172 | 2015-08-20T03:55:35.724Z,32.512714,35.010636,86.69999694824219 173 | 2015-08-20T03:55:38.786Z,32.512676,35.010562,87.19999694824219 174 | 2015-08-20T03:55:39.770Z,32.512664,35.010537,87.30000305175781 175 | 2015-08-20T03:55:42.826Z,32.512645,35.010455,87.0999984741211 176 | 2015-08-20T03:55:43.699Z,32.512642,35.010426,86.5999984741211 177 | 2015-08-20T03:55:46.771Z,32.512637,35.01034,85.0 178 | 2015-08-20T03:55:47.692Z,32.512636,35.010313,84.9000015258789 179 | 2015-08-20T03:55:51.779Z,32.512629,35.010212,84.9000015258789 180 | 2015-08-20T03:55:52.694Z,32.512625,35.010189,84.4000015258789 181 | 2015-08-20T03:55:56.849Z,32.512594,35.010093,82.9000015258789 182 | 2015-08-20T03:55:57.697Z,32.512584,35.010068,83.69999694824219 183 | 2015-08-20T03:56:00.786Z,32.512551,35.009988,84.0999984741211 184 | 2015-08-20T03:56:01.697Z,32.512539,35.009961,84.5 185 | 2015-08-20T03:56:04.757Z,32.512505,35.009883,84.0 186 | 2015-08-20T03:56:05.839Z,32.512493,35.009857,84.0 187 | 2015-08-20T03:56:08.782Z,32.512456,35.009785,83.0 188 | 2015-08-20T03:56:09.705Z,32.512445,35.009762,82.9000015258789 189 | 2015-08-20T03:56:12.777Z,32.512408,35.009692,82.4000015258789 190 | 2015-08-20T03:56:13.701Z,32.512395,35.009668,82.80000305175781 191 | 2015-08-20T03:56:16.840Z,32.512362,35.009595,81.5999984741211 192 | 2015-08-20T03:56:17.698Z,32.512347,35.009574,81.30000305175781 193 | 2015-08-20T03:56:20.757Z,32.512291,35.009517,81.80000305175781 194 | 2015-08-20T03:56:21.708Z,32.512267,35.009495,81.69999694824219 195 | 2015-08-20T03:56:24.832Z,32.512213,35.00943,82.30000305175781 196 | 2015-08-20T03:56:25.698Z,32.512199,35.00941,82.0 197 | 2015-08-20T03:56:28.974Z,32.512144,35.009361,80.69999694824219 198 | 2015-08-20T03:57:10.713Z,32.511551,35.009294,84.0 199 | 2015-08-20T03:57:14.785Z,32.511533,35.009386,86.9000015258789 200 | 2015-08-20T03:57:15.920Z,32.511524,35.009408,87.5 201 | 2015-08-20T03:57:19.818Z,32.511467,35.009485,87.30000305175781 202 | 2015-08-20T03:57:20.757Z,32.51145,35.0095,86.80000305175781 203 | 2015-08-20T03:57:24.836Z,32.511379,35.009559,89.5999984741211 204 | 2015-08-20T03:57:25.763Z,32.511362,35.009573,89.5 205 | 2015-08-20T03:57:29.824Z,32.511303,35.009636,89.0 206 | 2015-08-20T03:57:30.702Z,32.511293,35.009653,88.80000305175781 207 | 2015-08-20T03:57:35.785Z,32.511252,35.009745,91.19999694824219 208 | 2015-08-20T03:57:36.709Z,32.511245,35.009764,91.69999694824219 209 | 2015-08-20T03:57:41.812Z,32.511216,35.009855,91.30000305175781 210 | 2015-08-20T03:57:42.760Z,32.511212,35.009875,91.80000305175781 211 | 2015-08-20T03:57:47.810Z,32.511215,35.009977,87.69999694824219 212 | 2015-08-20T03:57:48.711Z,32.511218,35.009998,88.5999984741211 213 | 2015-08-20T03:57:53.815Z,32.511226,35.010102,86.19999694824219 214 | 2015-08-20T03:57:54.704Z,32.511225,35.010123,86.5999984741211 215 | 2015-08-20T03:57:59.780Z,32.511209,35.010227,86.9000015258789 216 | 2015-08-20T03:58:00.710Z,32.511202,35.010248,87.9000015258789 217 | 2015-08-20T03:58:04.797Z,32.511172,35.010329,88.80000305175781 218 | 2015-08-20T03:58:05.710Z,32.511162,35.010348,88.5 219 | 2015-08-20T03:58:09.754Z,32.511117,35.010419,90.30000305175781 220 | 2015-08-20T03:58:23.793Z,32.510997,35.010643,93.5 221 | 2015-08-20T03:58:28.757Z,32.510988,35.010748,93.19999694824219 222 | 2015-08-20T03:58:29.705Z,32.510981,35.010764,93.5999984741211 223 | 2015-08-20T03:58:34.772Z,32.510925,35.010825,93.30000305175781 224 | 2015-08-20T03:58:35.709Z,32.510912,35.010837,93.80000305175781 225 | 2015-08-20T03:58:40.773Z,32.510838,35.010887,95.4000015258789 226 | 2015-08-20T03:58:41.710Z,32.510821,35.010891,94.69999694824219 227 | 2015-08-20T03:58:46.790Z,32.510745,35.010903,97.69999694824219 228 | 2015-08-20T03:58:47.755Z,32.510729,35.01091,98.4000015258789 229 | 2015-08-20T03:58:52.795Z,32.510651,35.010939,100.5 230 | 2015-08-20T03:58:53.723Z,32.510637,35.010948,99.69999694824219 231 | 2015-08-20T03:58:58.841Z,32.510557,35.010988,98.80000305175781 232 | 2015-08-20T03:58:59.753Z,32.510539,35.010993,97.80000305175781 233 | 2015-08-20T03:59:04.834Z,32.510462,35.011028,98.19999694824219 234 | 2015-08-20T03:59:05.760Z,32.510448,35.011037,98.0999984741211 235 | 2015-08-20T03:59:10.877Z,32.510369,35.011071,98.0 236 | 2015-08-20T03:59:11.758Z,32.510353,35.011076,99.30000305175781 237 | 2015-08-20T03:59:16.821Z,32.510278,35.011083,100.19999694824219 238 | 2015-08-20T03:59:17.799Z,32.510262,35.011083,100.0 239 | 2015-08-20T03:59:22.869Z,32.510184,35.011083,100.5999984741211 240 | 2015-08-20T03:59:23.773Z,32.510168,35.011081,101.0 241 | 2015-08-20T03:59:29.840Z,32.510085,35.011108,103.69999694824219 242 | 2015-08-20T03:59:30.719Z,32.510071,35.011108,103.19999694824219 243 | 2015-08-20T03:59:35.811Z,32.509998,35.011101,104.0 244 | 2015-08-20T03:59:36.722Z,32.50998,35.011102,105.30000305175781 245 | 2015-08-20T03:59:41.823Z,32.509892,35.011123,109.5999984741211 246 | 2015-08-20T03:59:42.900Z,32.509875,35.011126,109.80000305175781 247 | 2015-08-20T03:59:47.759Z,32.509797,35.011142,112.30000305175781 248 | 2015-08-20T03:59:48.718Z,32.509782,35.011142,112.80000305175781 249 | 2015-08-20T03:59:54.855Z,32.509693,35.011128,110.80000305175781 250 | 2015-08-20T03:59:55.709Z,32.509679,35.01113,110.4000015258789 251 | 2015-08-20T04:00:02.764Z,32.509592,35.011152,109.19999694824219 252 | 2015-08-20T04:00:03.761Z,32.509576,35.011153,108.4000015258789 253 | 2015-08-20T04:00:08.786Z,32.509491,35.011162,109.80000305175781 254 | 2015-08-20T04:00:09.727Z,32.509474,35.011171,110.0999984741211 255 | 2015-08-20T04:00:13.815Z,32.50941,35.011228,111.5999984741211 256 | 2015-08-20T04:00:14.721Z,32.509395,35.011246,111.80000305175781 257 | 2015-08-20T04:00:18.879Z,32.509335,35.011324,111.0999984741211 258 | 2015-08-20T04:00:19.739Z,32.509325,35.011348,111.0 259 | 2015-08-20T04:00:22.758Z,32.50931,35.011425,110.30000305175781 260 | 2015-08-20T04:00:26.765Z,32.509363,35.011497,109.4000015258789 261 | 2015-08-20T04:00:31.754Z,32.509427,35.011568,109.5 262 | 2015-08-20T04:00:32.724Z,32.509434,35.01158,109.4000015258789 263 | 2015-08-20T04:00:38.798Z,32.509408,35.01168,108.30000305175781 264 | 2015-08-20T04:00:39.732Z,32.509398,35.011698,108.30000305175781 265 | 2015-08-20T04:00:44.912Z,32.509339,35.011764,106.5999984741211 266 | 2015-08-20T04:00:45.722Z,32.509328,35.011776,106.69999694824219 267 | 2015-08-20T04:00:50.955Z,32.509276,35.011845,103.0 268 | 2015-08-20T04:00:51.724Z,32.509261,35.011857,102.19999694824219 269 | 2015-08-20T04:00:56.837Z,32.509182,35.011906,100.9000015258789 270 | 2015-08-20T04:00:57.790Z,32.509167,35.011919,100.69999694824219 271 | 2015-08-20T04:01:02.893Z,32.509097,35.011982,100.5 272 | 2015-08-20T04:01:03.767Z,32.509082,35.011995,100.0999984741211 273 | 2015-08-20T04:01:07.773Z,32.509023,35.012046,98.69999694824219 274 | 2015-08-20T04:01:08.723Z,32.509008,35.01206,98.4000015258789 275 | 2015-08-20T04:01:12.892Z,32.508949,35.012118,98.19999694824219 276 | 2015-08-20T04:01:13.730Z,32.508936,35.012133,97.80000305175781 277 | 2015-08-20T04:01:17.889Z,32.508888,35.012198,96.9000015258789 278 | 2015-08-20T04:01:18.737Z,32.508875,35.012215,96.9000015258789 279 | 2015-08-20T04:01:22.773Z,32.508815,35.012275,96.0 280 | 2015-08-20T04:01:23.738Z,32.508801,35.012291,95.69999694824219 281 | 2015-08-20T04:01:27.842Z,32.508754,35.012367,95.5 282 | 2015-08-20T04:01:28.724Z,32.508745,35.01239,95.30000305175781 283 | 2015-08-20T04:01:32.771Z,32.508719,35.012489,94.9000015258789 284 | 2015-08-20T04:01:33.737Z,32.508714,35.012511,94.19999694824219 285 | 2015-08-20T04:01:37.826Z,32.508683,35.012593,93.30000305175781 286 | 2015-08-20T04:01:38.805Z,32.50867,35.012613,93.69999694824219 287 | 2015-08-20T04:01:42.885Z,32.508632,35.012693,92.0999984741211 288 | 2015-08-20T04:01:43.769Z,32.508626,35.012715,91.30000305175781 289 | 2015-08-20T04:01:47.862Z,32.508605,35.012807,90.5999984741211 290 | 2015-08-20T04:01:48.809Z,32.508601,35.012831,90.19999694824219 291 | 2015-08-20T04:01:52.842Z,32.508585,35.012924,89.5999984741211 292 | 2015-08-20T04:01:53.730Z,32.508577,35.012946,88.4000015258789 293 | 2015-08-20T04:01:56.975Z,32.508545,35.013015,88.0999984741211 294 | 2015-08-20T04:01:57.734Z,32.508537,35.013042,88.4000015258789 295 | 2015-08-20T04:02:01.816Z,32.508514,35.013143,87.30000305175781 296 | 2015-08-20T04:02:02.766Z,32.508506,35.013164,87.19999694824219 297 | 2015-08-20T04:02:06.811Z,32.508474,35.01325,87.0999984741211 298 | 2015-08-20T04:02:07.740Z,32.508467,35.013272,87.19999694824219 299 | 2015-08-20T04:02:11.804Z,32.508432,35.013361,87.4000015258789 300 | 2015-08-20T04:02:12.733Z,32.508421,35.013383,88.0 301 | 2015-08-20T04:02:16.800Z,32.508376,35.013474,88.0999984741211 302 | 2015-08-20T04:02:17.734Z,32.508364,35.013495,87.30000305175781 303 | 2015-08-20T04:02:22.799Z,32.508313,35.013573,85.19999694824219 304 | 2015-08-20T04:02:23.743Z,32.5083,35.013586,85.0 305 | 2015-08-20T04:02:28.794Z,32.508228,35.013635,80.80000305175781 306 | 2015-08-20T04:02:29.755Z,32.508212,35.013642,80.19999694824219 307 | 2015-08-20T04:02:33.807Z,32.508138,35.013675,79.9000015258789 308 | 2015-08-20T04:02:34.804Z,32.508119,35.013685,80.0999984741211 309 | 2015-08-20T04:02:38.812Z,32.508092,35.013769,80.69999694824219 310 | 2015-08-20T04:02:39.879Z,32.508098,35.0138,81.0 311 | 2015-08-20T04:02:42.909Z,32.508128,35.013877,79.69999694824219 312 | 2015-08-20T04:02:43.754Z,32.508136,35.013901,80.80000305175781 313 | 2015-08-20T04:02:48.018Z,32.508157,35.014002,80.5999984741211 314 | 2015-08-20T04:02:48.746Z,32.508158,35.014028,80.5999984741211 315 | 2015-08-20T04:02:56.857Z,32.508152,35.014134,80.69999694824219 316 | 2015-08-20T04:02:57.964Z,32.508154,35.014166,80.4000015258789 317 | 2015-08-20T04:03:00.838Z,32.508153,35.014262,80.0999984741211 318 | 2015-08-20T04:03:01.834Z,32.508154,35.014292,79.80000305175781 319 | 2015-08-20T04:03:04.926Z,32.508161,35.014381,78.80000305175781 320 | 2015-08-20T04:03:05.735Z,32.508159,35.014411,79.19999694824219 321 | 2015-08-20T04:03:08.875Z,32.508163,35.014501,79.0 322 | 2015-08-20T04:03:09.740Z,32.508176,35.014527,79.9000015258789 323 | 2015-08-20T04:03:12.773Z,32.508198,35.014609,80.4000015258789 324 | 2015-08-20T04:03:13.733Z,32.508205,35.014635,81.4000015258789 325 | 2015-08-20T04:03:17.917Z,32.508223,35.01473,81.0 326 | 2015-08-20T04:03:18.741Z,32.508227,35.014754,81.5 327 | 2015-08-20T04:03:22.777Z,32.508247,35.014854,81.5999984741211 328 | 2015-08-20T04:03:23.734Z,32.508254,35.01488,81.19999694824219 329 | 2015-08-20T04:03:26.806Z,32.508274,35.014959,81.0 330 | 2015-08-20T04:03:27.736Z,32.508278,35.014985,81.19999694824219 331 | 2015-08-20T04:03:31.781Z,32.508291,35.015084,83.30000305175781 332 | 2015-08-20T04:03:32.733Z,32.508294,35.015108,83.5999984741211 333 | 2015-08-20T04:03:36.817Z,32.508315,35.015203,84.5999984741211 334 | 2015-08-20T04:03:37.735Z,32.508318,35.015227,84.30000305175781 335 | 2015-08-20T04:03:41.910Z,32.508329,35.015329,84.80000305175781 336 | 2015-08-20T04:03:42.735Z,32.508329,35.015354,84.9000015258789 337 | 2015-08-20T04:03:46.780Z,32.508337,35.015452,85.30000305175781 338 | 2015-08-20T04:03:47.739Z,32.50834,35.015477,85.0 339 | 2015-08-20T04:03:51.812Z,32.50836,35.015572,84.5999984741211 340 | 2015-08-20T04:03:52.753Z,32.50837,35.015594,83.5999984741211 341 | 2015-08-20T04:03:56.823Z,32.508393,35.015688,84.0999984741211 342 | 2015-08-20T04:03:57.748Z,32.508398,35.015712,83.5 343 | 2015-08-20T04:04:01.886Z,32.508414,35.015804,83.19999694824219 344 | 2015-08-20T04:04:02.806Z,32.508417,35.015827,82.80000305175781 345 | 2015-08-20T04:04:06.819Z,32.508435,35.015917,81.19999694824219 346 | 2015-08-20T04:04:07.737Z,32.508441,35.015939,80.5999984741211 347 | 2015-08-20T04:04:11.934Z,32.508457,35.016031,81.0999984741211 348 | 2015-08-20T04:04:12.809Z,32.50846,35.016053,81.19999694824219 349 | 2015-08-20T04:04:16.845Z,32.508471,35.016144,79.0999984741211 350 | 2015-08-20T04:04:17.756Z,32.508474,35.016168,79.19999694824219 351 | 2015-08-20T04:04:21.812Z,32.508485,35.016264,77.9000015258789 352 | 2015-08-20T04:04:22.738Z,32.508485,35.016287,77.5 353 | 2015-08-20T04:04:26.828Z,32.508482,35.016389,78.30000305175781 354 | 2015-08-20T04:04:27.741Z,32.508484,35.016415,79.5 355 | 2015-08-20T04:04:30.815Z,32.508498,35.016495,79.19999694824219 356 | 2015-08-20T04:04:31.780Z,32.508502,35.016521,79.19999694824219 357 | 2015-08-20T04:04:35.782Z,32.508519,35.016616,80.19999694824219 358 | 2015-08-20T04:04:36.758Z,32.508519,35.01664,80.5999984741211 359 | 2015-08-20T04:04:40.819Z,32.508524,35.016736,80.9000015258789 360 | 2015-08-20T04:04:41.739Z,32.508526,35.01676,80.5999984741211 361 | 2015-08-20T04:04:45.822Z,32.50854,35.016862,82.0999984741211 362 | 2015-08-20T04:04:46.754Z,32.508545,35.016889,81.69999694824219 363 | 2015-08-20T04:04:49.819Z,32.50856,35.016969,81.69999694824219 364 | 2015-08-20T04:04:50.751Z,32.508565,35.016995,81.69999694824219 365 | 2015-08-20T04:04:54.827Z,32.508588,35.017093,81.5 366 | 2015-08-20T04:04:55.741Z,32.508594,35.017118,81.30000305175781 367 | 2015-08-20T04:04:59.953Z,32.508622,35.017211,81.69999694824219 368 | 2015-08-20T04:05:00.898Z,32.508629,35.017233,81.9000015258789 369 | 2015-08-20T04:05:04.825Z,32.50865,35.017327,83.69999694824219 370 | 2015-08-20T04:05:05.753Z,32.508654,35.017352,83.9000015258789 371 | 2015-08-20T04:05:09.820Z,32.508676,35.017453,85.80000305175781 372 | 2015-08-20T04:05:10.752Z,32.508681,35.017477,85.19999694824219 373 | 2015-08-20T04:05:14.782Z,32.508707,35.017574,85.0 374 | 2015-08-20T04:05:15.746Z,32.508715,35.017599,84.69999694824219 375 | 2015-08-20T04:05:18.810Z,32.508727,35.017679,84.30000305175781 376 | 2015-08-20T04:05:19.754Z,32.508727,35.017706,85.0999984741211 377 | 2015-08-20T04:05:23.821Z,32.508727,35.017811,85.19999694824219 378 | 2015-08-20T04:05:24.748Z,32.508732,35.017839,85.19999694824219 379 | 2015-08-20T04:05:27.786Z,32.508745,35.017921,84.4000015258789 380 | 2015-08-20T04:05:28.751Z,32.508745,35.01795,84.69999694824219 381 | 2015-08-20T04:05:31.779Z,32.508764,35.018032,84.69999694824219 382 | 2015-08-20T04:05:32.778Z,32.508771,35.01806,84.5 383 | 2015-08-20T04:05:35.827Z,32.508779,35.018146,84.69999694824219 384 | 2015-08-20T04:05:36.757Z,32.508782,35.018173,83.30000305175781 385 | 2015-08-20T04:05:40.868Z,32.508792,35.018274,83.5 386 | 2015-08-20T04:05:41.830Z,32.508795,35.018298,84.5 387 | 2015-08-20T04:05:45.830Z,32.508801,35.018397,83.69999694824219 388 | 2015-08-20T04:05:46.745Z,32.508802,35.018421,82.80000305175781 389 | 2015-08-20T04:05:50.865Z,32.508796,35.018515,80.9000015258789 390 | 2015-08-20T04:05:51.774Z,32.508792,35.018539,81.5 391 | 2015-08-20T04:05:55.985Z,32.508787,35.018637,82.5999984741211 392 | 2015-08-20T04:05:56.877Z,32.508784,35.01866,82.9000015258789 393 | 2015-08-20T04:06:01.100Z,32.508772,35.018762,84.80000305175781 394 | 2015-08-20T04:06:01.788Z,32.508772,35.018789,84.80000305175781 395 | 2015-08-20T04:06:04.895Z,32.508772,35.018874,84.69999694824219 396 | 2015-08-20T04:06:05.832Z,32.508774,35.018902,83.80000305175781 397 | 2015-08-20T04:06:08.882Z,32.50878,35.018988,82.0999984741211 398 | 2015-08-20T04:06:10.029Z,32.508783,35.019016,81.80000305175781 399 | 2015-08-20T04:06:12.907Z,32.508795,35.019104,80.5999984741211 400 | 2015-08-20T04:06:13.760Z,32.508798,35.019135,79.5 401 | 2015-08-20T04:06:16.824Z,32.508818,35.01922,80.5 402 | 2015-08-20T04:06:17.748Z,32.508826,35.019248,79.5 403 | 2015-08-20T04:06:20.825Z,32.508859,35.019327,79.4000015258789 404 | 2015-08-20T04:06:21.750Z,32.508868,35.019355,79.9000015258789 405 | 2015-08-20T04:06:24.830Z,32.508895,35.019439,80.0 406 | 2015-08-20T04:06:25.755Z,32.508902,35.019465,80.4000015258789 407 | 2015-08-20T04:06:28.846Z,32.508922,35.019544,79.0 408 | 2015-08-20T04:06:29.760Z,32.50893,35.019568,79.30000305175781 409 | 2015-08-20T04:06:33.815Z,32.50896,35.019661,79.5 410 | 2015-08-20T04:06:34.814Z,32.508969,35.019684,80.19999694824219 411 | 2015-08-20T04:06:38.879Z,32.509004,35.019779,80.4000015258789 412 | 2015-08-20T04:06:39.758Z,32.509014,35.019804,79.19999694824219 413 | 2015-08-20T04:06:42.786Z,32.509039,35.01988,79.9000015258789 414 | 2015-08-20T04:06:43.754Z,32.509046,35.019905,79.4000015258789 415 | 2015-08-20T04:06:47.808Z,32.509086,35.019981,80.0 416 | 2015-08-20T04:06:48.764Z,32.509093,35.019999,79.69999694824219 417 | 2015-08-20T04:06:53.841Z,32.509119,35.020097,80.0 418 | 2015-08-20T04:06:54.756Z,32.509125,35.020119,79.30000305175781 419 | 2015-08-20T04:06:58.908Z,32.509153,35.020204,81.5999984741211 420 | 2015-08-20T04:06:59.766Z,32.509157,35.020226,81.80000305175781 421 | 2015-08-20T04:07:04.844Z,32.509181,35.020326,83.19999694824219 422 | 2015-08-20T04:07:05.792Z,32.509186,35.020345,82.0999984741211 423 | 2015-08-20T04:07:09.806Z,32.509207,35.020426,82.5999984741211 424 | 2015-08-20T04:07:10.753Z,32.509211,35.020448,81.9000015258789 425 | 2015-08-20T04:07:14.850Z,32.509228,35.020537,82.30000305175781 426 | 2015-08-20T04:07:15.779Z,32.509234,35.020559,82.5 427 | 2015-08-20T04:07:19.852Z,32.50925,35.02065,87.4000015258789 428 | 2015-08-20T04:07:20.770Z,32.509254,35.020673,86.9000015258789 429 | 2015-08-20T04:07:24.887Z,32.509278,35.020759,88.0999984741211 430 | 2015-08-20T04:07:25.772Z,32.509284,35.020781,88.69999694824219 431 | 2015-08-20T04:07:29.868Z,32.509304,35.020867,89.5999984741211 432 | 2015-08-20T04:07:30.822Z,32.509309,35.020888,88.4000015258789 433 | 2015-08-20T04:07:34.900Z,32.509322,35.020976,89.0999984741211 434 | 2015-08-20T04:07:35.760Z,32.509325,35.020997,87.9000015258789 435 | 2015-08-20T04:07:41.002Z,32.509351,35.021097,86.4000015258789 436 | 2015-08-20T04:07:41.805Z,32.509356,35.021117,86.5999984741211 437 | 2015-08-20T04:07:47.040Z,32.509381,35.021218,87.69999694824219 438 | 2015-08-20T04:07:47.830Z,32.509384,35.021238,87.69999694824219 439 | 2015-08-20T04:07:51.835Z,32.509403,35.021322,88.19999694824219 440 | 2015-08-20T04:07:52.792Z,32.509405,35.021342,88.30000305175781 441 | 2015-08-20T04:07:57.866Z,32.509433,35.021441,88.80000305175781 442 | 2015-08-20T04:07:58.770Z,32.509438,35.021462,88.5 443 | 2015-08-20T04:08:02.860Z,32.509445,35.021548,88.0 444 | 2015-08-20T04:08:03.761Z,32.509445,35.021571,88.0 445 | 2015-08-20T04:08:07.842Z,32.509489,35.021641,88.0 446 | 2015-08-20T04:08:08.772Z,32.509511,35.021648,88.5999984741211 447 | 2015-08-20T04:08:12.796Z,32.509599,35.02164,88.5999984741211 448 | 2015-08-20T04:08:13.757Z,32.509619,35.021636,88.30000305175781 449 | 2015-08-20T04:08:17.819Z,32.509691,35.021609,88.80000305175781 450 | 2015-08-20T04:08:18.850Z,32.509711,35.021606,89.5999984741211 451 | 2015-08-20T04:08:22.966Z,32.509787,35.021593,91.0999984741211 452 | 2015-08-20T04:08:23.757Z,32.509805,35.021589,91.30000305175781 453 | 2015-08-20T04:08:28.794Z,32.509887,35.021561,91.80000305175781 454 | 2015-08-20T04:08:29.759Z,32.509901,35.021551,92.19999694824219 455 | 2015-08-20T04:08:35.900Z,32.509982,35.021518,91.0 456 | 2015-08-20T04:08:36.758Z,32.509996,35.021516,91.0999984741211 457 | 2015-08-20T04:08:41.814Z,32.510072,35.021502,91.5 458 | 2015-08-20T04:08:42.760Z,32.510086,35.021494,92.0 459 | 2015-08-20T04:08:47.832Z,32.510153,35.021456,94.5 460 | 2015-08-20T04:08:48.774Z,32.510169,35.021447,94.0 461 | 2015-08-20T04:08:53.897Z,32.51024,35.021412,95.5999984741211 462 | 2015-08-20T04:08:54.788Z,32.510255,35.021404,95.80000305175781 463 | 2015-08-20T04:08:59.841Z,32.510334,35.021376,97.9000015258789 464 | 2015-08-20T04:09:00.764Z,32.51035,35.021375,98.5 465 | 2015-08-20T04:09:05.833Z,32.510434,35.021379,100.30000305175781 466 | 2015-08-20T04:09:06.775Z,32.510449,35.021382,100.30000305175781 467 | 2015-08-20T04:09:11.860Z,32.51053,35.021413,101.0 468 | 2015-08-20T04:09:12.835Z,32.510546,35.021419,101.0999984741211 469 | 2015-08-20T04:09:17.860Z,32.510605,35.021491,99.5999984741211 470 | 2015-08-20T04:09:18.765Z,32.510614,35.021508,99.19999694824219 471 | 2015-08-20T04:09:23.855Z,32.510657,35.021598,98.9000015258789 472 | 2015-08-20T04:09:24.776Z,32.510665,35.021618,98.69999694824219 473 | 2015-08-20T04:09:28.839Z,32.510702,35.021694,99.19999694824219 474 | 2015-08-20T04:09:29.768Z,32.510714,35.021709,99.19999694824219 475 | 2015-08-20T04:09:34.851Z,32.510775,35.021785,99.4000015258789 476 | 2015-08-20T04:09:35.768Z,32.510788,35.021799,98.9000015258789 477 | 2015-08-20T04:09:39.837Z,32.510838,35.021858,99.0999984741211 478 | 2015-08-20T04:09:40.769Z,32.510849,35.021877,98.80000305175781 479 | 2015-08-20T04:09:44.872Z,32.51089,35.02196,97.4000015258789 480 | 2015-08-20T04:09:45.774Z,32.510899,35.02198,98.19999694824219 481 | 2015-08-20T04:09:49.854Z,32.510933,35.022068,98.5 482 | 2015-08-20T04:09:50.768Z,32.51094,35.022091,97.69999694824219 483 | 2015-08-20T04:09:54.847Z,32.510969,35.022182,97.69999694824219 484 | 2015-08-20T04:09:55.768Z,32.510979,35.022202,97.5999984741211 485 | 2015-08-20T04:09:59.850Z,32.511022,35.022282,97.5 486 | 2015-08-20T04:10:00.776Z,32.511032,35.0223,97.5999984741211 487 | 2015-08-20T04:10:05.856Z,32.511085,35.022376,98.9000015258789 488 | 2015-08-20T04:10:06.766Z,32.511094,35.022391,98.69999694824219 489 | 2015-08-20T04:10:12.468Z,32.511146,35.022471,99.80000305175781 490 | 2015-08-20T04:10:12.830Z,32.511155,35.022488,99.9000015258789 491 | 2015-08-20T04:10:17.817Z,32.511197,35.022577,99.69999694824219 492 | 2015-08-20T04:10:18.783Z,32.511205,35.022595,99.5999984741211 493 | 2015-08-20T04:10:23.827Z,32.511237,35.022677,100.69999694824219 494 | 2015-08-20T04:10:24.781Z,32.511247,35.02269,100.4000015258789 495 | 2015-08-20T04:10:29.980Z,32.511298,35.022761,101.80000305175781 496 | 2015-08-20T04:10:30.838Z,32.511309,35.022774,102.30000305175781 497 | 2015-08-20T04:10:35.889Z,32.51139,35.022733,103.30000305175781 498 | 2015-08-20T04:10:36.783Z,32.511398,35.022713,103.30000305175781 499 | 2015-08-20T04:10:40.836Z,32.511421,35.022627,99.9000015258789 500 | 2015-08-20T04:10:41.777Z,32.511418,35.0226,100.0999984741211 501 | 2015-08-20T04:10:45.853Z,32.511412,35.022497,99.5999984741211 502 | 2015-08-20T04:10:46.785Z,32.511417,35.022477,99.69999694824219 503 | 2015-08-20T04:10:51.857Z,32.511476,35.022398,103.5 504 | 2015-08-20T04:10:52.769Z,32.511487,35.022382,103.30000305175781 505 | 2015-08-20T04:10:57.843Z,32.511493,35.022287,100.69999694824219 506 | 2015-08-20T04:10:58.777Z,32.511486,35.022269,100.4000015258789 507 | 2015-08-20T04:11:02.933Z,32.511446,35.022192,100.69999694824219 508 | 2015-08-20T04:11:03.781Z,32.511434,35.022173,101.5 509 | 2015-08-20T04:11:07.870Z,32.511387,35.022099,103.80000305175781 510 | 2015-08-20T04:11:08.771Z,32.511378,35.022078,104.30000305175781 511 | 2015-08-20T04:11:12.832Z,32.511372,35.02199,105.5 512 | 2015-08-20T04:11:13.785Z,32.511375,35.021969,104.4000015258789 513 | 2015-08-20T04:11:18.859Z,32.511364,35.021865,104.4000015258789 514 | 2015-08-20T04:11:19.774Z,32.511358,35.021844,104.30000305175781 515 | 2015-08-20T04:11:23.916Z,32.511348,35.021755,104.30000305175781 516 | 2015-08-20T04:11:24.856Z,32.511341,35.021733,104.5999984741211 517 | 2015-08-20T04:11:28.859Z,32.511297,35.021653,103.5999984741211 518 | 2015-08-20T04:11:29.785Z,32.511285,35.021634,103.5999984741211 519 | 2015-08-20T04:11:33.916Z,32.511249,35.021544,102.69999694824219 520 | 2015-08-20T04:11:34.777Z,32.511242,35.021523,102.0 521 | 2015-08-20T04:11:38.845Z,32.511193,35.021447,101.69999694824219 522 | 2015-08-20T04:11:39.776Z,32.511181,35.02143,101.9000015258789 523 | 2015-08-20T04:11:43.854Z,32.511127,35.021367,101.4000015258789 524 | 2015-08-20T04:11:44.781Z,32.511111,35.021355,100.69999694824219 525 | 2015-08-20T04:11:48.862Z,32.511036,35.021326,99.69999694824219 526 | 2015-08-20T04:11:49.796Z,32.511016,35.021322,100.0999984741211 527 | 2015-08-20T04:11:53.868Z,32.510939,35.021304,99.4000015258789 528 | 2015-08-20T04:11:54.783Z,32.51092,35.021295,99.30000305175781 529 | 2015-08-20T04:11:58.880Z,32.510854,35.021241,99.5 530 | 2015-08-20T04:11:59.783Z,32.51084,35.021223,98.69999694824219 531 | 2015-08-20T04:12:03.871Z,32.510782,35.021152,97.30000305175781 532 | 2015-08-20T04:12:04.793Z,32.510766,35.021134,97.5999984741211 533 | 2015-08-20T04:12:08.851Z,32.510714,35.021052,96.5999984741211 534 | 2015-08-20T04:12:09.802Z,32.510703,35.02103,96.9000015258789 535 | 2015-08-20T04:12:13.871Z,32.510683,35.020927,96.0999984741211 536 | 2015-08-20T04:12:14.784Z,32.510684,35.020899,96.0999984741211 537 | 2015-08-20T04:12:17.844Z,32.510691,35.020811,96.5999984741211 538 | 2015-08-20T04:12:18.868Z,32.510695,35.02078,97.0 539 | 2015-08-20T04:12:21.929Z,32.51071,35.020689,96.69999694824219 540 | 2015-08-20T04:12:22.857Z,32.510717,35.02066,96.5999984741211 541 | 2015-08-20T04:12:25.926Z,32.51074,35.020582,96.0999984741211 542 | 2015-08-20T04:12:26.841Z,32.510747,35.020556,95.5999984741211 543 | 2015-08-20T04:12:30.906Z,32.510777,35.020461,94.30000305175781 544 | 2015-08-20T04:12:32.078Z,32.510786,35.020438,94.19999694824219 545 | 2015-08-20T04:12:35.899Z,32.510816,35.02034,92.4000015258789 546 | 2015-08-20T04:12:37.006Z,32.51082,35.020313,92.5999984741211 547 | 2015-08-20T04:12:39.957Z,32.510831,35.020222,93.9000015258789 548 | 2015-08-20T04:12:40.800Z,32.510836,35.020193,93.30000305175781 549 | 2015-08-20T04:12:43.876Z,32.510856,35.020111,93.5 550 | 2015-08-20T04:12:44.798Z,32.510863,35.020084,93.5 551 | 2015-08-20T04:12:47.876Z,32.510892,35.02001,92.9000015258789 552 | 2015-08-20T04:12:48.814Z,32.510902,35.019987,92.69999694824219 553 | 2015-08-20T04:12:52.978Z,32.510944,35.019899,92.30000305175781 554 | 2015-08-20T04:12:53.847Z,32.510955,35.019877,92.0 555 | 2015-08-20T04:12:57.829Z,32.510988,35.019784,92.19999694824219 556 | 2015-08-20T04:12:58.800Z,32.510993,35.019759,91.9000015258789 557 | 2015-08-20T04:13:01.913Z,32.511,35.019676,90.5999984741211 558 | 2015-08-20T04:13:03.025Z,32.511004,35.019648,90.5999984741211 559 | 2015-08-20T04:13:05.853Z,32.511023,35.019567,90.0 560 | 2015-08-20T04:13:06.809Z,32.511031,35.019541,89.5999984741211 561 | 2015-08-20T04:13:09.907Z,32.511058,35.01947,88.69999694824219 562 | 2015-08-20T04:13:11.796Z,32.511085,35.019434,88.5 563 | 2015-08-20T04:13:15.810Z,32.511152,35.019368,89.5999984741211 564 | 2015-08-20T04:13:16.782Z,32.51117,35.019353,89.0999984741211 565 | 2015-08-20T04:13:19.841Z,32.511213,35.019291,90.30000305175781 566 | 2015-08-20T04:13:20.799Z,32.511225,35.019267,91.4000015258789 567 | 2015-08-20T04:13:24.818Z,32.511276,35.019184,91.80000305175781 568 | 2015-08-20T04:13:25.969Z,32.511286,35.019163,92.0999984741211 569 | 2015-08-20T04:13:29.993Z,32.511319,35.01907,92.19999694824219 570 | 2015-08-20T04:13:30.782Z,32.51133,35.019048,92.69999694824219 571 | 2015-08-20T04:13:34.847Z,32.511367,35.018962,92.19999694824219 572 | 2015-08-20T04:13:35.784Z,32.511371,35.01894,91.9000015258789 573 | 2015-08-20T04:13:40.817Z,32.511413,35.01886,92.0999984741211 574 | 2015-08-20T04:13:41.783Z,32.511419,35.018845,92.0 575 | 2015-08-20T04:13:47.873Z,32.511452,35.018747,90.4000015258789 576 | 2015-08-20T04:13:48.828Z,32.511457,35.018728,91.0 577 | 2015-08-20T04:13:52.897Z,32.511486,35.018646,92.4000015258789 578 | 2015-08-20T04:13:53.799Z,32.511495,35.018627,91.9000015258789 579 | 2015-08-20T04:13:57.883Z,32.511541,35.018559,92.5 580 | 2015-08-20T04:13:58.794Z,32.511551,35.018542,91.80000305175781 581 | 2015-08-20T04:14:03.880Z,32.511598,35.01846,92.80000305175781 582 | 2015-08-20T04:14:04.928Z,32.511604,35.018444,92.5999984741211 583 | 2015-08-20T04:14:10.074Z,32.511663,35.018369,92.80000305175781 584 | 2015-08-20T04:14:10.882Z,32.511675,35.018355,92.4000015258789 585 | 2015-08-20T04:14:16.882Z,32.511724,35.018267,90.4000015258789 586 | 2015-08-20T04:14:17.787Z,32.511738,35.018253,90.5 587 | 2015-08-20T04:14:21.900Z,32.511797,35.018196,89.0999984741211 588 | 2015-08-20T04:14:22.795Z,32.511806,35.018176,88.80000305175781 589 | 2015-08-20T04:14:27.035Z,32.511863,35.018103,93.5 590 | 2015-08-20T04:14:27.814Z,32.511876,35.018086,93.30000305175781 591 | 2015-08-20T04:14:32.930Z,32.51191,35.01799,91.30000305175781 592 | 2015-08-20T04:14:33.823Z,32.511919,35.017974,91.0 593 | 2015-08-20T04:14:39.152Z,32.511969,35.0179,93.0 594 | 2015-08-20T04:14:39.822Z,32.511981,35.017886,92.30000305175781 595 | 2015-08-20T04:14:45.935Z,32.512028,35.017796,94.19999694824219 596 | 2015-08-20T04:14:46.797Z,32.512037,35.017785,94.19999694824219 597 | 2015-08-20T04:14:52.855Z,32.5121,35.017713,93.9000015258789 598 | 2015-08-20T04:14:53.800Z,32.512113,35.017704,94.69999694824219 599 | 2015-08-20T04:14:58.953Z,32.512166,35.017636,96.30000305175781 600 | 2015-08-20T04:14:59.818Z,32.512176,35.017623,96.0999984741211 601 | 2015-08-20T04:15:05.903Z,32.512235,35.017543,96.80000305175781 602 | 2015-08-20T04:15:06.857Z,32.512245,35.01753,97.0 603 | 2015-08-20T04:15:12.020Z,32.512297,35.017461,94.19999694824219 604 | 2015-08-20T04:15:12.817Z,32.512305,35.017448,93.69999694824219 605 | 2015-08-20T04:15:19.098Z,32.512358,35.017372,95.19999694824219 606 | 2015-08-20T04:15:19.947Z,32.512367,35.017358,94.9000015258789 607 | 2015-08-20T04:15:24.889Z,32.512411,35.017285,94.30000305175781 608 | 2015-08-20T04:15:25.969Z,32.512421,35.01727,95.0 609 | 2015-08-20T04:15:31.057Z,32.51248,35.017192,96.4000015258789 610 | 2015-08-20T04:15:31.836Z,32.512492,35.017175,96.19999694824219 611 | 2015-08-20T04:15:36.910Z,32.512551,35.017096,98.19999694824219 612 | 2015-08-20T04:15:37.812Z,32.512563,35.017081,99.0 613 | 2015-08-20T04:15:42.857Z,32.512622,35.017014,97.19999694824219 614 | 2015-08-20T04:15:43.904Z,32.512629,35.016998,96.9000015258789 615 | 2015-08-20T04:15:48.929Z,32.512679,35.016924,98.0 616 | 2015-08-20T04:15:49.830Z,32.512686,35.016908,97.80000305175781 617 | 2015-08-20T04:15:54.946Z,32.512727,35.016819,98.69999694824219 618 | 2015-08-20T04:15:55.863Z,32.512735,35.0168,97.9000015258789 619 | 2015-08-20T04:15:59.939Z,32.512763,35.016714,97.0 620 | 2015-08-20T04:16:00.878Z,32.512769,35.016691,98.0 621 | 2015-08-20T04:16:05.942Z,32.512842,35.016637,99.80000305175781 622 | 2015-08-20T04:16:06.875Z,32.512859,35.016648,100.30000305175781 623 | 2015-08-20T04:16:10.956Z,32.512922,35.016715,100.0 624 | 2015-08-20T04:16:11.879Z,32.512936,35.016735,100.5 625 | 2015-08-20T04:16:15.900Z,32.512992,35.016803,101.5 626 | 2015-08-20T04:16:16.890Z,32.513005,35.016819,100.69999694824219 627 | 2015-08-20T04:16:20.894Z,32.51307,35.016871,102.4000015258789 628 | 2015-08-20T04:16:21.815Z,32.513084,35.016884,102.5 629 | 2015-08-20T04:16:27.117Z,32.513151,35.016949,105.4000015258789 630 | 2015-08-20T04:16:27.981Z,32.513166,35.016961,105.30000305175781 631 | 2015-08-20T04:16:31.960Z,32.513221,35.01702,106.5999984741211 632 | 2015-08-20T04:16:32.888Z,32.513232,35.017037,107.30000305175781 633 | 2015-08-20T04:16:36.966Z,32.513276,35.017107,106.19999694824219 634 | 2015-08-20T04:16:37.866Z,32.513287,35.017123,107.4000015258789 635 | 2015-08-20T04:16:43.057Z,32.51333,35.017208,108.80000305175781 636 | 2015-08-20T04:16:43.873Z,32.51334,35.017226,110.30000305175781 637 | 2015-08-20T04:16:47.848Z,32.513398,35.017278,109.5 638 | 2015-08-20T04:16:48.815Z,32.513411,35.017291,109.9000015258789 639 | 2015-08-20T04:16:52.875Z,32.513464,35.017348,111.19999694824219 640 | 2015-08-20T04:16:53.817Z,32.513477,35.017364,112.5 641 | 2015-08-20T04:16:57.999Z,32.513534,35.017427,113.4000015258789 642 | 2015-08-20T04:16:58.839Z,32.513548,35.017441,113.69999694824219 643 | 2015-08-20T04:17:03.026Z,32.513618,35.017485,113.0 644 | 2015-08-20T04:17:03.872Z,32.513639,35.01749,112.80000305175781 645 | 2015-08-20T04:17:07.843Z,32.513718,35.017455,113.5999984741211 646 | 2015-08-20T04:17:08.815Z,32.513731,35.017436,113.69999694824219 647 | 2015-08-20T04:17:11.930Z,32.51377,35.017373,114.0999984741211 648 | 2015-08-20T04:17:12.887Z,32.513784,35.017349,114.0 649 | 2015-08-20T04:17:15.874Z,32.513828,35.017284,114.5 650 | 2015-08-20T04:17:16.827Z,32.513843,35.017263,114.5999984741211 651 | 2015-08-20T04:17:19.920Z,32.513887,35.017201,114.4000015258789 652 | 2015-08-20T04:17:20.855Z,32.513897,35.017175,113.9000015258789 653 | 2015-08-20T04:17:24.052Z,32.51393,35.017102,113.5 654 | 2015-08-20T04:17:25.054Z,32.513935,35.017077,113.5999984741211 655 | 2015-08-20T04:17:27.916Z,32.51393,35.016994,113.9000015258789 656 | 2015-08-20T04:17:28.819Z,32.513929,35.016965,114.9000015258789 657 | 2015-08-20T04:17:31.911Z,32.513936,35.016881,114.9000015258789 658 | 2015-08-20T04:17:32.827Z,32.513941,35.016855,114.30000305175781 659 | 2015-08-20T04:17:36.970Z,32.513958,35.016764,113.5999984741211 660 | 2015-08-20T04:17:37.876Z,32.513959,35.016742,113.5999984741211 661 | 2015-08-20T04:17:41.925Z,32.513989,35.01666,113.5999984741211 662 | 2015-08-20T04:17:42.821Z,32.513999,35.016639,113.69999694824219 663 | 2015-08-20T04:17:46.931Z,32.514054,35.016579,111.9000015258789 664 | 2015-08-20T04:17:47.947Z,32.514065,35.016562,112.80000305175781 665 | 2015-08-20T04:17:51.892Z,32.514112,35.016492,113.69999694824219 666 | 2015-08-20T04:17:52.841Z,32.514126,35.016471,113.80000305175781 667 | 2015-08-20T04:17:56.908Z,32.51417,35.016384,114.19999694824219 668 | 2015-08-20T04:17:57.824Z,32.514178,35.016362,114.30000305175781 669 | 2015-08-20T04:18:01.921Z,32.51421,35.016274,114.30000305175781 670 | 2015-08-20T04:18:02.823Z,32.514221,35.016254,114.19999694824219 671 | 2015-08-20T04:18:06.896Z,32.514278,35.016184,114.80000305175781 672 | 2015-08-20T04:18:07.813Z,32.514296,35.016171,115.5999984741211 673 | 2015-08-20T04:18:10.895Z,32.514355,35.016146,115.5999984741211 674 | 2015-08-20T04:18:13.814Z,32.514421,35.016143,116.30000305175781 675 | 2015-08-20T04:18:17.869Z,32.514502,35.016162,117.5999984741211 676 | 2015-08-20T04:18:18.813Z,32.514522,35.016165,117.5 677 | 2015-08-20T04:18:22.862Z,32.514598,35.016182,117.4000015258789 678 | 2015-08-20T04:18:23.814Z,32.514616,35.016187,117.0999984741211 679 | 2015-08-20T04:18:27.863Z,32.514686,35.016171,116.69999694824219 680 | 2015-08-20T04:18:28.816Z,32.514703,35.016158,116.5999984741211 681 | 2015-08-20T04:18:32.870Z,32.514754,35.016085,116.5999984741211 682 | 2015-08-20T04:18:33.815Z,32.514765,35.01607,115.80000305175781 683 | 2015-08-20T04:18:37.847Z,32.514825,35.016018,117.30000305175781 684 | 2015-08-20T04:18:38.816Z,32.514843,35.016007,117.69999694824219 685 | 2015-08-20T04:18:42.882Z,32.514921,35.015984,117.5999984741211 686 | 2015-08-20T04:18:43.815Z,32.514942,35.015984,118.30000305175781 687 | 2015-08-20T04:18:47.897Z,32.51503,35.01597,118.30000305175781 688 | 2015-08-20T04:18:48.836Z,32.515053,35.01597,118.0999984741211 689 | 2015-08-20T04:18:50.877Z,32.515114,35.015958,116.4000015258789 690 | 2015-08-20T04:18:51.819Z,32.515146,35.015951,117.0999984741211 691 | 2015-08-20T04:18:54.007Z,32.515209,35.015942,117.0999984741211 692 | 2015-08-20T04:18:54.893Z,32.51524,35.015937,117.5 693 | 2015-08-20T04:18:57.939Z,32.515328,35.015943,118.5999984741211 694 | 2015-08-20T04:18:58.845Z,32.515358,35.015946,118.5 695 | 2015-08-20T04:19:01.992Z,32.515443,35.015964,118.30000305175781 696 | 2015-08-20T04:19:02.889Z,32.515462,35.015973,118.30000305175781 697 | 2015-08-20T04:19:06.990Z,32.515544,35.01601,118.69999694824219 698 | 2015-08-20T04:19:07.888Z,32.51556,35.016017,118.5999984741211 699 | 2015-08-20T04:19:11.886Z,32.515638,35.016042,118.5999984741211 700 | 2015-08-20T04:19:12.819Z,32.51566,35.016051,118.0 701 | 2015-08-20T04:19:16.911Z,32.515738,35.016069,117.9000015258789 702 | 2015-08-20T04:19:17.842Z,32.515757,35.016076,117.19999694824219 703 | 2015-08-20T04:19:21.908Z,32.515844,35.016087,116.4000015258789 704 | 2015-08-20T04:19:22.820Z,32.51587,35.016071,116.19999694824219 705 | 2015-08-20T04:19:25.934Z,32.515933,35.016016,116.0 706 | 2015-08-20T04:19:26.831Z,32.515953,35.015993,116.80000305175781 707 | 2015-08-20T04:19:29.879Z,32.516001,35.015918,116.5 708 | 2015-08-20T04:19:30.833Z,32.51602,35.015894,117.0 709 | 2015-08-20T04:19:34.152Z,32.516074,35.015828,116.5 710 | 2015-08-20T04:19:34.904Z,32.516091,35.015804,116.5 711 | 2015-08-20T04:19:37.851Z,32.516142,35.01573,116.5999984741211 712 | 2015-08-20T04:19:38.820Z,32.516157,35.015705,116.5 713 | 2015-08-20T04:19:41.881Z,32.516211,35.01564,115.4000015258789 714 | 2015-08-20T04:19:42.825Z,32.516225,35.015617,114.0999984741211 715 | 2015-08-20T04:19:45.963Z,32.516278,35.015551,113.5 716 | 2015-08-20T04:19:46.890Z,32.516301,35.015533,112.5 717 | 2015-08-20T04:19:49.987Z,32.516361,35.015468,112.0 718 | 2015-08-20T04:19:50.878Z,32.51638,35.015444,112.69999694824219 719 | 2015-08-20T04:19:53.937Z,32.516442,35.015369,112.5 720 | 2015-08-20T04:19:54.896Z,32.516462,35.015343,112.5999984741211 721 | 2015-08-20T04:19:58.048Z,32.516517,35.015264,112.30000305175781 722 | 2015-08-20T04:19:58.898Z,32.516537,35.015238,112.0999984741211 723 | 2015-08-20T04:20:01.965Z,32.516592,35.015157,110.0999984741211 724 | 2015-08-20T04:20:02.886Z,32.51661,35.015129,109.80000305175781 725 | 2015-08-20T04:20:05.959Z,32.516665,35.015048,107.69999694824219 726 | 2015-08-20T04:20:06.823Z,32.516683,35.015023,107.5 727 | 2015-08-20T04:20:09.926Z,32.516736,35.014943,107.5999984741211 728 | 2015-08-20T04:20:10.824Z,32.516754,35.014916,107.0999984741211 729 | 2015-08-20T04:20:14.040Z,32.5168,35.014835,106.0999984741211 730 | 2015-08-20T04:20:14.888Z,32.516818,35.01481,105.19999694824219 731 | 2015-08-20T04:20:17.897Z,32.516873,35.014737,106.4000015258789 732 | 2015-08-20T04:20:18.844Z,32.516889,35.014709,106.4000015258789 733 | 2015-08-20T04:20:21.996Z,32.516933,35.014617,103.5 734 | 2015-08-20T04:20:22.897Z,32.516945,35.014584,103.0999984741211 735 | 2015-08-20T04:20:24.905Z,32.516971,35.014518,103.80000305175781 736 | 2015-08-20T04:20:25.835Z,32.516984,35.014484,104.19999694824219 737 | 2015-08-20T04:20:28.982Z,32.51702,35.014387,104.80000305175781 738 | 2015-08-20T04:20:29.923Z,32.517035,35.014355,105.19999694824219 739 | 2015-08-20T04:20:32.863Z,32.517087,35.014279,102.9000015258789 740 | 2015-08-20T04:20:33.994Z,32.517098,35.014264,102.4000015258789 741 | 2015-08-20T04:20:42.329Z,32.517142,35.014212,103.4000015258789 742 | -------------------------------------------------------------------------------- /Ch06/06_02/track.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "abd119de-5319-43c1-8866-fdbad80616ac", 6 | "metadata": {}, 7 | "source": [ 8 | "# Calculate Running Speed" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "d423b72a-e2bd-4c32-add6-297ee43f423f", 14 | "metadata": {}, 15 | "source": [ 16 | "## Load Data" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 10, 22 | "id": "9a86be15-068f-4e79-8c09-042e8d7ea8b0", 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "import pandas as pd\n", 27 | "from os import environ" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": 11, 33 | "id": "b1d2c42f-70fb-4258-9221-4bca2a768d6e", 34 | "metadata": {}, 35 | "outputs": [], 36 | "source": [ 37 | "csv_file = environ.get('CSV_FILE', 'track.csv')\n", 38 | "df = pd.read_csv(csv_file, parse_dates=['time'])" 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "id": "80004a1e-c15d-4a1b-a41a-ee4ee4f149a3", 44 | "metadata": {}, 45 | "source": [ 46 | "## Calculate Speed\n", 47 | "\n", 48 | "For simplicity, we're using Euclidean distance." 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": 5, 54 | "id": "4b2b73fa-7088-4dfd-800e-5bc613a6428a", 55 | "metadata": {}, 56 | "outputs": [], 57 | "source": [ 58 | "import numpy as np\n", 59 | "\n", 60 | "lat1, lat2 = df['lat'], df['lat'].shift()\n", 61 | "lng1, lng2 = df['lng'], df['lng'].shift()\n", 62 | "\n", 63 | "\n", 64 | "lat_km = 92\n", 65 | "lng_km = 111\n", 66 | "\n", 67 | "delta_lat = (lat1 - lat2) * lat_km\n", 68 | "delta_lng = (lng1 - lng2) * lng_km\n", 69 | "dist_km = np.hypot(delta_lat, delta_lng)" 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "id": "90524989-d517-4189-87a0-812f0a0c90f3", 75 | "metadata": {}, 76 | "source": [ 77 | "## Calculate Time & Speed" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": 6, 83 | "id": "8298d052-624d-444b-b862-6721c2de35a1", 84 | "metadata": {}, 85 | "outputs": [], 86 | "source": [ 87 | "duration = df['time'].diff()\n", 88 | "duration_hours = duration / pd.Timedelta(hours=1)\n", 89 | "speed_kmh = dist_km / duration_hours" 90 | ] 91 | }, 92 | { 93 | "cell_type": "markdown", 94 | "id": "808cdec4-f6fe-4fff-9356-371900e6fdcb", 95 | "metadata": {}, 96 | "source": [ 97 | "## Display Average Speed" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": 13, 103 | "id": "1db39f43-46dd-4c33-8347-52235a2d090c", 104 | "metadata": {}, 105 | "outputs": [ 106 | { 107 | "data": { 108 | "text/plain": [ 109 | "9.58044454743704" 110 | ] 111 | }, 112 | "execution_count": 13, 113 | "metadata": {}, 114 | "output_type": "execute_result" 115 | } 116 | ], 117 | "source": [ 118 | "speed_kmh.mean()" 119 | ] 120 | }, 121 | { 122 | "cell_type": "markdown", 123 | "id": "7dd567b2-5494-441d-9344-41e69cb0286f", 124 | "metadata": {}, 125 | "source": [ 126 | "## Test Output" 127 | ] 128 | }, 129 | { 130 | "cell_type": "code", 131 | "execution_count": 14, 132 | "id": "96ef0dcb-2de8-47e5-9314-1f87e75baf72", 133 | "metadata": {}, 134 | "outputs": [], 135 | "source": [ 136 | "import json\n", 137 | "\n", 138 | "out_file = environ.get('OUT_FILE')\n", 139 | "if out_file:\n", 140 | " response = {'mean_speed': speed_kmh.mean()}\n", 141 | " with open(out_file, 'w') as out:\n", 142 | " json.dump(response, out)" 143 | ] 144 | } 145 | ], 146 | "metadata": { 147 | "kernelspec": { 148 | "display_name": "Python 3 (ipykernel)", 149 | "language": "python", 150 | "name": "python3" 151 | }, 152 | "language_info": { 153 | "codemirror_mode": { 154 | "name": "ipython", 155 | "version": 3 156 | }, 157 | "file_extension": ".py", 158 | "mimetype": "text/x-python", 159 | "name": "python", 160 | "nbconvert_exporter": "python", 161 | "pygments_lexer": "ipython3", 162 | "version": "3.10.4" 163 | } 164 | }, 165 | "nbformat": 4, 166 | "nbformat_minor": 5 167 | } 168 | -------------------------------------------------------------------------------- /Ch06/06_03/test_tracklib.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import tracklib as tl 3 | 4 | 5 | def test_calc_distance(): 6 | dist = tl.calc_distance(0, 0, 1, 1) 7 | assert np.allclose(144.17003, dist) -------------------------------------------------------------------------------- /Ch06/06_03/track.csv: -------------------------------------------------------------------------------- 1 | time,lat,lng,height 2 | 2015-08-20T03:48:07.235Z,32.519585,35.015021,136.1999969482422 3 | 2015-08-20T03:48:24.734Z,32.519606,35.014954,126.5999984741211 4 | 2015-08-20T03:48:25.660Z,32.519612,35.014871,123.0 5 | 2015-08-20T03:48:26.819Z,32.519654,35.014824,120.5 6 | 2015-08-20T03:48:27.828Z,32.519689,35.014776,118.9000015258789 7 | 2015-08-20T03:48:29.720Z,32.519691,35.014704,119.9000015258789 8 | 2015-08-20T03:48:30.669Z,32.519734,35.014657,120.9000015258789 9 | 2015-08-20T03:48:33.793Z,32.519719,35.014563,121.69999694824219 10 | 2015-08-20T03:48:34.869Z,32.519694,35.014549,121.19999694824219 11 | 2015-08-20T03:48:37.708Z,32.519625,35.014515,121.69999694824219 12 | 2015-08-20T03:48:38.839Z,32.519599,35.014505,121.80000305175781 13 | 2015-08-20T03:48:41.980Z,32.519514,35.014481,122.5999984741211 14 | 2015-08-20T03:48:42.725Z,32.519486,35.014472,123.0 15 | 2015-08-20T03:48:45.896Z,32.519405,35.014439,122.69999694824219 16 | 2015-08-20T03:48:46.662Z,32.519379,35.014432,122.69999694824219 17 | 2015-08-20T03:48:49.829Z,32.519309,35.014414,122.69999694824219 18 | 2015-08-20T03:48:50.665Z,32.519287,35.0144,123.30000305175781 19 | 2015-08-20T03:48:53.692Z,32.519211,35.014372,122.30000305175781 20 | 2015-08-20T03:48:54.662Z,32.519187,35.014365,122.5999984741211 21 | 2015-08-20T03:48:58.869Z,32.519106,35.014337,122.0 22 | 2015-08-20T03:48:59.663Z,32.519084,35.014331,121.80000305175781 23 | 2015-08-20T03:49:03.861Z,32.519009,35.014303,122.9000015258789 24 | 2015-08-20T03:49:04.663Z,32.518989,35.014306,122.9000015258789 25 | 2015-08-20T03:49:07.742Z,32.518916,35.01434,123.0999984741211 26 | 2015-08-20T03:50:13.679Z,32.517636,35.013531,115.19999694824219 27 | 2015-08-20T03:50:16.767Z,32.517589,35.013606,114.30000305175781 28 | 2015-08-20T03:50:17.719Z,32.517574,35.01363,114.19999694824219 29 | 2015-08-20T03:50:20.748Z,32.517529,35.013705,113.80000305175781 30 | 2015-08-20T03:50:21.681Z,32.517512,35.01373,114.19999694824219 31 | 2015-08-20T03:50:24.735Z,32.517459,35.013809,114.0 32 | 2015-08-20T03:50:25.677Z,32.517442,35.013834,113.0999984741211 33 | 2015-08-20T03:50:28.738Z,32.517389,35.013903,112.5999984741211 34 | 2015-08-20T03:50:29.673Z,32.517373,35.013925,113.5 35 | 2015-08-20T03:50:32.816Z,32.517323,35.013991,113.5999984741211 36 | 2015-08-20T03:50:33.682Z,32.517306,35.014012,113.4000015258789 37 | 2015-08-20T03:50:36.749Z,32.517254,35.014075,114.5999984741211 38 | 2015-08-20T03:50:37.744Z,32.517236,35.014095,114.19999694824219 39 | 2015-08-20T03:50:40.735Z,32.517183,35.014148,115.5 40 | 2015-08-20T03:50:41.682Z,32.517164,35.014167,116.0 41 | 2015-08-20T03:50:44.757Z,32.517111,35.014235,116.5999984741211 42 | 2015-08-20T03:50:45.674Z,32.517095,35.014257,116.5999984741211 43 | 2015-08-20T03:50:48.716Z,32.517044,35.014332,115.30000305175781 44 | 2015-08-20T03:50:49.684Z,32.517026,35.014357,115.0 45 | 2015-08-20T03:50:52.757Z,32.516972,35.014431,114.9000015258789 46 | 2015-08-20T03:50:53.688Z,32.516954,35.014456,114.9000015258789 47 | 2015-08-20T03:50:56.782Z,32.516891,35.014519,115.69999694824219 48 | 2015-08-20T03:50:57.731Z,32.516868,35.014522,114.0 49 | 2015-08-20T03:51:00.870Z,32.516818,35.01447,113.5999984741211 50 | 2015-08-20T03:51:01.772Z,32.516803,35.014442,113.0 51 | 2015-08-20T03:51:04.744Z,32.516752,35.01436,112.0 52 | 2015-08-20T03:51:05.747Z,32.516734,35.014335,112.30000305175781 53 | 2015-08-20T03:51:08.831Z,32.516677,35.014257,110.9000015258789 54 | 2015-08-20T03:51:09.744Z,32.516657,35.014233,110.80000305175781 55 | 2015-08-20T03:51:12.743Z,32.516591,35.014176,108.69999694824219 56 | 2015-08-20T03:51:13.702Z,32.516568,35.014162,108.4000015258789 57 | 2015-08-20T03:51:16.777Z,32.516506,35.014103,109.19999694824219 58 | 2015-08-20T03:51:17.729Z,32.516486,35.014084,108.4000015258789 59 | 2015-08-20T03:51:20.733Z,32.516421,35.014026,108.5 60 | 2015-08-20T03:51:21.670Z,32.5164,35.014006,108.5999984741211 61 | 2015-08-20T03:51:24.691Z,32.516338,35.013941,107.5999984741211 62 | 2015-08-20T03:51:25.672Z,32.516318,35.01392,107.9000015258789 63 | 2015-08-20T03:51:28.745Z,32.516253,35.013869,108.0 64 | 2015-08-20T03:51:29.677Z,32.51623,35.013852,108.0 65 | 2015-08-20T03:51:32.707Z,32.516174,35.013795,105.5999984741211 66 | 2015-08-20T03:51:33.674Z,32.516156,35.013775,104.80000305175781 67 | 2015-08-20T03:51:36.758Z,32.516108,35.01371,105.30000305175781 68 | 2015-08-20T03:51:37.675Z,32.516089,35.01369,103.9000015258789 69 | 2015-08-20T03:51:40.733Z,32.516033,35.013633,103.69999694824219 70 | 2015-08-20T03:51:41.674Z,32.516014,35.013615,103.5 71 | 2015-08-20T03:51:44.744Z,32.51596,35.013559,102.80000305175781 72 | 2015-08-20T03:51:45.679Z,32.515943,35.01354,103.0 73 | 2015-08-20T03:51:48.760Z,32.515891,35.013482,102.0 74 | 2015-08-20T03:51:49.684Z,32.515873,35.013463,102.0 75 | 2015-08-20T03:51:52.709Z,32.515826,35.013403,102.0 76 | 2015-08-20T03:51:53.672Z,32.515812,35.013382,102.0 77 | 2015-08-20T03:51:56.894Z,32.515761,35.013325,101.80000305175781 78 | 2015-08-20T03:51:57.767Z,32.515743,35.013307,101.30000305175781 79 | 2015-08-20T03:52:00.768Z,32.515693,35.013246,100.5 80 | 2015-08-20T03:52:01.676Z,32.515675,35.013226,100.80000305175781 81 | 2015-08-20T03:52:04.866Z,32.515622,35.013162,101.0999984741211 82 | 2015-08-20T03:52:05.780Z,32.515605,35.013139,100.69999694824219 83 | 2015-08-20T03:52:08.753Z,32.51555,35.013074,99.19999694824219 84 | 2015-08-20T03:52:09.700Z,32.515531,35.013055,99.19999694824219 85 | 2015-08-20T03:52:12.855Z,32.515471,35.012994,99.30000305175781 86 | 2015-08-20T03:52:13.780Z,32.515451,35.012974,99.0 87 | 2015-08-20T03:52:16.775Z,32.515388,35.012912,99.69999694824219 88 | 2015-08-20T03:52:17.704Z,32.515368,35.012891,99.69999694824219 89 | 2015-08-20T03:52:20.907Z,32.515311,35.012826,99.0999984741211 90 | 2015-08-20T03:52:21.779Z,32.515291,35.012806,98.80000305175781 91 | 2015-08-20T03:52:24.813Z,32.515226,35.01276,98.5 92 | 2015-08-20T03:52:25.698Z,32.515203,35.012747,97.9000015258789 93 | 2015-08-20T03:52:28.748Z,32.515136,35.012709,97.4000015258789 94 | 2015-08-20T03:52:29.672Z,32.515113,35.012694,97.0 95 | 2015-08-20T03:52:32.719Z,32.515052,35.012636,96.30000305175781 96 | 2015-08-20T03:52:33.698Z,32.515034,35.012617,96.30000305175781 97 | 2015-08-20T03:52:37.790Z,32.514986,35.012537,96.0999984741211 98 | 2015-08-20T03:52:38.678Z,32.514964,35.012521,96.5999984741211 99 | 2015-08-20T03:52:41.752Z,32.514901,35.01246,95.19999694824219 100 | 2015-08-20T03:52:42.684Z,32.514882,35.012438,94.69999694824219 101 | 2015-08-20T03:52:45.758Z,32.514836,35.012371,94.30000305175781 102 | 2015-08-20T03:52:46.679Z,32.514813,35.012367,94.9000015258789 103 | 2015-08-20T03:52:49.764Z,32.514761,35.012418,95.0 104 | 2015-08-20T03:52:50.678Z,32.514746,35.012445,95.4000015258789 105 | 2015-08-20T03:52:54.323Z,32.514689,35.012516,96.4000015258789 106 | 2015-08-20T03:52:54.673Z,32.514671,35.01254,96.5 107 | 2015-08-20T03:52:57.937Z,32.514631,35.012615,98.0 108 | 2015-08-20T03:52:58.682Z,32.514619,35.012636,97.69999694824219 109 | 2015-08-20T03:53:02.766Z,32.514562,35.012717,99.0999984741211 110 | 2015-08-20T03:53:03.678Z,32.514545,35.012741,99.19999694824219 111 | 2015-08-20T03:53:05.884Z,32.514507,35.012782,99.4000015258789 112 | 2015-08-20T03:53:33.775Z,32.514134,35.013324,105.19999694824219 113 | 2015-08-20T03:53:36.808Z,32.514092,35.013393,105.80000305175781 114 | 2015-08-20T03:53:37.677Z,32.514077,35.013417,106.19999694824219 115 | 2015-08-20T03:53:40.734Z,32.514028,35.013493,106.30000305175781 116 | 2015-08-20T03:53:41.686Z,32.514011,35.013514,107.19999694824219 117 | 2015-08-20T03:53:44.713Z,32.513947,35.013472,106.69999694824219 118 | 2015-08-20T03:53:45.682Z,32.513928,35.013445,107.30000305175781 119 | 2015-08-20T03:53:49.290Z,32.513882,35.013363,103.9000015258789 120 | 2015-08-20T03:53:49.679Z,32.513869,35.013336,102.5999984741211 121 | 2015-08-20T03:53:52.831Z,32.513823,35.01327,105.4000015258789 122 | 2015-08-20T03:53:53.737Z,32.513807,35.013251,105.0999984741211 123 | 2015-08-20T03:53:56.820Z,32.513777,35.013178,105.19999694824219 124 | 2015-08-20T03:53:57.772Z,32.513769,35.013153,104.69999694824219 125 | 2015-08-20T03:54:00.947Z,32.513739,35.013078,104.19999694824219 126 | 2015-08-20T03:54:01.713Z,32.513726,35.013053,103.9000015258789 127 | 2015-08-20T03:54:04.796Z,32.513683,35.012981,102.80000305175781 128 | 2015-08-20T03:54:05.739Z,32.513666,35.012958,102.30000305175781 129 | 2015-08-20T03:54:08.837Z,32.513614,35.012891,100.4000015258789 130 | 2015-08-20T03:54:09.736Z,32.513598,35.012869,100.4000015258789 131 | 2015-08-20T03:54:12.795Z,32.513558,35.012791,100.5999984741211 132 | 2015-08-20T03:54:13.691Z,32.513546,35.012765,100.4000015258789 133 | 2015-08-20T03:54:17.425Z,32.513513,35.012687,99.69999694824219 134 | 2015-08-20T03:54:17.724Z,32.513502,35.01266,99.9000015258789 135 | 2015-08-20T03:54:20.759Z,32.513469,35.012578,102.0 136 | 2015-08-20T03:54:21.692Z,32.51346,35.01255,102.0999984741211 137 | 2015-08-20T03:54:24.813Z,32.513433,35.012471,101.5999984741211 138 | 2015-08-20T03:54:25.692Z,32.513426,35.012445,100.9000015258789 139 | 2015-08-20T03:54:28.783Z,32.513402,35.012367,100.0999984741211 140 | 2015-08-20T03:54:29.687Z,32.513394,35.012338,99.19999694824219 141 | 2015-08-20T03:54:32.827Z,32.513355,35.01226,99.5 142 | 2015-08-20T03:54:33.691Z,32.51334,35.012236,99.4000015258789 143 | 2015-08-20T03:54:36.774Z,32.513301,35.012159,98.30000305175781 144 | 2015-08-20T03:54:37.686Z,32.513288,35.012135,96.69999694824219 145 | 2015-08-20T03:54:40.787Z,32.513249,35.012063,95.19999694824219 146 | 2015-08-20T03:54:41.686Z,32.513237,35.012037,95.0 147 | 2015-08-20T03:54:44.769Z,32.513199,35.011961,94.69999694824219 148 | 2015-08-20T03:54:45.688Z,32.513184,35.011937,95.19999694824219 149 | 2015-08-20T03:54:48.745Z,32.51314,35.011868,93.30000305175781 150 | 2015-08-20T03:54:49.689Z,32.513126,35.011844,93.19999694824219 151 | 2015-08-20T03:54:52.757Z,32.513097,35.011766,92.5 152 | 2015-08-20T03:54:53.684Z,32.513088,35.011741,91.4000015258789 153 | 2015-08-20T03:54:57.781Z,32.513055,35.011644,91.19999694824219 154 | 2015-08-20T03:54:58.688Z,32.513048,35.011618,90.9000015258789 155 | 2015-08-20T03:55:01.904Z,32.513024,35.011538,90.69999694824219 156 | 2015-08-20T03:55:02.695Z,32.513016,35.01151,91.0 157 | 2015-08-20T03:55:05.766Z,32.512991,35.011432,90.0 158 | 2015-08-20T03:55:06.696Z,32.512982,35.011409,88.9000015258789 159 | 2015-08-20T03:55:10.766Z,32.512965,35.01131,88.0 160 | 2015-08-20T03:55:11.690Z,32.512962,35.011284,88.0999984741211 161 | 2015-08-20T03:55:14.787Z,32.512944,35.011205,87.9000015258789 162 | 2015-08-20T03:55:15.692Z,32.512936,35.011179,87.80000305175781 163 | 2015-08-20T03:55:18.789Z,32.512908,35.0111,86.80000305175781 164 | 2015-08-20T03:55:19.724Z,32.512897,35.011073,87.69999694824219 165 | 2015-08-20T03:55:22.747Z,32.512862,35.010991,88.0 166 | 2015-08-20T03:55:23.801Z,32.51285,35.010963,88.30000305175781 167 | 2015-08-20T03:55:26.824Z,32.51282,35.010873,88.0999984741211 168 | 2015-08-20T03:55:27.730Z,32.51281,35.010844,87.30000305175781 169 | 2015-08-20T03:55:30.791Z,32.512774,35.010765,87.4000015258789 170 | 2015-08-20T03:55:31.786Z,32.512762,35.010739,87.5999984741211 171 | 2015-08-20T03:55:34.837Z,32.512726,35.010661,86.80000305175781 172 | 2015-08-20T03:55:35.724Z,32.512714,35.010636,86.69999694824219 173 | 2015-08-20T03:55:38.786Z,32.512676,35.010562,87.19999694824219 174 | 2015-08-20T03:55:39.770Z,32.512664,35.010537,87.30000305175781 175 | 2015-08-20T03:55:42.826Z,32.512645,35.010455,87.0999984741211 176 | 2015-08-20T03:55:43.699Z,32.512642,35.010426,86.5999984741211 177 | 2015-08-20T03:55:46.771Z,32.512637,35.01034,85.0 178 | 2015-08-20T03:55:47.692Z,32.512636,35.010313,84.9000015258789 179 | 2015-08-20T03:55:51.779Z,32.512629,35.010212,84.9000015258789 180 | 2015-08-20T03:55:52.694Z,32.512625,35.010189,84.4000015258789 181 | 2015-08-20T03:55:56.849Z,32.512594,35.010093,82.9000015258789 182 | 2015-08-20T03:55:57.697Z,32.512584,35.010068,83.69999694824219 183 | 2015-08-20T03:56:00.786Z,32.512551,35.009988,84.0999984741211 184 | 2015-08-20T03:56:01.697Z,32.512539,35.009961,84.5 185 | 2015-08-20T03:56:04.757Z,32.512505,35.009883,84.0 186 | 2015-08-20T03:56:05.839Z,32.512493,35.009857,84.0 187 | 2015-08-20T03:56:08.782Z,32.512456,35.009785,83.0 188 | 2015-08-20T03:56:09.705Z,32.512445,35.009762,82.9000015258789 189 | 2015-08-20T03:56:12.777Z,32.512408,35.009692,82.4000015258789 190 | 2015-08-20T03:56:13.701Z,32.512395,35.009668,82.80000305175781 191 | 2015-08-20T03:56:16.840Z,32.512362,35.009595,81.5999984741211 192 | 2015-08-20T03:56:17.698Z,32.512347,35.009574,81.30000305175781 193 | 2015-08-20T03:56:20.757Z,32.512291,35.009517,81.80000305175781 194 | 2015-08-20T03:56:21.708Z,32.512267,35.009495,81.69999694824219 195 | 2015-08-20T03:56:24.832Z,32.512213,35.00943,82.30000305175781 196 | 2015-08-20T03:56:25.698Z,32.512199,35.00941,82.0 197 | 2015-08-20T03:56:28.974Z,32.512144,35.009361,80.69999694824219 198 | 2015-08-20T03:57:10.713Z,32.511551,35.009294,84.0 199 | 2015-08-20T03:57:14.785Z,32.511533,35.009386,86.9000015258789 200 | 2015-08-20T03:57:15.920Z,32.511524,35.009408,87.5 201 | 2015-08-20T03:57:19.818Z,32.511467,35.009485,87.30000305175781 202 | 2015-08-20T03:57:20.757Z,32.51145,35.0095,86.80000305175781 203 | 2015-08-20T03:57:24.836Z,32.511379,35.009559,89.5999984741211 204 | 2015-08-20T03:57:25.763Z,32.511362,35.009573,89.5 205 | 2015-08-20T03:57:29.824Z,32.511303,35.009636,89.0 206 | 2015-08-20T03:57:30.702Z,32.511293,35.009653,88.80000305175781 207 | 2015-08-20T03:57:35.785Z,32.511252,35.009745,91.19999694824219 208 | 2015-08-20T03:57:36.709Z,32.511245,35.009764,91.69999694824219 209 | 2015-08-20T03:57:41.812Z,32.511216,35.009855,91.30000305175781 210 | 2015-08-20T03:57:42.760Z,32.511212,35.009875,91.80000305175781 211 | 2015-08-20T03:57:47.810Z,32.511215,35.009977,87.69999694824219 212 | 2015-08-20T03:57:48.711Z,32.511218,35.009998,88.5999984741211 213 | 2015-08-20T03:57:53.815Z,32.511226,35.010102,86.19999694824219 214 | 2015-08-20T03:57:54.704Z,32.511225,35.010123,86.5999984741211 215 | 2015-08-20T03:57:59.780Z,32.511209,35.010227,86.9000015258789 216 | 2015-08-20T03:58:00.710Z,32.511202,35.010248,87.9000015258789 217 | 2015-08-20T03:58:04.797Z,32.511172,35.010329,88.80000305175781 218 | 2015-08-20T03:58:05.710Z,32.511162,35.010348,88.5 219 | 2015-08-20T03:58:09.754Z,32.511117,35.010419,90.30000305175781 220 | 2015-08-20T03:58:23.793Z,32.510997,35.010643,93.5 221 | 2015-08-20T03:58:28.757Z,32.510988,35.010748,93.19999694824219 222 | 2015-08-20T03:58:29.705Z,32.510981,35.010764,93.5999984741211 223 | 2015-08-20T03:58:34.772Z,32.510925,35.010825,93.30000305175781 224 | 2015-08-20T03:58:35.709Z,32.510912,35.010837,93.80000305175781 225 | 2015-08-20T03:58:40.773Z,32.510838,35.010887,95.4000015258789 226 | 2015-08-20T03:58:41.710Z,32.510821,35.010891,94.69999694824219 227 | 2015-08-20T03:58:46.790Z,32.510745,35.010903,97.69999694824219 228 | 2015-08-20T03:58:47.755Z,32.510729,35.01091,98.4000015258789 229 | 2015-08-20T03:58:52.795Z,32.510651,35.010939,100.5 230 | 2015-08-20T03:58:53.723Z,32.510637,35.010948,99.69999694824219 231 | 2015-08-20T03:58:58.841Z,32.510557,35.010988,98.80000305175781 232 | 2015-08-20T03:58:59.753Z,32.510539,35.010993,97.80000305175781 233 | 2015-08-20T03:59:04.834Z,32.510462,35.011028,98.19999694824219 234 | 2015-08-20T03:59:05.760Z,32.510448,35.011037,98.0999984741211 235 | 2015-08-20T03:59:10.877Z,32.510369,35.011071,98.0 236 | 2015-08-20T03:59:11.758Z,32.510353,35.011076,99.30000305175781 237 | 2015-08-20T03:59:16.821Z,32.510278,35.011083,100.19999694824219 238 | 2015-08-20T03:59:17.799Z,32.510262,35.011083,100.0 239 | 2015-08-20T03:59:22.869Z,32.510184,35.011083,100.5999984741211 240 | 2015-08-20T03:59:23.773Z,32.510168,35.011081,101.0 241 | 2015-08-20T03:59:29.840Z,32.510085,35.011108,103.69999694824219 242 | 2015-08-20T03:59:30.719Z,32.510071,35.011108,103.19999694824219 243 | 2015-08-20T03:59:35.811Z,32.509998,35.011101,104.0 244 | 2015-08-20T03:59:36.722Z,32.50998,35.011102,105.30000305175781 245 | 2015-08-20T03:59:41.823Z,32.509892,35.011123,109.5999984741211 246 | 2015-08-20T03:59:42.900Z,32.509875,35.011126,109.80000305175781 247 | 2015-08-20T03:59:47.759Z,32.509797,35.011142,112.30000305175781 248 | 2015-08-20T03:59:48.718Z,32.509782,35.011142,112.80000305175781 249 | 2015-08-20T03:59:54.855Z,32.509693,35.011128,110.80000305175781 250 | 2015-08-20T03:59:55.709Z,32.509679,35.01113,110.4000015258789 251 | 2015-08-20T04:00:02.764Z,32.509592,35.011152,109.19999694824219 252 | 2015-08-20T04:00:03.761Z,32.509576,35.011153,108.4000015258789 253 | 2015-08-20T04:00:08.786Z,32.509491,35.011162,109.80000305175781 254 | 2015-08-20T04:00:09.727Z,32.509474,35.011171,110.0999984741211 255 | 2015-08-20T04:00:13.815Z,32.50941,35.011228,111.5999984741211 256 | 2015-08-20T04:00:14.721Z,32.509395,35.011246,111.80000305175781 257 | 2015-08-20T04:00:18.879Z,32.509335,35.011324,111.0999984741211 258 | 2015-08-20T04:00:19.739Z,32.509325,35.011348,111.0 259 | 2015-08-20T04:00:22.758Z,32.50931,35.011425,110.30000305175781 260 | 2015-08-20T04:00:26.765Z,32.509363,35.011497,109.4000015258789 261 | 2015-08-20T04:00:31.754Z,32.509427,35.011568,109.5 262 | 2015-08-20T04:00:32.724Z,32.509434,35.01158,109.4000015258789 263 | 2015-08-20T04:00:38.798Z,32.509408,35.01168,108.30000305175781 264 | 2015-08-20T04:00:39.732Z,32.509398,35.011698,108.30000305175781 265 | 2015-08-20T04:00:44.912Z,32.509339,35.011764,106.5999984741211 266 | 2015-08-20T04:00:45.722Z,32.509328,35.011776,106.69999694824219 267 | 2015-08-20T04:00:50.955Z,32.509276,35.011845,103.0 268 | 2015-08-20T04:00:51.724Z,32.509261,35.011857,102.19999694824219 269 | 2015-08-20T04:00:56.837Z,32.509182,35.011906,100.9000015258789 270 | 2015-08-20T04:00:57.790Z,32.509167,35.011919,100.69999694824219 271 | 2015-08-20T04:01:02.893Z,32.509097,35.011982,100.5 272 | 2015-08-20T04:01:03.767Z,32.509082,35.011995,100.0999984741211 273 | 2015-08-20T04:01:07.773Z,32.509023,35.012046,98.69999694824219 274 | 2015-08-20T04:01:08.723Z,32.509008,35.01206,98.4000015258789 275 | 2015-08-20T04:01:12.892Z,32.508949,35.012118,98.19999694824219 276 | 2015-08-20T04:01:13.730Z,32.508936,35.012133,97.80000305175781 277 | 2015-08-20T04:01:17.889Z,32.508888,35.012198,96.9000015258789 278 | 2015-08-20T04:01:18.737Z,32.508875,35.012215,96.9000015258789 279 | 2015-08-20T04:01:22.773Z,32.508815,35.012275,96.0 280 | 2015-08-20T04:01:23.738Z,32.508801,35.012291,95.69999694824219 281 | 2015-08-20T04:01:27.842Z,32.508754,35.012367,95.5 282 | 2015-08-20T04:01:28.724Z,32.508745,35.01239,95.30000305175781 283 | 2015-08-20T04:01:32.771Z,32.508719,35.012489,94.9000015258789 284 | 2015-08-20T04:01:33.737Z,32.508714,35.012511,94.19999694824219 285 | 2015-08-20T04:01:37.826Z,32.508683,35.012593,93.30000305175781 286 | 2015-08-20T04:01:38.805Z,32.50867,35.012613,93.69999694824219 287 | 2015-08-20T04:01:42.885Z,32.508632,35.012693,92.0999984741211 288 | 2015-08-20T04:01:43.769Z,32.508626,35.012715,91.30000305175781 289 | 2015-08-20T04:01:47.862Z,32.508605,35.012807,90.5999984741211 290 | 2015-08-20T04:01:48.809Z,32.508601,35.012831,90.19999694824219 291 | 2015-08-20T04:01:52.842Z,32.508585,35.012924,89.5999984741211 292 | 2015-08-20T04:01:53.730Z,32.508577,35.012946,88.4000015258789 293 | 2015-08-20T04:01:56.975Z,32.508545,35.013015,88.0999984741211 294 | 2015-08-20T04:01:57.734Z,32.508537,35.013042,88.4000015258789 295 | 2015-08-20T04:02:01.816Z,32.508514,35.013143,87.30000305175781 296 | 2015-08-20T04:02:02.766Z,32.508506,35.013164,87.19999694824219 297 | 2015-08-20T04:02:06.811Z,32.508474,35.01325,87.0999984741211 298 | 2015-08-20T04:02:07.740Z,32.508467,35.013272,87.19999694824219 299 | 2015-08-20T04:02:11.804Z,32.508432,35.013361,87.4000015258789 300 | 2015-08-20T04:02:12.733Z,32.508421,35.013383,88.0 301 | 2015-08-20T04:02:16.800Z,32.508376,35.013474,88.0999984741211 302 | 2015-08-20T04:02:17.734Z,32.508364,35.013495,87.30000305175781 303 | 2015-08-20T04:02:22.799Z,32.508313,35.013573,85.19999694824219 304 | 2015-08-20T04:02:23.743Z,32.5083,35.013586,85.0 305 | 2015-08-20T04:02:28.794Z,32.508228,35.013635,80.80000305175781 306 | 2015-08-20T04:02:29.755Z,32.508212,35.013642,80.19999694824219 307 | 2015-08-20T04:02:33.807Z,32.508138,35.013675,79.9000015258789 308 | 2015-08-20T04:02:34.804Z,32.508119,35.013685,80.0999984741211 309 | 2015-08-20T04:02:38.812Z,32.508092,35.013769,80.69999694824219 310 | 2015-08-20T04:02:39.879Z,32.508098,35.0138,81.0 311 | 2015-08-20T04:02:42.909Z,32.508128,35.013877,79.69999694824219 312 | 2015-08-20T04:02:43.754Z,32.508136,35.013901,80.80000305175781 313 | 2015-08-20T04:02:48.018Z,32.508157,35.014002,80.5999984741211 314 | 2015-08-20T04:02:48.746Z,32.508158,35.014028,80.5999984741211 315 | 2015-08-20T04:02:56.857Z,32.508152,35.014134,80.69999694824219 316 | 2015-08-20T04:02:57.964Z,32.508154,35.014166,80.4000015258789 317 | 2015-08-20T04:03:00.838Z,32.508153,35.014262,80.0999984741211 318 | 2015-08-20T04:03:01.834Z,32.508154,35.014292,79.80000305175781 319 | 2015-08-20T04:03:04.926Z,32.508161,35.014381,78.80000305175781 320 | 2015-08-20T04:03:05.735Z,32.508159,35.014411,79.19999694824219 321 | 2015-08-20T04:03:08.875Z,32.508163,35.014501,79.0 322 | 2015-08-20T04:03:09.740Z,32.508176,35.014527,79.9000015258789 323 | 2015-08-20T04:03:12.773Z,32.508198,35.014609,80.4000015258789 324 | 2015-08-20T04:03:13.733Z,32.508205,35.014635,81.4000015258789 325 | 2015-08-20T04:03:17.917Z,32.508223,35.01473,81.0 326 | 2015-08-20T04:03:18.741Z,32.508227,35.014754,81.5 327 | 2015-08-20T04:03:22.777Z,32.508247,35.014854,81.5999984741211 328 | 2015-08-20T04:03:23.734Z,32.508254,35.01488,81.19999694824219 329 | 2015-08-20T04:03:26.806Z,32.508274,35.014959,81.0 330 | 2015-08-20T04:03:27.736Z,32.508278,35.014985,81.19999694824219 331 | 2015-08-20T04:03:31.781Z,32.508291,35.015084,83.30000305175781 332 | 2015-08-20T04:03:32.733Z,32.508294,35.015108,83.5999984741211 333 | 2015-08-20T04:03:36.817Z,32.508315,35.015203,84.5999984741211 334 | 2015-08-20T04:03:37.735Z,32.508318,35.015227,84.30000305175781 335 | 2015-08-20T04:03:41.910Z,32.508329,35.015329,84.80000305175781 336 | 2015-08-20T04:03:42.735Z,32.508329,35.015354,84.9000015258789 337 | 2015-08-20T04:03:46.780Z,32.508337,35.015452,85.30000305175781 338 | 2015-08-20T04:03:47.739Z,32.50834,35.015477,85.0 339 | 2015-08-20T04:03:51.812Z,32.50836,35.015572,84.5999984741211 340 | 2015-08-20T04:03:52.753Z,32.50837,35.015594,83.5999984741211 341 | 2015-08-20T04:03:56.823Z,32.508393,35.015688,84.0999984741211 342 | 2015-08-20T04:03:57.748Z,32.508398,35.015712,83.5 343 | 2015-08-20T04:04:01.886Z,32.508414,35.015804,83.19999694824219 344 | 2015-08-20T04:04:02.806Z,32.508417,35.015827,82.80000305175781 345 | 2015-08-20T04:04:06.819Z,32.508435,35.015917,81.19999694824219 346 | 2015-08-20T04:04:07.737Z,32.508441,35.015939,80.5999984741211 347 | 2015-08-20T04:04:11.934Z,32.508457,35.016031,81.0999984741211 348 | 2015-08-20T04:04:12.809Z,32.50846,35.016053,81.19999694824219 349 | 2015-08-20T04:04:16.845Z,32.508471,35.016144,79.0999984741211 350 | 2015-08-20T04:04:17.756Z,32.508474,35.016168,79.19999694824219 351 | 2015-08-20T04:04:21.812Z,32.508485,35.016264,77.9000015258789 352 | 2015-08-20T04:04:22.738Z,32.508485,35.016287,77.5 353 | 2015-08-20T04:04:26.828Z,32.508482,35.016389,78.30000305175781 354 | 2015-08-20T04:04:27.741Z,32.508484,35.016415,79.5 355 | 2015-08-20T04:04:30.815Z,32.508498,35.016495,79.19999694824219 356 | 2015-08-20T04:04:31.780Z,32.508502,35.016521,79.19999694824219 357 | 2015-08-20T04:04:35.782Z,32.508519,35.016616,80.19999694824219 358 | 2015-08-20T04:04:36.758Z,32.508519,35.01664,80.5999984741211 359 | 2015-08-20T04:04:40.819Z,32.508524,35.016736,80.9000015258789 360 | 2015-08-20T04:04:41.739Z,32.508526,35.01676,80.5999984741211 361 | 2015-08-20T04:04:45.822Z,32.50854,35.016862,82.0999984741211 362 | 2015-08-20T04:04:46.754Z,32.508545,35.016889,81.69999694824219 363 | 2015-08-20T04:04:49.819Z,32.50856,35.016969,81.69999694824219 364 | 2015-08-20T04:04:50.751Z,32.508565,35.016995,81.69999694824219 365 | 2015-08-20T04:04:54.827Z,32.508588,35.017093,81.5 366 | 2015-08-20T04:04:55.741Z,32.508594,35.017118,81.30000305175781 367 | 2015-08-20T04:04:59.953Z,32.508622,35.017211,81.69999694824219 368 | 2015-08-20T04:05:00.898Z,32.508629,35.017233,81.9000015258789 369 | 2015-08-20T04:05:04.825Z,32.50865,35.017327,83.69999694824219 370 | 2015-08-20T04:05:05.753Z,32.508654,35.017352,83.9000015258789 371 | 2015-08-20T04:05:09.820Z,32.508676,35.017453,85.80000305175781 372 | 2015-08-20T04:05:10.752Z,32.508681,35.017477,85.19999694824219 373 | 2015-08-20T04:05:14.782Z,32.508707,35.017574,85.0 374 | 2015-08-20T04:05:15.746Z,32.508715,35.017599,84.69999694824219 375 | 2015-08-20T04:05:18.810Z,32.508727,35.017679,84.30000305175781 376 | 2015-08-20T04:05:19.754Z,32.508727,35.017706,85.0999984741211 377 | 2015-08-20T04:05:23.821Z,32.508727,35.017811,85.19999694824219 378 | 2015-08-20T04:05:24.748Z,32.508732,35.017839,85.19999694824219 379 | 2015-08-20T04:05:27.786Z,32.508745,35.017921,84.4000015258789 380 | 2015-08-20T04:05:28.751Z,32.508745,35.01795,84.69999694824219 381 | 2015-08-20T04:05:31.779Z,32.508764,35.018032,84.69999694824219 382 | 2015-08-20T04:05:32.778Z,32.508771,35.01806,84.5 383 | 2015-08-20T04:05:35.827Z,32.508779,35.018146,84.69999694824219 384 | 2015-08-20T04:05:36.757Z,32.508782,35.018173,83.30000305175781 385 | 2015-08-20T04:05:40.868Z,32.508792,35.018274,83.5 386 | 2015-08-20T04:05:41.830Z,32.508795,35.018298,84.5 387 | 2015-08-20T04:05:45.830Z,32.508801,35.018397,83.69999694824219 388 | 2015-08-20T04:05:46.745Z,32.508802,35.018421,82.80000305175781 389 | 2015-08-20T04:05:50.865Z,32.508796,35.018515,80.9000015258789 390 | 2015-08-20T04:05:51.774Z,32.508792,35.018539,81.5 391 | 2015-08-20T04:05:55.985Z,32.508787,35.018637,82.5999984741211 392 | 2015-08-20T04:05:56.877Z,32.508784,35.01866,82.9000015258789 393 | 2015-08-20T04:06:01.100Z,32.508772,35.018762,84.80000305175781 394 | 2015-08-20T04:06:01.788Z,32.508772,35.018789,84.80000305175781 395 | 2015-08-20T04:06:04.895Z,32.508772,35.018874,84.69999694824219 396 | 2015-08-20T04:06:05.832Z,32.508774,35.018902,83.80000305175781 397 | 2015-08-20T04:06:08.882Z,32.50878,35.018988,82.0999984741211 398 | 2015-08-20T04:06:10.029Z,32.508783,35.019016,81.80000305175781 399 | 2015-08-20T04:06:12.907Z,32.508795,35.019104,80.5999984741211 400 | 2015-08-20T04:06:13.760Z,32.508798,35.019135,79.5 401 | 2015-08-20T04:06:16.824Z,32.508818,35.01922,80.5 402 | 2015-08-20T04:06:17.748Z,32.508826,35.019248,79.5 403 | 2015-08-20T04:06:20.825Z,32.508859,35.019327,79.4000015258789 404 | 2015-08-20T04:06:21.750Z,32.508868,35.019355,79.9000015258789 405 | 2015-08-20T04:06:24.830Z,32.508895,35.019439,80.0 406 | 2015-08-20T04:06:25.755Z,32.508902,35.019465,80.4000015258789 407 | 2015-08-20T04:06:28.846Z,32.508922,35.019544,79.0 408 | 2015-08-20T04:06:29.760Z,32.50893,35.019568,79.30000305175781 409 | 2015-08-20T04:06:33.815Z,32.50896,35.019661,79.5 410 | 2015-08-20T04:06:34.814Z,32.508969,35.019684,80.19999694824219 411 | 2015-08-20T04:06:38.879Z,32.509004,35.019779,80.4000015258789 412 | 2015-08-20T04:06:39.758Z,32.509014,35.019804,79.19999694824219 413 | 2015-08-20T04:06:42.786Z,32.509039,35.01988,79.9000015258789 414 | 2015-08-20T04:06:43.754Z,32.509046,35.019905,79.4000015258789 415 | 2015-08-20T04:06:47.808Z,32.509086,35.019981,80.0 416 | 2015-08-20T04:06:48.764Z,32.509093,35.019999,79.69999694824219 417 | 2015-08-20T04:06:53.841Z,32.509119,35.020097,80.0 418 | 2015-08-20T04:06:54.756Z,32.509125,35.020119,79.30000305175781 419 | 2015-08-20T04:06:58.908Z,32.509153,35.020204,81.5999984741211 420 | 2015-08-20T04:06:59.766Z,32.509157,35.020226,81.80000305175781 421 | 2015-08-20T04:07:04.844Z,32.509181,35.020326,83.19999694824219 422 | 2015-08-20T04:07:05.792Z,32.509186,35.020345,82.0999984741211 423 | 2015-08-20T04:07:09.806Z,32.509207,35.020426,82.5999984741211 424 | 2015-08-20T04:07:10.753Z,32.509211,35.020448,81.9000015258789 425 | 2015-08-20T04:07:14.850Z,32.509228,35.020537,82.30000305175781 426 | 2015-08-20T04:07:15.779Z,32.509234,35.020559,82.5 427 | 2015-08-20T04:07:19.852Z,32.50925,35.02065,87.4000015258789 428 | 2015-08-20T04:07:20.770Z,32.509254,35.020673,86.9000015258789 429 | 2015-08-20T04:07:24.887Z,32.509278,35.020759,88.0999984741211 430 | 2015-08-20T04:07:25.772Z,32.509284,35.020781,88.69999694824219 431 | 2015-08-20T04:07:29.868Z,32.509304,35.020867,89.5999984741211 432 | 2015-08-20T04:07:30.822Z,32.509309,35.020888,88.4000015258789 433 | 2015-08-20T04:07:34.900Z,32.509322,35.020976,89.0999984741211 434 | 2015-08-20T04:07:35.760Z,32.509325,35.020997,87.9000015258789 435 | 2015-08-20T04:07:41.002Z,32.509351,35.021097,86.4000015258789 436 | 2015-08-20T04:07:41.805Z,32.509356,35.021117,86.5999984741211 437 | 2015-08-20T04:07:47.040Z,32.509381,35.021218,87.69999694824219 438 | 2015-08-20T04:07:47.830Z,32.509384,35.021238,87.69999694824219 439 | 2015-08-20T04:07:51.835Z,32.509403,35.021322,88.19999694824219 440 | 2015-08-20T04:07:52.792Z,32.509405,35.021342,88.30000305175781 441 | 2015-08-20T04:07:57.866Z,32.509433,35.021441,88.80000305175781 442 | 2015-08-20T04:07:58.770Z,32.509438,35.021462,88.5 443 | 2015-08-20T04:08:02.860Z,32.509445,35.021548,88.0 444 | 2015-08-20T04:08:03.761Z,32.509445,35.021571,88.0 445 | 2015-08-20T04:08:07.842Z,32.509489,35.021641,88.0 446 | 2015-08-20T04:08:08.772Z,32.509511,35.021648,88.5999984741211 447 | 2015-08-20T04:08:12.796Z,32.509599,35.02164,88.5999984741211 448 | 2015-08-20T04:08:13.757Z,32.509619,35.021636,88.30000305175781 449 | 2015-08-20T04:08:17.819Z,32.509691,35.021609,88.80000305175781 450 | 2015-08-20T04:08:18.850Z,32.509711,35.021606,89.5999984741211 451 | 2015-08-20T04:08:22.966Z,32.509787,35.021593,91.0999984741211 452 | 2015-08-20T04:08:23.757Z,32.509805,35.021589,91.30000305175781 453 | 2015-08-20T04:08:28.794Z,32.509887,35.021561,91.80000305175781 454 | 2015-08-20T04:08:29.759Z,32.509901,35.021551,92.19999694824219 455 | 2015-08-20T04:08:35.900Z,32.509982,35.021518,91.0 456 | 2015-08-20T04:08:36.758Z,32.509996,35.021516,91.0999984741211 457 | 2015-08-20T04:08:41.814Z,32.510072,35.021502,91.5 458 | 2015-08-20T04:08:42.760Z,32.510086,35.021494,92.0 459 | 2015-08-20T04:08:47.832Z,32.510153,35.021456,94.5 460 | 2015-08-20T04:08:48.774Z,32.510169,35.021447,94.0 461 | 2015-08-20T04:08:53.897Z,32.51024,35.021412,95.5999984741211 462 | 2015-08-20T04:08:54.788Z,32.510255,35.021404,95.80000305175781 463 | 2015-08-20T04:08:59.841Z,32.510334,35.021376,97.9000015258789 464 | 2015-08-20T04:09:00.764Z,32.51035,35.021375,98.5 465 | 2015-08-20T04:09:05.833Z,32.510434,35.021379,100.30000305175781 466 | 2015-08-20T04:09:06.775Z,32.510449,35.021382,100.30000305175781 467 | 2015-08-20T04:09:11.860Z,32.51053,35.021413,101.0 468 | 2015-08-20T04:09:12.835Z,32.510546,35.021419,101.0999984741211 469 | 2015-08-20T04:09:17.860Z,32.510605,35.021491,99.5999984741211 470 | 2015-08-20T04:09:18.765Z,32.510614,35.021508,99.19999694824219 471 | 2015-08-20T04:09:23.855Z,32.510657,35.021598,98.9000015258789 472 | 2015-08-20T04:09:24.776Z,32.510665,35.021618,98.69999694824219 473 | 2015-08-20T04:09:28.839Z,32.510702,35.021694,99.19999694824219 474 | 2015-08-20T04:09:29.768Z,32.510714,35.021709,99.19999694824219 475 | 2015-08-20T04:09:34.851Z,32.510775,35.021785,99.4000015258789 476 | 2015-08-20T04:09:35.768Z,32.510788,35.021799,98.9000015258789 477 | 2015-08-20T04:09:39.837Z,32.510838,35.021858,99.0999984741211 478 | 2015-08-20T04:09:40.769Z,32.510849,35.021877,98.80000305175781 479 | 2015-08-20T04:09:44.872Z,32.51089,35.02196,97.4000015258789 480 | 2015-08-20T04:09:45.774Z,32.510899,35.02198,98.19999694824219 481 | 2015-08-20T04:09:49.854Z,32.510933,35.022068,98.5 482 | 2015-08-20T04:09:50.768Z,32.51094,35.022091,97.69999694824219 483 | 2015-08-20T04:09:54.847Z,32.510969,35.022182,97.69999694824219 484 | 2015-08-20T04:09:55.768Z,32.510979,35.022202,97.5999984741211 485 | 2015-08-20T04:09:59.850Z,32.511022,35.022282,97.5 486 | 2015-08-20T04:10:00.776Z,32.511032,35.0223,97.5999984741211 487 | 2015-08-20T04:10:05.856Z,32.511085,35.022376,98.9000015258789 488 | 2015-08-20T04:10:06.766Z,32.511094,35.022391,98.69999694824219 489 | 2015-08-20T04:10:12.468Z,32.511146,35.022471,99.80000305175781 490 | 2015-08-20T04:10:12.830Z,32.511155,35.022488,99.9000015258789 491 | 2015-08-20T04:10:17.817Z,32.511197,35.022577,99.69999694824219 492 | 2015-08-20T04:10:18.783Z,32.511205,35.022595,99.5999984741211 493 | 2015-08-20T04:10:23.827Z,32.511237,35.022677,100.69999694824219 494 | 2015-08-20T04:10:24.781Z,32.511247,35.02269,100.4000015258789 495 | 2015-08-20T04:10:29.980Z,32.511298,35.022761,101.80000305175781 496 | 2015-08-20T04:10:30.838Z,32.511309,35.022774,102.30000305175781 497 | 2015-08-20T04:10:35.889Z,32.51139,35.022733,103.30000305175781 498 | 2015-08-20T04:10:36.783Z,32.511398,35.022713,103.30000305175781 499 | 2015-08-20T04:10:40.836Z,32.511421,35.022627,99.9000015258789 500 | 2015-08-20T04:10:41.777Z,32.511418,35.0226,100.0999984741211 501 | 2015-08-20T04:10:45.853Z,32.511412,35.022497,99.5999984741211 502 | 2015-08-20T04:10:46.785Z,32.511417,35.022477,99.69999694824219 503 | 2015-08-20T04:10:51.857Z,32.511476,35.022398,103.5 504 | 2015-08-20T04:10:52.769Z,32.511487,35.022382,103.30000305175781 505 | 2015-08-20T04:10:57.843Z,32.511493,35.022287,100.69999694824219 506 | 2015-08-20T04:10:58.777Z,32.511486,35.022269,100.4000015258789 507 | 2015-08-20T04:11:02.933Z,32.511446,35.022192,100.69999694824219 508 | 2015-08-20T04:11:03.781Z,32.511434,35.022173,101.5 509 | 2015-08-20T04:11:07.870Z,32.511387,35.022099,103.80000305175781 510 | 2015-08-20T04:11:08.771Z,32.511378,35.022078,104.30000305175781 511 | 2015-08-20T04:11:12.832Z,32.511372,35.02199,105.5 512 | 2015-08-20T04:11:13.785Z,32.511375,35.021969,104.4000015258789 513 | 2015-08-20T04:11:18.859Z,32.511364,35.021865,104.4000015258789 514 | 2015-08-20T04:11:19.774Z,32.511358,35.021844,104.30000305175781 515 | 2015-08-20T04:11:23.916Z,32.511348,35.021755,104.30000305175781 516 | 2015-08-20T04:11:24.856Z,32.511341,35.021733,104.5999984741211 517 | 2015-08-20T04:11:28.859Z,32.511297,35.021653,103.5999984741211 518 | 2015-08-20T04:11:29.785Z,32.511285,35.021634,103.5999984741211 519 | 2015-08-20T04:11:33.916Z,32.511249,35.021544,102.69999694824219 520 | 2015-08-20T04:11:34.777Z,32.511242,35.021523,102.0 521 | 2015-08-20T04:11:38.845Z,32.511193,35.021447,101.69999694824219 522 | 2015-08-20T04:11:39.776Z,32.511181,35.02143,101.9000015258789 523 | 2015-08-20T04:11:43.854Z,32.511127,35.021367,101.4000015258789 524 | 2015-08-20T04:11:44.781Z,32.511111,35.021355,100.69999694824219 525 | 2015-08-20T04:11:48.862Z,32.511036,35.021326,99.69999694824219 526 | 2015-08-20T04:11:49.796Z,32.511016,35.021322,100.0999984741211 527 | 2015-08-20T04:11:53.868Z,32.510939,35.021304,99.4000015258789 528 | 2015-08-20T04:11:54.783Z,32.51092,35.021295,99.30000305175781 529 | 2015-08-20T04:11:58.880Z,32.510854,35.021241,99.5 530 | 2015-08-20T04:11:59.783Z,32.51084,35.021223,98.69999694824219 531 | 2015-08-20T04:12:03.871Z,32.510782,35.021152,97.30000305175781 532 | 2015-08-20T04:12:04.793Z,32.510766,35.021134,97.5999984741211 533 | 2015-08-20T04:12:08.851Z,32.510714,35.021052,96.5999984741211 534 | 2015-08-20T04:12:09.802Z,32.510703,35.02103,96.9000015258789 535 | 2015-08-20T04:12:13.871Z,32.510683,35.020927,96.0999984741211 536 | 2015-08-20T04:12:14.784Z,32.510684,35.020899,96.0999984741211 537 | 2015-08-20T04:12:17.844Z,32.510691,35.020811,96.5999984741211 538 | 2015-08-20T04:12:18.868Z,32.510695,35.02078,97.0 539 | 2015-08-20T04:12:21.929Z,32.51071,35.020689,96.69999694824219 540 | 2015-08-20T04:12:22.857Z,32.510717,35.02066,96.5999984741211 541 | 2015-08-20T04:12:25.926Z,32.51074,35.020582,96.0999984741211 542 | 2015-08-20T04:12:26.841Z,32.510747,35.020556,95.5999984741211 543 | 2015-08-20T04:12:30.906Z,32.510777,35.020461,94.30000305175781 544 | 2015-08-20T04:12:32.078Z,32.510786,35.020438,94.19999694824219 545 | 2015-08-20T04:12:35.899Z,32.510816,35.02034,92.4000015258789 546 | 2015-08-20T04:12:37.006Z,32.51082,35.020313,92.5999984741211 547 | 2015-08-20T04:12:39.957Z,32.510831,35.020222,93.9000015258789 548 | 2015-08-20T04:12:40.800Z,32.510836,35.020193,93.30000305175781 549 | 2015-08-20T04:12:43.876Z,32.510856,35.020111,93.5 550 | 2015-08-20T04:12:44.798Z,32.510863,35.020084,93.5 551 | 2015-08-20T04:12:47.876Z,32.510892,35.02001,92.9000015258789 552 | 2015-08-20T04:12:48.814Z,32.510902,35.019987,92.69999694824219 553 | 2015-08-20T04:12:52.978Z,32.510944,35.019899,92.30000305175781 554 | 2015-08-20T04:12:53.847Z,32.510955,35.019877,92.0 555 | 2015-08-20T04:12:57.829Z,32.510988,35.019784,92.19999694824219 556 | 2015-08-20T04:12:58.800Z,32.510993,35.019759,91.9000015258789 557 | 2015-08-20T04:13:01.913Z,32.511,35.019676,90.5999984741211 558 | 2015-08-20T04:13:03.025Z,32.511004,35.019648,90.5999984741211 559 | 2015-08-20T04:13:05.853Z,32.511023,35.019567,90.0 560 | 2015-08-20T04:13:06.809Z,32.511031,35.019541,89.5999984741211 561 | 2015-08-20T04:13:09.907Z,32.511058,35.01947,88.69999694824219 562 | 2015-08-20T04:13:11.796Z,32.511085,35.019434,88.5 563 | 2015-08-20T04:13:15.810Z,32.511152,35.019368,89.5999984741211 564 | 2015-08-20T04:13:16.782Z,32.51117,35.019353,89.0999984741211 565 | 2015-08-20T04:13:19.841Z,32.511213,35.019291,90.30000305175781 566 | 2015-08-20T04:13:20.799Z,32.511225,35.019267,91.4000015258789 567 | 2015-08-20T04:13:24.818Z,32.511276,35.019184,91.80000305175781 568 | 2015-08-20T04:13:25.969Z,32.511286,35.019163,92.0999984741211 569 | 2015-08-20T04:13:29.993Z,32.511319,35.01907,92.19999694824219 570 | 2015-08-20T04:13:30.782Z,32.51133,35.019048,92.69999694824219 571 | 2015-08-20T04:13:34.847Z,32.511367,35.018962,92.19999694824219 572 | 2015-08-20T04:13:35.784Z,32.511371,35.01894,91.9000015258789 573 | 2015-08-20T04:13:40.817Z,32.511413,35.01886,92.0999984741211 574 | 2015-08-20T04:13:41.783Z,32.511419,35.018845,92.0 575 | 2015-08-20T04:13:47.873Z,32.511452,35.018747,90.4000015258789 576 | 2015-08-20T04:13:48.828Z,32.511457,35.018728,91.0 577 | 2015-08-20T04:13:52.897Z,32.511486,35.018646,92.4000015258789 578 | 2015-08-20T04:13:53.799Z,32.511495,35.018627,91.9000015258789 579 | 2015-08-20T04:13:57.883Z,32.511541,35.018559,92.5 580 | 2015-08-20T04:13:58.794Z,32.511551,35.018542,91.80000305175781 581 | 2015-08-20T04:14:03.880Z,32.511598,35.01846,92.80000305175781 582 | 2015-08-20T04:14:04.928Z,32.511604,35.018444,92.5999984741211 583 | 2015-08-20T04:14:10.074Z,32.511663,35.018369,92.80000305175781 584 | 2015-08-20T04:14:10.882Z,32.511675,35.018355,92.4000015258789 585 | 2015-08-20T04:14:16.882Z,32.511724,35.018267,90.4000015258789 586 | 2015-08-20T04:14:17.787Z,32.511738,35.018253,90.5 587 | 2015-08-20T04:14:21.900Z,32.511797,35.018196,89.0999984741211 588 | 2015-08-20T04:14:22.795Z,32.511806,35.018176,88.80000305175781 589 | 2015-08-20T04:14:27.035Z,32.511863,35.018103,93.5 590 | 2015-08-20T04:14:27.814Z,32.511876,35.018086,93.30000305175781 591 | 2015-08-20T04:14:32.930Z,32.51191,35.01799,91.30000305175781 592 | 2015-08-20T04:14:33.823Z,32.511919,35.017974,91.0 593 | 2015-08-20T04:14:39.152Z,32.511969,35.0179,93.0 594 | 2015-08-20T04:14:39.822Z,32.511981,35.017886,92.30000305175781 595 | 2015-08-20T04:14:45.935Z,32.512028,35.017796,94.19999694824219 596 | 2015-08-20T04:14:46.797Z,32.512037,35.017785,94.19999694824219 597 | 2015-08-20T04:14:52.855Z,32.5121,35.017713,93.9000015258789 598 | 2015-08-20T04:14:53.800Z,32.512113,35.017704,94.69999694824219 599 | 2015-08-20T04:14:58.953Z,32.512166,35.017636,96.30000305175781 600 | 2015-08-20T04:14:59.818Z,32.512176,35.017623,96.0999984741211 601 | 2015-08-20T04:15:05.903Z,32.512235,35.017543,96.80000305175781 602 | 2015-08-20T04:15:06.857Z,32.512245,35.01753,97.0 603 | 2015-08-20T04:15:12.020Z,32.512297,35.017461,94.19999694824219 604 | 2015-08-20T04:15:12.817Z,32.512305,35.017448,93.69999694824219 605 | 2015-08-20T04:15:19.098Z,32.512358,35.017372,95.19999694824219 606 | 2015-08-20T04:15:19.947Z,32.512367,35.017358,94.9000015258789 607 | 2015-08-20T04:15:24.889Z,32.512411,35.017285,94.30000305175781 608 | 2015-08-20T04:15:25.969Z,32.512421,35.01727,95.0 609 | 2015-08-20T04:15:31.057Z,32.51248,35.017192,96.4000015258789 610 | 2015-08-20T04:15:31.836Z,32.512492,35.017175,96.19999694824219 611 | 2015-08-20T04:15:36.910Z,32.512551,35.017096,98.19999694824219 612 | 2015-08-20T04:15:37.812Z,32.512563,35.017081,99.0 613 | 2015-08-20T04:15:42.857Z,32.512622,35.017014,97.19999694824219 614 | 2015-08-20T04:15:43.904Z,32.512629,35.016998,96.9000015258789 615 | 2015-08-20T04:15:48.929Z,32.512679,35.016924,98.0 616 | 2015-08-20T04:15:49.830Z,32.512686,35.016908,97.80000305175781 617 | 2015-08-20T04:15:54.946Z,32.512727,35.016819,98.69999694824219 618 | 2015-08-20T04:15:55.863Z,32.512735,35.0168,97.9000015258789 619 | 2015-08-20T04:15:59.939Z,32.512763,35.016714,97.0 620 | 2015-08-20T04:16:00.878Z,32.512769,35.016691,98.0 621 | 2015-08-20T04:16:05.942Z,32.512842,35.016637,99.80000305175781 622 | 2015-08-20T04:16:06.875Z,32.512859,35.016648,100.30000305175781 623 | 2015-08-20T04:16:10.956Z,32.512922,35.016715,100.0 624 | 2015-08-20T04:16:11.879Z,32.512936,35.016735,100.5 625 | 2015-08-20T04:16:15.900Z,32.512992,35.016803,101.5 626 | 2015-08-20T04:16:16.890Z,32.513005,35.016819,100.69999694824219 627 | 2015-08-20T04:16:20.894Z,32.51307,35.016871,102.4000015258789 628 | 2015-08-20T04:16:21.815Z,32.513084,35.016884,102.5 629 | 2015-08-20T04:16:27.117Z,32.513151,35.016949,105.4000015258789 630 | 2015-08-20T04:16:27.981Z,32.513166,35.016961,105.30000305175781 631 | 2015-08-20T04:16:31.960Z,32.513221,35.01702,106.5999984741211 632 | 2015-08-20T04:16:32.888Z,32.513232,35.017037,107.30000305175781 633 | 2015-08-20T04:16:36.966Z,32.513276,35.017107,106.19999694824219 634 | 2015-08-20T04:16:37.866Z,32.513287,35.017123,107.4000015258789 635 | 2015-08-20T04:16:43.057Z,32.51333,35.017208,108.80000305175781 636 | 2015-08-20T04:16:43.873Z,32.51334,35.017226,110.30000305175781 637 | 2015-08-20T04:16:47.848Z,32.513398,35.017278,109.5 638 | 2015-08-20T04:16:48.815Z,32.513411,35.017291,109.9000015258789 639 | 2015-08-20T04:16:52.875Z,32.513464,35.017348,111.19999694824219 640 | 2015-08-20T04:16:53.817Z,32.513477,35.017364,112.5 641 | 2015-08-20T04:16:57.999Z,32.513534,35.017427,113.4000015258789 642 | 2015-08-20T04:16:58.839Z,32.513548,35.017441,113.69999694824219 643 | 2015-08-20T04:17:03.026Z,32.513618,35.017485,113.0 644 | 2015-08-20T04:17:03.872Z,32.513639,35.01749,112.80000305175781 645 | 2015-08-20T04:17:07.843Z,32.513718,35.017455,113.5999984741211 646 | 2015-08-20T04:17:08.815Z,32.513731,35.017436,113.69999694824219 647 | 2015-08-20T04:17:11.930Z,32.51377,35.017373,114.0999984741211 648 | 2015-08-20T04:17:12.887Z,32.513784,35.017349,114.0 649 | 2015-08-20T04:17:15.874Z,32.513828,35.017284,114.5 650 | 2015-08-20T04:17:16.827Z,32.513843,35.017263,114.5999984741211 651 | 2015-08-20T04:17:19.920Z,32.513887,35.017201,114.4000015258789 652 | 2015-08-20T04:17:20.855Z,32.513897,35.017175,113.9000015258789 653 | 2015-08-20T04:17:24.052Z,32.51393,35.017102,113.5 654 | 2015-08-20T04:17:25.054Z,32.513935,35.017077,113.5999984741211 655 | 2015-08-20T04:17:27.916Z,32.51393,35.016994,113.9000015258789 656 | 2015-08-20T04:17:28.819Z,32.513929,35.016965,114.9000015258789 657 | 2015-08-20T04:17:31.911Z,32.513936,35.016881,114.9000015258789 658 | 2015-08-20T04:17:32.827Z,32.513941,35.016855,114.30000305175781 659 | 2015-08-20T04:17:36.970Z,32.513958,35.016764,113.5999984741211 660 | 2015-08-20T04:17:37.876Z,32.513959,35.016742,113.5999984741211 661 | 2015-08-20T04:17:41.925Z,32.513989,35.01666,113.5999984741211 662 | 2015-08-20T04:17:42.821Z,32.513999,35.016639,113.69999694824219 663 | 2015-08-20T04:17:46.931Z,32.514054,35.016579,111.9000015258789 664 | 2015-08-20T04:17:47.947Z,32.514065,35.016562,112.80000305175781 665 | 2015-08-20T04:17:51.892Z,32.514112,35.016492,113.69999694824219 666 | 2015-08-20T04:17:52.841Z,32.514126,35.016471,113.80000305175781 667 | 2015-08-20T04:17:56.908Z,32.51417,35.016384,114.19999694824219 668 | 2015-08-20T04:17:57.824Z,32.514178,35.016362,114.30000305175781 669 | 2015-08-20T04:18:01.921Z,32.51421,35.016274,114.30000305175781 670 | 2015-08-20T04:18:02.823Z,32.514221,35.016254,114.19999694824219 671 | 2015-08-20T04:18:06.896Z,32.514278,35.016184,114.80000305175781 672 | 2015-08-20T04:18:07.813Z,32.514296,35.016171,115.5999984741211 673 | 2015-08-20T04:18:10.895Z,32.514355,35.016146,115.5999984741211 674 | 2015-08-20T04:18:13.814Z,32.514421,35.016143,116.30000305175781 675 | 2015-08-20T04:18:17.869Z,32.514502,35.016162,117.5999984741211 676 | 2015-08-20T04:18:18.813Z,32.514522,35.016165,117.5 677 | 2015-08-20T04:18:22.862Z,32.514598,35.016182,117.4000015258789 678 | 2015-08-20T04:18:23.814Z,32.514616,35.016187,117.0999984741211 679 | 2015-08-20T04:18:27.863Z,32.514686,35.016171,116.69999694824219 680 | 2015-08-20T04:18:28.816Z,32.514703,35.016158,116.5999984741211 681 | 2015-08-20T04:18:32.870Z,32.514754,35.016085,116.5999984741211 682 | 2015-08-20T04:18:33.815Z,32.514765,35.01607,115.80000305175781 683 | 2015-08-20T04:18:37.847Z,32.514825,35.016018,117.30000305175781 684 | 2015-08-20T04:18:38.816Z,32.514843,35.016007,117.69999694824219 685 | 2015-08-20T04:18:42.882Z,32.514921,35.015984,117.5999984741211 686 | 2015-08-20T04:18:43.815Z,32.514942,35.015984,118.30000305175781 687 | 2015-08-20T04:18:47.897Z,32.51503,35.01597,118.30000305175781 688 | 2015-08-20T04:18:48.836Z,32.515053,35.01597,118.0999984741211 689 | 2015-08-20T04:18:50.877Z,32.515114,35.015958,116.4000015258789 690 | 2015-08-20T04:18:51.819Z,32.515146,35.015951,117.0999984741211 691 | 2015-08-20T04:18:54.007Z,32.515209,35.015942,117.0999984741211 692 | 2015-08-20T04:18:54.893Z,32.51524,35.015937,117.5 693 | 2015-08-20T04:18:57.939Z,32.515328,35.015943,118.5999984741211 694 | 2015-08-20T04:18:58.845Z,32.515358,35.015946,118.5 695 | 2015-08-20T04:19:01.992Z,32.515443,35.015964,118.30000305175781 696 | 2015-08-20T04:19:02.889Z,32.515462,35.015973,118.30000305175781 697 | 2015-08-20T04:19:06.990Z,32.515544,35.01601,118.69999694824219 698 | 2015-08-20T04:19:07.888Z,32.51556,35.016017,118.5999984741211 699 | 2015-08-20T04:19:11.886Z,32.515638,35.016042,118.5999984741211 700 | 2015-08-20T04:19:12.819Z,32.51566,35.016051,118.0 701 | 2015-08-20T04:19:16.911Z,32.515738,35.016069,117.9000015258789 702 | 2015-08-20T04:19:17.842Z,32.515757,35.016076,117.19999694824219 703 | 2015-08-20T04:19:21.908Z,32.515844,35.016087,116.4000015258789 704 | 2015-08-20T04:19:22.820Z,32.51587,35.016071,116.19999694824219 705 | 2015-08-20T04:19:25.934Z,32.515933,35.016016,116.0 706 | 2015-08-20T04:19:26.831Z,32.515953,35.015993,116.80000305175781 707 | 2015-08-20T04:19:29.879Z,32.516001,35.015918,116.5 708 | 2015-08-20T04:19:30.833Z,32.51602,35.015894,117.0 709 | 2015-08-20T04:19:34.152Z,32.516074,35.015828,116.5 710 | 2015-08-20T04:19:34.904Z,32.516091,35.015804,116.5 711 | 2015-08-20T04:19:37.851Z,32.516142,35.01573,116.5999984741211 712 | 2015-08-20T04:19:38.820Z,32.516157,35.015705,116.5 713 | 2015-08-20T04:19:41.881Z,32.516211,35.01564,115.4000015258789 714 | 2015-08-20T04:19:42.825Z,32.516225,35.015617,114.0999984741211 715 | 2015-08-20T04:19:45.963Z,32.516278,35.015551,113.5 716 | 2015-08-20T04:19:46.890Z,32.516301,35.015533,112.5 717 | 2015-08-20T04:19:49.987Z,32.516361,35.015468,112.0 718 | 2015-08-20T04:19:50.878Z,32.51638,35.015444,112.69999694824219 719 | 2015-08-20T04:19:53.937Z,32.516442,35.015369,112.5 720 | 2015-08-20T04:19:54.896Z,32.516462,35.015343,112.5999984741211 721 | 2015-08-20T04:19:58.048Z,32.516517,35.015264,112.30000305175781 722 | 2015-08-20T04:19:58.898Z,32.516537,35.015238,112.0999984741211 723 | 2015-08-20T04:20:01.965Z,32.516592,35.015157,110.0999984741211 724 | 2015-08-20T04:20:02.886Z,32.51661,35.015129,109.80000305175781 725 | 2015-08-20T04:20:05.959Z,32.516665,35.015048,107.69999694824219 726 | 2015-08-20T04:20:06.823Z,32.516683,35.015023,107.5 727 | 2015-08-20T04:20:09.926Z,32.516736,35.014943,107.5999984741211 728 | 2015-08-20T04:20:10.824Z,32.516754,35.014916,107.0999984741211 729 | 2015-08-20T04:20:14.040Z,32.5168,35.014835,106.0999984741211 730 | 2015-08-20T04:20:14.888Z,32.516818,35.01481,105.19999694824219 731 | 2015-08-20T04:20:17.897Z,32.516873,35.014737,106.4000015258789 732 | 2015-08-20T04:20:18.844Z,32.516889,35.014709,106.4000015258789 733 | 2015-08-20T04:20:21.996Z,32.516933,35.014617,103.5 734 | 2015-08-20T04:20:22.897Z,32.516945,35.014584,103.0999984741211 735 | 2015-08-20T04:20:24.905Z,32.516971,35.014518,103.80000305175781 736 | 2015-08-20T04:20:25.835Z,32.516984,35.014484,104.19999694824219 737 | 2015-08-20T04:20:28.982Z,32.51702,35.014387,104.80000305175781 738 | 2015-08-20T04:20:29.923Z,32.517035,35.014355,105.19999694824219 739 | 2015-08-20T04:20:32.863Z,32.517087,35.014279,102.9000015258789 740 | 2015-08-20T04:20:33.994Z,32.517098,35.014264,102.4000015258789 741 | 2015-08-20T04:20:42.329Z,32.517142,35.014212,103.4000015258789 742 | -------------------------------------------------------------------------------- /Ch06/06_03/track.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "abd119de-5319-43c1-8866-fdbad80616ac", 6 | "metadata": {}, 7 | "source": [ 8 | "# Calculate Running Speed" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 1, 14 | "id": "9a86be15-068f-4e79-8c09-042e8d7ea8b0", 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "import pandas as pd\n", 19 | "from os import environ\n", 20 | "\n", 21 | "import tracklib" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 3, 27 | "id": "b1d2c42f-70fb-4258-9221-4bca2a768d6e", 28 | "metadata": {}, 29 | "outputs": [ 30 | { 31 | "name": "stdout", 32 | "output_type": "stream", 33 | "text": [ 34 | "9.58044454743704\n" 35 | ] 36 | } 37 | ], 38 | "source": [ 39 | "csv_file = environ.get('CSV_FILE', 'track.csv')\n", 40 | "df = tracklib.load_csv(csv_file)\n", 41 | "speed_kmh = tracklib.running_speed(df)\n", 42 | "print(speed_kmh.mean())" 43 | ] 44 | } 45 | ], 46 | "metadata": { 47 | "kernelspec": { 48 | "display_name": "Python 3 (ipykernel)", 49 | "language": "python", 50 | "name": "python3" 51 | }, 52 | "language_info": { 53 | "codemirror_mode": { 54 | "name": "ipython", 55 | "version": 3 56 | }, 57 | "file_extension": ".py", 58 | "mimetype": "text/x-python", 59 | "name": "python", 60 | "nbconvert_exporter": "python", 61 | "pygments_lexer": "ipython3", 62 | "version": "3.10.4" 63 | } 64 | }, 65 | "nbformat": 4, 66 | "nbformat_minor": 5 67 | } 68 | -------------------------------------------------------------------------------- /Ch06/06_03/track_before.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "abd119de-5319-43c1-8866-fdbad80616ac", 6 | "metadata": {}, 7 | "source": [ 8 | "# Calculate Running Speed" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "d423b72a-e2bd-4c32-add6-297ee43f423f", 14 | "metadata": {}, 15 | "source": [ 16 | "## Load Data" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 10, 22 | "id": "9a86be15-068f-4e79-8c09-042e8d7ea8b0", 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "import pandas as pd\n", 27 | "from os import environ" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": 11, 33 | "id": "b1d2c42f-70fb-4258-9221-4bca2a768d6e", 34 | "metadata": {}, 35 | "outputs": [], 36 | "source": [ 37 | "csv_file = environ.get('CSV_FILE', 'track.csv')\n", 38 | "df = pd.read_csv(csv_file, parse_dates=['time'])" 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "id": "80004a1e-c15d-4a1b-a41a-ee4ee4f149a3", 44 | "metadata": {}, 45 | "source": [ 46 | "## Calculate Speed\n", 47 | "\n", 48 | "For simplicity, we're using Euclidean distance." 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": 5, 54 | "id": "4b2b73fa-7088-4dfd-800e-5bc613a6428a", 55 | "metadata": {}, 56 | "outputs": [], 57 | "source": [ 58 | "import numpy as np\n", 59 | "\n", 60 | "lat1, lat2 = df['lat'], df['lat'].shift()\n", 61 | "lng1, lng2 = df['lng'], df['lng'].shift()\n", 62 | "\n", 63 | "\n", 64 | "lat_km = 92\n", 65 | "lng_km = 111\n", 66 | "\n", 67 | "delta_lat = (lat1 - lat2) * lat_km\n", 68 | "delta_lng = (lng1 - lng2) * lng_km\n", 69 | "dist_km = np.hypot(delta_lat, delta_lng)" 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "id": "90524989-d517-4189-87a0-812f0a0c90f3", 75 | "metadata": {}, 76 | "source": [ 77 | "## Calculate Time & Speed" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": 6, 83 | "id": "8298d052-624d-444b-b862-6721c2de35a1", 84 | "metadata": {}, 85 | "outputs": [], 86 | "source": [ 87 | "duration = df['time'].diff()\n", 88 | "duration_hours = duration / pd.Timedelta(hours=1)\n", 89 | "speed_kmh = dist_km / duration_hours" 90 | ] 91 | }, 92 | { 93 | "cell_type": "markdown", 94 | "id": "808cdec4-f6fe-4fff-9356-371900e6fdcb", 95 | "metadata": {}, 96 | "source": [ 97 | "## Display Average Speed" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": 13, 103 | "id": "1db39f43-46dd-4c33-8347-52235a2d090c", 104 | "metadata": {}, 105 | "outputs": [ 106 | { 107 | "data": { 108 | "text/plain": [ 109 | "9.58044454743704" 110 | ] 111 | }, 112 | "execution_count": 13, 113 | "metadata": {}, 114 | "output_type": "execute_result" 115 | } 116 | ], 117 | "source": [ 118 | "speed_kmh.mean()" 119 | ] 120 | }, 121 | { 122 | "cell_type": "markdown", 123 | "id": "7dd567b2-5494-441d-9344-41e69cb0286f", 124 | "metadata": {}, 125 | "source": [ 126 | "## Test Output" 127 | ] 128 | }, 129 | { 130 | "cell_type": "code", 131 | "execution_count": 14, 132 | "id": "96ef0dcb-2de8-47e5-9314-1f87e75baf72", 133 | "metadata": {}, 134 | "outputs": [], 135 | "source": [ 136 | "import json\n", 137 | "\n", 138 | "out_file = environ.get('OUT_FILE')\n", 139 | "if out_file:\n", 140 | " response = {'mean_speed': speed_kmh.mean()}\n", 141 | " with open(out_file, 'w') as out:\n", 142 | " json.dump(response, out)" 143 | ] 144 | } 145 | ], 146 | "metadata": { 147 | "kernelspec": { 148 | "display_name": "Python 3 (ipykernel)", 149 | "language": "python", 150 | "name": "python3" 151 | }, 152 | "language_info": { 153 | "codemirror_mode": { 154 | "name": "ipython", 155 | "version": 3 156 | }, 157 | "file_extension": ".py", 158 | "mimetype": "text/x-python", 159 | "name": "python", 160 | "nbconvert_exporter": "python", 161 | "pygments_lexer": "ipython3", 162 | "version": "3.10.4" 163 | } 164 | }, 165 | "nbformat": 4, 166 | "nbformat_minor": 5 167 | } 168 | -------------------------------------------------------------------------------- /Ch06/06_03/tracklib.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | 4 | lat_km = 92 5 | lng_km = 111 6 | 7 | 8 | def load_csv(csv_file): 9 | """Load track data from CSV file.""" 10 | return pd.read_csv(csv_file, parse_dates=['time']) 11 | 12 | 13 | def calc_distance(lat1, lng1, lat2, lng2): 14 | """Return Euclidean distance in kilometers.""" 15 | delta_lat = (lat1 - lat2) * lat_km 16 | delta_lng = (lng1 - lng2) * lng_km 17 | return np.hypot(delta_lat, delta_lng) 18 | 19 | 20 | def running_speed(df): 21 | """Calculate running speed.""" 22 | lat1, lat2 = df['lat'], df['lat'].shift() 23 | lng1, lng2 = df['lng'], df['lng'].shift() 24 | dist_km = calc_distance(lat1, lng1, lat2, lng2) 25 | duration = df['time'].diff() 26 | duration_hours = duration / pd.Timedelta(hours=1) 27 | return dist_km / duration_hours -------------------------------------------------------------------------------- /Ch06/06_04/test_track.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | import numpy as np 4 | from testbook import testbook 5 | 6 | here = Path(__file__).absolute().parent 7 | ipynb = here / 'track.ipynb' 8 | 9 | @testbook(ipynb, execute=True) 10 | def test_distance(tb): 11 | calc_distance = tb.ref('calc_distance') 12 | dist = calc_distance(0, 0, 1, 1) 13 | assert np.allclose(144.17003, dist) -------------------------------------------------------------------------------- /Ch06/06_04/track.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "id": "4ba0d8e5-7c07-4fe3-82a2-4653823a2214", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "import numpy as np\n", 11 | "\n", 12 | "\n", 13 | "lat_km = 92\n", 14 | "lng_km = 111\n", 15 | "\n", 16 | "\n", 17 | "def calc_distance(lat1, lng1, lat2, lng2):\n", 18 | " \"\"\"Return Euclidean distance in kilometers.\"\"\"\n", 19 | " delta_lat = (lat1 - lat2) * lat_km\n", 20 | " delta_lng = (lng1 - lng2) * lng_km\n", 21 | " return np.hypot(delta_lat, delta_lng)" 22 | ] 23 | } 24 | ], 25 | "metadata": { 26 | "kernelspec": { 27 | "display_name": "Python 3 (ipykernel)", 28 | "language": "python", 29 | "name": "python3" 30 | }, 31 | "language_info": { 32 | "codemirror_mode": { 33 | "name": "ipython", 34 | "version": 3 35 | }, 36 | "file_extension": ".py", 37 | "mimetype": "text/x-python", 38 | "name": "python", 39 | "nbconvert_exporter": "python", 40 | "pygments_lexer": "ipython3", 41 | "version": "3.10.4" 42 | } 43 | }, 44 | "nbformat": 4, 45 | "nbformat_minor": 5 46 | } 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | LinkedIn Learning Exercise Files License Agreement 2 | ================================================== 3 | 4 | This License Agreement (the "Agreement") is a binding legal agreement 5 | between you (as an individual or entity, as applicable) and LinkedIn 6 | Corporation (“LinkedIn”). By downloading or using the LinkedIn Learning 7 | exercise files in this repository (“Licensed Materials”), you agree to 8 | be bound by the terms of this Agreement. If you do not agree to these 9 | terms, do not download or use the Licensed Materials. 10 | 11 | 1. License. 12 | - a. Subject to the terms of this Agreement, LinkedIn hereby grants LinkedIn 13 | members during their LinkedIn Learning subscription a non-exclusive, 14 | non-transferable copyright license, for internal use only, to 1) make a 15 | reasonable number of copies of the Licensed Materials, and 2) make 16 | derivative works of the Licensed Materials for the sole purpose of 17 | practicing skills taught in LinkedIn Learning courses. 18 | - b. Distribution. Unless otherwise noted in the Licensed Materials, subject 19 | to the terms of this Agreement, LinkedIn hereby grants LinkedIn members 20 | with a LinkedIn Learning subscription a non-exclusive, non-transferable 21 | copyright license to distribute the Licensed Materials, except the 22 | Licensed Materials may not be included in any product or service (or 23 | otherwise used) to instruct or educate others. 24 | 25 | 2. Restrictions and Intellectual Property. 26 | - a. You may not to use, modify, copy, make derivative works of, publish, 27 | distribute, rent, lease, sell, sublicense, assign or otherwise transfer the 28 | Licensed Materials, except as expressly set forth above in Section 1. 29 | - b. Linkedin (and its licensors) retains its intellectual property rights 30 | in the Licensed Materials. Except as expressly set forth in Section 1, 31 | LinkedIn grants no licenses. 32 | - c. You indemnify LinkedIn and its licensors and affiliates for i) any 33 | alleged infringement or misappropriation of any intellectual property rights 34 | of any third party based on modifications you make to the Licensed Materials, 35 | ii) any claims arising from your use or distribution of all or part of the 36 | Licensed Materials and iii) a breach of this Agreement. You will defend, hold 37 | harmless, and indemnify LinkedIn and its affiliates (and our and their 38 | respective employees, shareholders, and directors) from any claim or action 39 | brought by a third party, including all damages, liabilities, costs and 40 | expenses, including reasonable attorneys’ fees, to the extent resulting from, 41 | alleged to have resulted from, or in connection with: (a) your breach of your 42 | obligations herein; or (b) your use or distribution of any Licensed Materials. 43 | 44 | 3. Open source. This code may include open source software, which may be 45 | subject to other license terms as provided in the files. 46 | 47 | 4. Warranty Disclaimer. LINKEDIN PROVIDES THE LICENSED MATERIALS ON AN “AS IS” 48 | AND “AS AVAILABLE” BASIS. LINKEDIN MAKES NO REPRESENTATION OR WARRANTY, 49 | WHETHER EXPRESS OR IMPLIED, ABOUT THE LICENSED MATERIALS, INCLUDING ANY 50 | REPRESENTATION THAT THE LICENSED MATERIALS WILL BE FREE OF ERRORS, BUGS OR 51 | INTERRUPTIONS, OR THAT THE LICENSED MATERIALS ARE ACCURATE, COMPLETE OR 52 | OTHERWISE VALID. TO THE FULLEST EXTENT PERMITTED BY LAW, LINKEDIN AND ITS 53 | AFFILIATES DISCLAIM ANY IMPLIED OR STATUTORY WARRANTY OR CONDITION, INCLUDING 54 | ANY IMPLIED WARRANTY OR CONDITION OF MERCHANTABILITY OR FITNESS FOR A 55 | PARTICULAR PURPOSE, AVAILABILITY, SECURITY, TITLE AND/OR NON-INFRINGEMENT. 56 | YOUR USE OF THE LICENSED MATERIALS IS AT YOUR OWN DISCRETION AND RISK, AND 57 | YOU WILL BE SOLELY RESPONSIBLE FOR ANY DAMAGE THAT RESULTS FROM USE OF THE 58 | LICENSED MATERIALS TO YOUR COMPUTER SYSTEM OR LOSS OF DATA. NO ADVICE OR 59 | INFORMATION, WHETHER ORAL OR WRITTEN, OBTAINED BY YOU FROM US OR THROUGH OR 60 | FROM THE LICENSED MATERIALS WILL CREATE ANY WARRANTY OR CONDITION NOT 61 | EXPRESSLY STATED IN THESE TERMS. 62 | 63 | 5. Limitation of Liability. LINKEDIN SHALL NOT BE LIABLE FOR ANY INDIRECT, 64 | INCIDENTAL, SPECIAL, PUNITIVE, CONSEQUENTIAL OR EXEMPLARY DAMAGES, INCLUDING 65 | BUT NOT LIMITED TO, DAMAGES FOR LOSS OF PROFITS, GOODWILL, USE, DATA OR OTHER 66 | INTANGIBLE LOSSES . IN NO EVENT WILL LINKEDIN'S AGGREGATE LIABILITY TO YOU 67 | EXCEED $100. THIS LIMITATION OF LIABILITY SHALL: 68 | - i. APPLY REGARDLESS OF WHETHER (A) YOU BASE YOUR CLAIM ON CONTRACT, TORT, 69 | STATUTE, OR ANY OTHER LEGAL THEORY, (B) WE KNEW OR SHOULD HAVE KNOWN ABOUT 70 | THE POSSIBILITY OF SUCH DAMAGES, OR (C) THE LIMITED REMEDIES PROVIDED IN THIS 71 | SECTION FAIL OF THEIR ESSENTIAL PURPOSE; AND 72 | - ii. NOT APPLY TO ANY DAMAGE THAT LINKEDIN MAY CAUSE YOU INTENTIONALLY OR 73 | KNOWINGLY IN VIOLATION OF THESE TERMS OR APPLICABLE LAW, OR AS OTHERWISE 74 | MANDATED BY APPLICABLE LAW THAT CANNOT BE DISCLAIMED IN THESE TERMS. 75 | 76 | 6. Termination. This Agreement automatically terminates upon your breach of 77 | this Agreement or termination of your LinkedIn Learning subscription. On 78 | termination, all licenses granted under this Agreement will terminate 79 | immediately and you will delete the Licensed Materials. Sections 2-7 of this 80 | Agreement survive any termination of this Agreement. LinkedIn may discontinue 81 | the availability of some or all of the Licensed Materials at any time for any 82 | reason. 83 | 84 | 7. Miscellaneous. This Agreement will be governed by and construed in 85 | accordance with the laws of the State of California without regard to conflict 86 | of laws principles. The exclusive forum for any disputes arising out of or 87 | relating to this Agreement shall be an appropriate federal or state court 88 | sitting in the County of Santa Clara, State of California. If LinkedIn does 89 | not act to enforce a breach of this Agreement, that does not mean that 90 | LinkedIn has waived its right to enforce this Agreement. The Agreement does 91 | not create a partnership, agency relationship, or joint venture between the 92 | parties. Neither party has the power or authority to bind the other or to 93 | create any obligation or responsibility on behalf of the other. You may not, 94 | without LinkedIn’s prior written consent, assign or delegate any rights or 95 | obligations under these terms, including in connection with a change of 96 | control. Any purported assignment and delegation shall be ineffective. The 97 | Agreement shall bind and inure to the benefit of the parties, their respective 98 | successors and permitted assigns. If any provision of the Agreement is 99 | unenforceable, that provision will be modified to render it enforceable to the 100 | extent possible to give effect to the parties’ intentions and the remaining 101 | provisions will not be affected. This Agreement is the only agreement between 102 | you and LinkedIn regarding the Licensed Materials, and supersedes all prior 103 | agreements relating to the Licensed Materials. 104 | 105 | Last Updated: March 2019 106 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2022 LinkedIn Corporation 2 | All Rights Reserved. 3 | 4 | Licensed under the LinkedIn Learning Exercise File License (the "License"). 5 | See LICENSE in the project root for license information. 6 | 7 | ATTRIBUTIONS: 8 | [PLEASE PROVIDE ATTRIBUTIONS OR DELETE THIS AND THE ABOVE LINE “ATTRIBUTIONS”] 9 | 10 | Please note, this project may automatically load third party code from external 11 | repositories (for example, NPM modules, Composer packages, or other dependencies). 12 | If so, such third party code may be subject to other license terms than as set 13 | forth above. In addition, such third party code may also depend on and load 14 | multiple tiers of dependencies. Please review the applicable licenses of the 15 | additional dependencies. 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Testing Python Data Science Code 2 | This is the repository for the LinkedIn Learning course Testing Python Data Science Code. The full course is available from [LinkedIn Learning][lil-course-url]. 3 | 4 | ![Testing Python Data Science Code][lil-thumbnail-url] 5 | 6 | The larger and more complex the world of data science becomes, the more data there is to collect, sort, clean, model on, and much more. An emerging pain point in this brave new world is that a lot can go wrong if your data engineering and development practices are shoddy. This advanced-level course shows data scientists, Python developers, and data analysts how to test scientific (data science) code written in Python. Veteran data science trainer and consultant Miki Tebeka covers testing techniques, with a focus on issues specific to data science code, such as floating point errors, statistical testing, working with large datasets, choosing a baseline, and more. After presenting a testing overview, Miki dives into testing with pytest and hypothesis. He explains how to use schemas, truth values, approximate testing, and more in data validation. Miki goes over regression testing, then demonstrates how to test Jupyter Notebooks. 7 | 8 | 9 | ### Instructor 10 | 11 | Miki Tebeka 12 | 13 | 14 | 15 | 16 | 17 | Check out my other courses on [LinkedIn Learning](https://www.linkedin.com/learning/instructors/miki-tebeka). 18 | 19 | [lil-course-url]: https://www.linkedin.com/learning/testing-python-data-science-code 20 | [lil-thumbnail-url]: https://cdn.lynda.com/course/2477020/2477020-1661795583756-16x9.jpg 21 | -------------------------------------------------------------------------------- /create_env.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from subprocess import run 4 | from sys import executable, platform 5 | 6 | 7 | def call(cmd): 8 | print(' '.join(cmd)) 9 | run(cmd, check=True) 10 | 11 | 12 | venv = '.venv' 13 | call([executable, '-m', 'venv', venv]) 14 | if platform == 'win32': 15 | py = f'{venv}/Scripts/python.exe' 16 | else: 17 | py = f'{venv}/bin/python' 18 | call([py, '-m', 'pip', 'install', '--upgrade', 'pip']) 19 | call([py, '-m', 'pip', 'install', '-r', 'requirements.txt']) 20 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | flask~=2.1 2 | hypothesis~=6.52 3 | ipython~=8.4 4 | jupyterlab~=3.4 5 | pandas~=1.4 6 | pandera~=0.11 7 | psutil!=5.9 8 | pytest~=7.1 9 | PyYAML~=6.0 10 | scikit-learn~=1.1 11 | testbook~=0.4 12 | --------------------------------------------------------------------------------