Archivo por meses: marzo 2021

Segmentos de ciclismo con la API de Strava

De la API de Strava me interesa sobretodo la parte de segmentos, que son trozos de rutas donde la gent se cronometra y se publican los rankings. Sin una subscripción Premium no se puede acceder a toda la información. Jugando un rato con la API de Strava he llegado a poder ver los segmentos que hay en una zona geográfica, y poder ver los puntos de este segmento, que se pueden representar en cualquier mapa.

Para acceder a la información de un segmento:

$ curl -X GET https://www.strava.com/api/v3/segments/229781 -H 'Authorization: Bearer *******************'

Y el resultado:

{"id":229781,"resource_state":3,"name":"Hawk Hill","activity_type":"Ride","distance":2684.82,"average_grade":5.8,"maximum_grade":10.9,"elevation_high":247.2,"elevation_low":92.0,"start_latlng":[37.833112,-122.483436],"end_latlng":[37.828072,-122.498139],"elevation_profile":"https://d3o5xota0a1fcr.cloudfront.net/v6/charts/KO5P7GCFLK5P5NF5GNUX3D6IVFLIEYRYD6JRBEGMXHOCPENJUQZXD5IIEJOYINQE2HX3XLZMYRTF5GHG5JLQ====","start_latitude":37.833112,"start_longitude":-122.483436,"end_latitude":37.828072,"end_longitude":-122.498139,"climb_category":1,"city":"San Francisco","state":"CA","country":"United States","private":false,"hazardous":false,"starred":false,"created_at":"2009-09-21T20:29:41Z","updated_at":"2021-03-13T09:01:33Z","total_elevation_gain":155.2,

"map":{"id":"s229781","polyline":"}g|eFnpqjVl@En@Md@HbAd@d@^h@Xx@VbARjBDh@OPQf@w@d@k@XKXDFPF\\CbGT`AV`@v@|@NTNb@?XOb@cAxAWLuE@eAFMBoAv@eBt@q@b@}@tAeAt@i@dAC`AFZj@dBA~@Yh@MbAVn@b@b@\\d@Ef@Qd@_@d@eB|@c@h@YfBI|AMpA?VF\\\\t@f@t@h@j@|@b@hCb@b@XTd@Bl@GtA?jAL`ALp@Tr@RXd@Rx@Pn@^Zh@Tx@Zf@`@FTCzDy@f@Yx@m@n@Op@VJr@","resource_state":3},

"effort_count":556805,"athlete_count":49100,"star_count":5022,"athlete_segment_stats":{"pr_elapsed_time":null,"pr_date":null,"pr_activity_id":null,"effort_count":0},"xoms":{"kom":"5:37","qom":"6:42","destination":{"href":"strava://segments/229781/leaderboard","type":"overall","name":"All-Time"}},"local_legend":{"athlete_id":54312907,"title":"Dalton Nonweiler","profile":"https://dgalywyr863hv.cloudfront.net/pictures/athletes/54312907/14907176/5/large.jpg","effort_description":"86 efforts in the last 90 days","effort_count":"86","effort_counts":{"overall":"86 efforts","female":"41 efforts"},"destination":"strava://segments/229781/local_legend?categories%5B%5D=overall"}}

Vemos que la polilinea está codificada en una cadena de texto. La podemos decodificar y obtener las coordenadas:

$ pip3 install polyline

$ python3
>> import polyline
>> #polyline.decode(summary_polyline)
>> polyline.decode("gxu{Fem|Kc@fAq@fAoApAMR[ZMXw@v@a@VQZi@j@sAhAk@hA_@f@oDxCiAhA_@j@a@~@{@pCC`@EFD^H`B?`@BNNZV@JGDMEqA@q@H]NOFSLo@t@eB^i@d@i@t@m@n@Yz@EHBR\\`AdDFdEJ`@RNHIVGf@ATH`At@VXDl@GJU@WY[e@YSKC_@GgA@YMKMc@eBYeBSWg@AUTSVa@|@[tAAPDb@Nr@@TCb@[bACd@BNJ^Xh@N^BNB`@Nn@DJTNZ\\Rn@?\\c@zAA^B\\JZHHh@NZDVHTRHJBNAb@I|@B\\Th@PTVf@F`@Cl@Sj@WJ{Ae@{@OKBSPOr@IvA[z@UTw@JWE_@]QUUKKCu@Hs@NMEIIi@kAOUGE]OUMGIGY?y@XiB@]E]U[SGU?c@XcA`Aw@|@i@~@WbASPK?IC_Au@q@_@SAI@g@Lo@XK?YB[MYOQSQYi@Y_@AK@CDg@X]Bg@KUMi@e@[k@GU@MHQb@a@DIFU@WIYg@u@]y@IqAP{ABq@Is@e@iB}@wAw@oBk@aAa@g@g@w@Km@Q{AYkB_AmCc@eB?]H]NWxAiBZq@JYFm@@m@C[G]OWa@k@eAu@o@k@iBkCm@k@SKc@CK@]LS@e@]]]E@GDEH@`@PZJd@CHEFI?OSMe@Uk@")

[(41.40436, 2.11683), (41.40454, 2.11647), (41.40479, 2.11611), (41.40519, 2.1157), (41.40526, 2.1156), (41.4054, 2.11546), (41.40547, 2.11533), 
...
(41.41868, 2.11667), (41.41859, 2.11653), (41.41853, 2.11634), (41.41855, 2.11629), (41.41858, 2.11625), (41.41863, 2.11625), (41.41871, 2.11635), (41.41878, 2.11654), (41.41889, 2.11676)]

Referències:

Gráficos interactivos con Jupyter Notebooks: tiro parabólico

Ahora que ya he empezado a hacer pruebas con Jupyter Notebook, el siguiente paso que quiero probar es hacer gráficos interactivos. Pues ha resultado ser más fácil y rápido de lo que pensaba.

Partimos de un script python que simula los datos experimentales de una trayectoria parabólica, y calcula la parábola que mejor se ajusta (regresión cuadrática). A partir de la ecuación de la parábola se puede deducir la constante g (=9,81 m/s2). Simulamos los datos experimentales introduciendo un error de ruido en los datos teóricos. Pues bien, con mi gráfico interactivo puedo jugar con el nivel de ruido y con el número de puntos del muestreo, tal com se ve en el video. El código queda de la siguiente forma:

%matplotlib inline
from ipywidgets import interactive
import numpy as np
import pylab as plt
from IPython.display import display, Math, Latex

# tir parabòlic: y = vy*t - .5gt^2
vy = 10 # 10m/s
g = 9.81 # m/s^2
t_max = 2*vy/g

def f(nivell_soroll, num_punts):
    t = np.linspace(0, t_max, num_punts)
    y_or = vy*t - .5*g*t**2
    noise = np.random.normal(0, nivell_soroll, num_punts) # simulem dades experimentals
    y = y_or + noise

    # ajustament a una paràbola
    z = np.polyfit(t, y, 2)
    g_exp = 2.0*z[0]

    t_ = np.linspace(0, t_max, 100)
    y_ = z[0]*t_**2 + z[1]*t_ + z[2]

    fig, ax = plt.subplots()
    plt.plot(t_, y_, t, y, 'bo')
    plt.suptitle("Tir parabòlic. Regressió quadràtica")
    plt.title("y = " + str(round(z[0],3)) + "t^2 + " + str(round(z[1],3)) + "t + " + str(round(z[2],3)) + " -> g exp = " + str(round(g_exp,3)) + " m/s^2")
    ax.set(xlabel='temps (s)', ylabel='y (m)')
    ax.grid()
    plt.show()
    
interactive_plot = interactive(f, nivell_soroll=(0.0, 2.0),  num_punts=(10, 50))
interactive_plot

Otra cosa que me interesa es la manera de exportar estos Jupyter Notebooks a una web, conservando las gráficas y las fórmulas en format Latex (aunque se pierda la interacció con las gráficas). Esto se consigue directamente exportando el Notebook a html:

$ jupyter nbconvert --execute tir_parabolic.ipynb --to html

e integrando este código en una web donde haya más texto y explicaciones, y con la librería Bootstrap.

Introducción a Jupyter Notebooks

Ya hace tiempo que tenía ganas de mirar qué es esto de Jupyter Notebook, del que se está hablando mucho y cada vez se hablará más. Este es el primer ejemplo que hago, la solución de la ecuación de 2o grado con python y la librería sympy, que he cogido de una página que me gusta mucho: arachnoid.com.

El siguiente paso será mirar Jupyter Lab, que proporciona una interfície más moderna, y tengo ganas de jugar con widgets y sliders para poder hacer cosas más interactivas. Ahora que estoy programando bastante con Python para preparar ejemplos para las clases de CNED en la UPC, hacerlo con las Notebooks de Jupyter sería una manera muy puntera de hacer clases interactivas.

Referencias:

Incendio en OVH Estrasburgo

Esta noche ha habido un incendio en los servidores de OVH en Estrasburgo, me he enterado por Twitter. Cuando me he levantado, he comprobado que la mediawiki de wiki.joanillo.org y este bloc de www.joanillo.org estaban activos. Sabía que mi máquina estaba en Francia, y ya me temía lo peor. Por suerte, he comprobado que mi máquina está en Gravelines, que es una localidad en el Pas de Calais. Suerte! De todas formas, tenía hecha una copia de seguridad de la wiki de hacía un par de días.

Esto nos tiene que hacer reflexionar sobre lo líquido y lo intangible de la información en la nube… Precisamente esta semana íbamos a contratar los servicios de OVH para alojar la web del instituto.