From 3805470e8ef8e2b19ef56ae0beab0b61a4e3e68f Mon Sep 17 00:00:00 2001 From: Prince Date: Mon, 30 Mar 2026 18:30:53 +0000 Subject: [PATCH 1/2] feat: add optional coastline layer to 3D visualization --- .../visualise/geo_data.py | 2 + src/weather_model_graphs/visualise/plot_3d.py | 560 ++++++++++++++++++ 2 files changed, 562 insertions(+) create mode 100644 src/weather_model_graphs/visualise/geo_data.py create mode 100644 src/weather_model_graphs/visualise/plot_3d.py diff --git a/src/weather_model_graphs/visualise/geo_data.py b/src/weather_model_graphs/visualise/geo_data.py new file mode 100644 index 0000000..716a346 --- /dev/null +++ b/src/weather_model_graphs/visualise/geo_data.py @@ -0,0 +1,2 @@ +COAST_LONS = [61.21, 62.98, 63.98, 64.75, 65.75, 66.52, 67.83, 68.86, 69.52, 70.27, 70.81, 71.24, 71.45, 72.19, 73.26, 74.98, 74.58, 72.92, 71.26, 71.61, 71.16, 69.93, 69.69, 69.32, 68.56, 67.68, 66.38, 65.05, 64.15, 62.55, 61.78, 60.94, 60.54, 60.53, 61.21, None, 16.33, 16.86, 17.47, 18.46, 19.17, 20.04, 20.6, 21.73, 21.95, 21.88, 22.16, 22.84, 23.91, 23.9, 23.93, 21.93, 22.56, 21.38, 18.26, 14.06, 12.81, 11.73, 11.78, 12.18, 12.74, 13.63, 13.69, 13.12, 12.93, 12.93, 12.23, 12.74, 13.38, None, 12.44, 11.91, 12.62, 12.63, 12.44, None, 20.59, 20.61, 21.0, 20.61, 19.98, 19.41, 19.4, 19.37, 19.74, 20.07, 20.52, None, 51.58, 51.79, 53.4, 54.69, 56.07, 56.4, 55.8, 55.53, 55.23, 55.01, 51.62, None, -65.5, -66.96, -68.63, -68.25, -66.45, -65.5, None, -64.96, -63.99, -62.69, -60.03, -57.78, -58.62, -56.49, -54.79, -54.13, -53.65, -55.16, -57.63, -58.14, -58.35, -58.5, -57.36, -56.79, -59.23, -62.34, -62.33, -62.75, -64.73, -64.98, -63.76, -64.38, -65.33, -66.51, -67.58, -65.64, -67.17, -68.73, -68.82, -68.57, -71.91, -72.31, -73.33, -72.65, -72.45, -71.55, -71.22, -71.79, -71.92, -71.75, -71.68, -70.81, -71.12, -70.39, -69.81, -70.54, -70.01, -69.0, -68.59, -68.42, -66.99, -66.27, None, 43.58, 45.18, 45.36, 45.61, 46.48, 46.14, 45.74, 45.0, 44.4, 43.75, None, -59.57, -60.16, -64.49, -65.74, -64.04, -61.14, -59.57, None, -159.21, -162.44, -163.07, -163.11, -160.25, -159.21, None, -45.15, -43.49, -43.33, -46.51, -50.48, -54.16, -51.85, -50.36, -49.31, -48.66, -46.66, None, -121.21, -118.72, -120.23, -122.62, -122.41, None, -125.56, -124.62, -127.28, -126.56, None, -98.98, -96.79, -96.98, -99.43, -101.8, -101.7, -98.98, None, -68.45, -68.51, -69.96, -72.39, -73.07, -74.95, -73.92, -73.23, -71.78, -71.74, -70.25, -69.49, -68.73, None, -58.61, -59.79, -61.3, -62.51, -62.59, -62.81, -64.29, -65.51, -65.31, -63.96, -62.79, -62.28, -61.51, -61.08, -60.69, -61.38, -63.3, -64.35, -67.19, -69.8, -72.21, -75.56, -76.93, -74.28, -74.77, -77.93, -78.02, -76.63, -73.24, -70.01, -65.7, -61.55, -58.71, -57.01, -53.62, -49.76, -44.83, -42.16, -38.24, -34.39, -30.1, -29.25, -29.69, -33.68, -35.91, -35.33, -32.21, -29.78, -27.51, -25.47, -22.46, -20.01, -17.52, -15.7, -16.47, -15.45, -13.31, -11.51, -10.3, -8.61, -7.38, -5.79, -4.34, -1.8, -0.23, 1.89, 4.14, 6.27, 7.74, 9.53, 10.82, 12.4, 14.73, 15.95, 18.2, 20.38, 21.92, 23.67, 25.98, 28.09, 30.03, 31.99, 33.3, 34.91, 36.16, 37.91, 39.67, 40.92, 42.94, 44.9, 46.5, 48.34, 49.93, 50.95, 52.61, 54.53, 56.36, 57.26, 58.74, 60.61, 62.39, 64.05, 65.97, 67.89, 69.71, 69.56, 67.81, 69.07, 68.42, 68.71, 71.02, 71.91, 73.08, 73.86, 75.63, 77.64, 78.43, 80.09, 81.48, 82.78, 84.68, 86.75, 87.99, 88.83, 90.63, 92.61, 94.18, 95.78, 97.76, 99.72, 100.89, 102.83, 104.24, 106.18, 108.08, 110.24, 111.74, 113.6, 114.9, 116.7, 118.58, 120.87, 122.32, 124.12, 126.1, 127.88, 129.7, 131.8, 133.86, 135.03, 135.7, 136.21, 137.46, 139.91, 142.12, 144.37, 146.2, 146.65, 148.84, 151.48, 153.64, 155.17, 156.81, 159.18, 160.81, 162.69, 164.92, 167.31, 169.46, 171.21, 170.56, 169.76, 167.98, 166.09, 164.96, 163.82, 163.47, 164.06, 164.74, 167.0, 163.67, 160.92, 160.32, 161.12, 162.49, 165.1, 168.9, 172.28, 173.22, 178.28, -179.94, -177.26, -176.08, -175.83, -173.12, -169.95, -168.53, -164.18, -158.07, -150.94, -145.89, -142.89, -150.06, -153.59, -153.04, -152.86, -155.29, -154.41, -150.65, -147.22, -146.77, -149.53, -153.39, -155.98, -158.05, -157.88, -155.33, -152.92, -150.0, -147.61, -146.14, -146.2, -144.32, -141.64, -138.86, -136.43, -134.43, -132.26, -129.55, -126.89, -124.01, -121.07, -118.68, -116.22, -113.94, -112.95, -111.26, -108.71, -106.15, -103.37, -100.65, -100.76, -102.55, -103.33, -102.92, -100.31, -98.12, -96.34, -93.67, -91.42, -89.23, -87.27, -85.19, -82.67, -80.69, -79.3, -76.91, -74.89, -72.83, -70.21, -67.96, -67.13, -67.56, -68.23, -68.54, -67.98, -67.43, -67.74, -66.7, -65.37, -64.18, -63.0, -61.41, -59.89, -58.59, -57.22, -58.61, None, 68.94, 70.53, 70.28, 68.72, 68.94, None, 145.4, 146.91, 148.29, 148.02, 147.56, 146.66, 145.43, 144.72, 145.4, None, 143.56, 144.56, 145.37, 145.49, 145.89, 146.06, 147.47, 148.85, 149.29, 150.08, 150.73, 151.61, 152.86, 153.16, 153.57, 153.34, 153.09, 152.45, 151.34, 150.71, 150.08, 150.0, 148.3, 146.92, 145.49, 145.03, 143.61, 142.18, 140.64, 139.81, 139.08, 138.45, 137.72, 137.35, 137.89, 137.0, 135.99, 135.24, 134.09, 132.99, 131.33, 128.24, 126.15, 124.22, 123.66, 122.18, 120.58, 119.3, 118.51, 117.3, 115.56, 115.05, 115.71, 115.8, 115.16, 115.04, 114.62, 114.05, 113.34, 113.44, 114.23, 113.72, 113.39, 113.71, 113.74, 114.23, 115.46, 116.71, 117.44, 118.84, 119.25, 120.86, 121.66, 122.29, 123.01, 123.86, 123.82, 124.38, 125.17, 125.69, 126.14, 127.07, 128.36, 129.62, 129.89, 130.18, 131.22, 132.58, 131.82, 133.02, 134.39, 135.3, 136.26, 136.95, 136.31, 136.08, 135.43, 136.3, 137.58, 138.59, 139.26, 140.88, 141.27, 141.7, 141.64, 141.65, 141.69, 142.12, 142.52, 142.87, 143.16, 143.6, None, 16.98, 16.34, 16.2, 15.14, 13.81, 12.15, 11.05, 9.93, 9.63, 9.9, 10.54, 12.14, 12.93, 12.88, 13.6, 14.9, 16.03, 16.96, 16.98, None, 45.0, 45.74, 46.14, 44.95, 45.0, None, 47.37, 47.99, 49.11, 50.08, 49.57, 49.22, 48.88, 48.01, 48.06, 46.51, 46.03, 45.89, 45.56, 44.97, 45.96, 46.64, 46.4, 47.37, None, 29.34, 29.02, 29.94, 30.53, 30.75, 30.12, 29.34, None, 3.31, 4.97, 6.16, 5.78, 4.8, 3.59, 2.66, 3.31, None, 2.69, 1.62, 1.46, 1.08, 0.9, 1.45, 2.15, 2.85, 3.57, 3.6, 3.22, 2.72, 2.69, None, -2.83, -3.98, -4.78, -5.4, -5.2, -4.43, -4.01, -3.1, -2.19, -1.07, -0.27, 0.3, 0.99, 2.18, 1.94, 1.24, 0.02, -0.76, -2.94, -2.83, None, 92.67, 92.3, 92.08, 91.83, 90.5, 90.27, 89.7, 89.03, 88.53, 88.08, 88.93, 88.56, 89.83, 90.87, 92.38, 91.47, 91.71, 92.15, None, 22.66, 23.33, 25.57, 27.24, 28.56, 27.67, 27.14, 26.11, 24.49, 22.95, 22.38, 22.44, 22.99, 22.41, None, -77.53, -78.03, -78.19, -77.54, None, -77.82, -78.98, -77.85, None, -77.0, -77.36, -77.79, -77.0, None, 19.01, 19.12, 19.45, 19.03, 18.56, 17.3, 16.46, 15.75, 16.32, 17.0, 18.55, None, 23.48, 25.54, 26.59, 27.1, 29.23, 29.9, 30.97, 31.38, 31.73, 32.69, 31.5, 31.54, 30.93, 30.56, 29.25, 28.62, 27.45, 25.33, 24.01, 23.51, 23.8, 23.53, None, -89.14, -89.03, -88.49, -88.3, -88.12, -88.2, -88.24, -88.55, -88.93, -89.15, None, -64.78, -64.79, -64.82, -64.8, -64.8, -64.82, -64.83, -64.86, -64.86, -64.87, -64.86, -64.84, -64.83, -64.86, -64.87, -64.88, -64.88, -64.85, -64.84, -64.83, -64.81, -64.77, -64.76, -64.72, -64.7, -64.66, -64.66, -64.65, -64.67, -64.7, -64.71, -64.7, -64.69, -64.68, -64.68, -64.66, -64.69, -64.71, -64.72, -64.73, -64.74, -64.75, -64.77, None, -62.85, -64.38, -66.27, -67.83, -68.76, -68.97, -69.59, -69.39, -69.34, -68.93, -68.67, -68.79, -68.05, -66.65, -65.44, -65.4, -63.2, -62.13, -61.08, -60.46, -60.25, -60.16, -58.39, -57.73, -57.68, -57.85, -58.18, -60.04, -62.27, -62.69, None, -57.63, -55.16, -53.65, -54.13, -54.43, -54.29, -55.03, -55.52, -55.8, -56.88, -57.87, -57.85, -57.68, -57.73, -58.39, -60.16, -60.25, -60.46, -61.08, -62.13, -63.2, -65.4, -65.44, -66.65, -68.05, -68.79, -70.09, -70.48, -72.18, -73.23, -73.57, -73.72, -73.12, -72.96, -71.75, -70.79, -69.44, -69.58, -70.02, -69.25, -69.8, -67.87, -67.26, -66.88, -65.55, -64.61, -64.08, -63.42, -64.41, -64.82, -63.89, -62.8, -60.97, -60.73, -59.98, -59.77, -59.82, -59.72, -59.03, -58.43, -57.66, -56.78, -56.0, -56.07, -55.57, -54.52, -53.78, -53.42, -52.56, -51.66, -51.07, -49.97, -50.7, -48.62, -47.82, -44.91, -44.58, -41.47, -38.5, -36.45, -35.24, -34.73, -35.64, -37.68, -38.67, -38.88, -39.27, -39.76, -40.94, -41.99, -44.65, -46.47, -48.5, -48.47, -48.89, -50.7, -52.26, -53.37, -53.21, -54.57, -55.97, -57.63, None, 114.2, 115.45, 115.35, 114.66, None, 91.7, 92.03, 90.37, 88.84, 89.48, 90.73, 91.7, None, 25.65, 26.16, 27.72, 28.02, 29.43, 27.12, 26.49, 25.77, 25.03, 23.73, 22.82, 22.11, 20.89, 20.76, 19.9, 20.88, 21.66, 23.58, 24.52, 25.26, None, 15.28, 16.29, 16.71, 18.39, 18.81, 20.06, 21.72, 22.86, 23.55, 23.39, 23.81, 25.11, 25.8, 26.47, 27.37, 26.4, 25.28, 24.81, 23.3, 22.7, 21.66, 20.29, 18.93, 18.45, 17.13, 16.01, 15.86, 15.04, 14.48, 14.46, 14.78, None, -63.66, -62.01, -62.87, -64.39, -63.66, None, -61.81, -63.59, -64.17, -61.84, None, -123.51, -125.66, -126.85, -128.06, -128.36, -126.7, -125.42, -123.92, None, -56.13, -56.14, -55.82, -54.47, -53.79, -52.96, -53.07, -54.18, -54.24, -56.0, -56.25, -59.27, -58.8, -58.39, -56.74, -55.41, -56.13, None, -132.71, -132.05, -131.58, -132.55, -133.24, -132.71, None, -79.27, -80.1, -80.32, -79.52, None, -81.9, -83.77, -83.25, -81.9, None, -85.16, -84.46, -82.79, -81.55, -80.1, -82.55, -84.1, -85.87, -86.35, -85.88, None, -75.87, -77.24, -75.9, -75.1, -75.87, None, -95.65, -97.62, -99.8, -98.22, -96.56, -95.65, None, -90.55, -89.22, -88.32, -86.31, -85.52, -82.62, -81.22, -81.26, -83.34, -85.77, -87.03, -88.48, -90.7, -91.93, -94.24, -94.68, -92.76, -90.9, -88.04, -86.07, -83.36, -82.44, -81.4, -79.14, -79.12, -78.23, -76.54, -77.3, -77.34, -78.11, -75.7, -73.84, -71.68, -69.59, -69.29, -67.65, -65.25, -63.8, -61.4, -60.47, -57.98, -56.94, -55.76, -56.41, -58.77, -61.72, -65.36, -67.24, -69.95, -70.26, -66.55, -64.17, -64.8, -63.17, -60.52, -59.8, -63.25, -65.36, -66.16, -66.03, -67.79, -68.23, -69.24, -70.31, -71.08, -71.51, -74.87, -76.38, -76.82, -78.72, -79.01, -78.94, -81.28, -82.69, -83.14, -82.9, -82.14, -82.55, -83.47, -83.89, -84.14, -84.6, -84.78, -85.65, -87.44, -89.27, -90.83, -92.61, -94.33, -94.82, -95.16, -100.65, -107.05, -113.0, -117.03, -122.84, -124.91, -127.44, -127.85, -129.31, -130.54, -130.01, -132.73, -134.27, -135.48, -137.45, -139.04, -141.0, -140.99, -137.55, -135.63, -132.93, -129.79, -128.36, -127.45, -124.42, -123.06, -121.47, -117.6, -115.25, -115.3, -110.8, -108.88, -108.81, -106.95, -105.34, -103.22, -99.9, -98.56, -96.12, -95.49, -94.23, -96.47, -95.21, -92.88, -92.41, None, -114.17, -112.44, -109.92, -108.19, -108.4, -106.52, -104.77, -102.79, -101.09, -102.09, -104.24, -107.12, -111.53, -113.85, -116.11, -116.67, -113.72, -114.35, -117.9, -116.11, -119.4, -117.87, -114.17, None, -104.5, -106.94, -105.26, None, -76.34, -77.31, -79.49, -80.88, -80.35, -76.34, None, -86.56, -84.85, -80.6, -78.77, -75.61, -74.1, -71.2, -67.91, -68.81, -64.86, -61.85, -63.92, -66.72, -68.14, -65.73, -64.67, -66.28, -67.37, -66.17, -71.02, -71.89, -74.83, -77.71, -77.9, -73.96, -73.94, -72.93, -74.84, -76.23, -78.17, -79.49, -84.94, -88.68, -88.47, -90.21, -88.41, -86.56, None, -100.36, -97.38, -98.05, -96.72, -99.32, -102.5, -100.44, -100.36, None, -93.2, -95.41, -96.02, -94.5, -90.51, -93.2, None, -120.46, -123.62, -125.5, -123.94, -121.54, -117.56, -115.51, -119.22, -120.46, None, -93.61, -95.61, -96.29, -93.98, None, -98.5, -97.7, -99.81, -100.86, -102.57, -99.98, -98.5, None, -108.21, -106.93, -105.7, -109.7, -113.74, -111.79, -117.71, -115.4, -110.81, -110.5, -108.55, None, -94.68, -91.61, -90.97, -89.19, -86.38, -82.75, -80.06, -80.46, -83.23, -88.15, -92.42, -92.89, -95.96, -96.75, None, -116.2, -117.11, -119.9, -122.85, -121.16, -117.57, None, -93.84, -96.17, -94.42, -93.84, None, -110.19, -113.53, -111.26, -110.19, None, -109.66, -112.54, -111.5, -109.66, None, -95.83, -98.12, -98.63, -96.75, -95.83, None, -100.06, -101.3, -105.18, -105.42, -103.53, -100.06, None, -87.02, -87.19, -90.8, -93.95, -93.15, -96.08, -96.02, -94.3, -92.41, -89.45, -87.02, None, -68.5, -63.68, -61.89, -66.75, -65.48, -69.47, -73.24, -76.91, -76.22, -76.34, -78.36, -79.62, -77.89, -83.17, -87.6, -89.62, -88.26, -84.98, -87.96, -85.38, -86.51, -84.2, -81.85, -87.6, -90.2, -91.59, -88.93, -85.5, -83.18, -81.1, -76.25, -72.83, -68.5, None, 9.59, 9.48, 10.44, 9.92, 8.97, 8.32, 7.27, 6.5, 6.04, 6.74, 7.47, 8.52, None, -68.63, -67.56, -67.29, -68.64, -69.96, -72.26, -74.66, -72.43, -70.59, -69.35, None, -68.22, -67.11, -67.33, -68.39, -68.3, -69.66, -69.92, -70.07, -69.82, -70.36, -71.12, -71.41, -71.92, -72.15, -71.46, -71.33, -71.66, -71.92, -72.33, -73.42, -72.98, -72.33, -69.5, -69.46, -70.85, -71.43, -73.7, -74.95, -74.98, -75.61, -74.13, -74.69, -73.24, -73.39, -74.33, -73.68, -73.51, -73.17, -71.86, -71.67, -71.49, -70.72, -70.09, -70.37, -69.59, -68.97, -68.76, None, 110.34, 108.66, 109.12, 110.79, 110.57, None, 127.66, 130.58, 132.51, 135.03, 134.11, 133.1, 131.03, 131.14, 130.64, 129.6, 128.21, 126.87, 125.08, 122.87, 121.05, 121.38, 121.64, 119.64, 118.04, 118.06, 118.91, 120.82, 122.36, 121.1, 119.66, 120.23, 121.23, 121.89, 121.5, 121.94, 121.13, 119.59, 117.28, 114.76, 113.81, 111.84, 110.44, 109.63, 108.52, 107.04, 106.73, 105.33, 103.5, 102.17, 101.8, 101.18, 100.42, 99.24, 98.9, 97.6, 98.67, 98.68, 97.91, 96.25, 96.12, 94.57, 92.5, 91.26, 90.02, 88.81, 88.12, 85.82, 84.23, 83.34, 81.53, 79.72, 78.46, 79.21, 78.91, 76.19, 75.16, 74.83, 74.26, 73.68, 73.82, 75.47, 76.9, 78.54, 80.26, 80.87, 81.95, 83.18, 85.72, 86.6, 87.75, 88.85, 90.97, 90.95, 93.48, 95.31, 96.35, 99.52, 101.83, 104.52, 106.13, 109.24, 111.13, 111.67, 111.87, 113.46, 115.99, 117.42, 119.66, 118.87, 117.3, 115.74, 116.19, 117.88, 119.28, 120.74, 120.18, 122.25, 125.07, 126.56, 127.29, None, -2.86, -4.01, -5.83, -7.52, -7.64, -7.57, -8.31, -8.39, -8.44, -8.22, -8.2, -8.08, -8.23, -7.9, -6.85, -6.49, -6.05, -5.4, -4.78, -3.98, -2.83, -2.98, -2.81, None, 13.08, 12.36, 11.28, 9.8, 8.95, 8.49, 8.76, 9.52, 10.5, 11.75, 12.06, 12.75, 13.17, 13.57, 14.47, 14.18, 14.5, 14.96, 15.47, 14.63, 13.95, 14.98, 15.44, 14.78, 14.46, 14.48, 15.04, 15.86, 16.01, 15.15, 13.08, None, 30.83, 31.17, 30.47, 29.88, 29.59, 29.29, 29.12, 29.28, 29.52, 29.62, 30.74, 29.0, 28.45, 28.5, 28.64, 29.62, 28.93, 28.16, 27.16, 25.75, 24.78, 24.26, 23.46, 22.4, 22.21, 21.8, 21.75, 20.51, 20.09, 19.42, 19.02, 18.13, 17.09, 16.57, 13.38, 12.74, 12.18, 12.47, 13.0, 13.6, 14.21, 15.17, 16.01, 16.41, 17.52, 17.66, 17.77, 18.09, 18.45, 18.93, 20.29, 21.66, 22.7, 23.3, 24.81, 25.28, 26.4, 27.37, 28.43, 29.16, 29.95, None, 13.0, 12.32, 11.09, 11.48, 12.5, 13.11, 14.3, 14.32, 14.28, 13.28, 13.08, 15.15, 16.01, 17.13, 18.45, 18.09, 17.77, 17.66, 17.52, 16.41, 16.01, 15.17, 14.21, 13.6, 13.0, None, -75.37, -76.29, -77.42, -77.86, -78.99, -78.66, -77.93, -77.13, -77.31, -77.32, -77.88, -77.43, -77.47, -76.84, -75.67, -75.48, -74.28, -73.41, -72.24, -71.4, -71.33, -72.23, -72.91, -73.3, -72.66, -72.36, -72.44, -71.96, -70.09, -68.99, -67.7, -67.52, -67.82, -67.34, -67.81, -67.18, -67.07, -67.54, -69.82, -69.22, -69.45, -70.02, -69.42, -69.89, -70.69, -70.81, -71.77, -73.07, -74.12, -75.11, None, -82.97, -83.71, -83.63, -84.3, -84.71, -84.91, -85.34, -85.8, -85.66, -85.71, -84.9, -84.36, -83.9, -83.4, -82.55, -82.93, -82.87, -82.91, None, -82.27, -80.62, -79.28, -77.99, -76.52, -75.6, -74.93, -74.3, -75.63, -77.76, -77.49, -78.48, -79.28, -80.52, -82.17, -82.78, -83.91, -84.55, -84.45, -83.78, -82.51, None, 32.73, 32.95, 34.58, 33.97, 33.68, 33.48, 33.38, 32.92, None, 33.97, 32.98, 32.26, 32.92, 33.38, 33.48, 33.68, 33.97, None, 16.96, 16.03, 14.9, 13.6, 12.52, 12.24, 13.34, 14.31, 15.02, 16.24, 16.72, 17.55, 18.39, 18.55, 18.17, 17.91, 17.55, 16.96, None, 9.92, 10.95, 11.96, 13.65, 14.35, 14.44, 14.61, 14.57, 14.06, 12.97, 12.42, 13.03, 13.24, 13.03, 12.62, 11.43, 10.4, 9.59, 8.32, 7.59, 6.66, 6.24, 6.16, 6.59, 7.09, 7.1, 8.12, 8.57, 9.28, None, 43.08, 43.29, 43.15, 42.55, 41.76, 41.66, 42.35, 43.08, None, 12.69, 11.04, 12.37, None, 10.91, 10.37, 9.92, 8.53, 8.09, 8.54, 9.78, 10.55, 10.37, None, -71.71, -70.81, -69.95, -69.22, -68.81, -68.69, -69.62, -70.13, -70.67, -71.4, -71.71, -71.95, -71.62, None, 12.0, 5.68, 3.16, 2.68, 1.82, -4.92, -8.67, -8.67, -6.06, -4.86, -3.65, -2.62, -1.12, -1.73, -2.17, -0.13, 1.47, 4.82, 6.26, 7.74, 8.22, 8.14, 7.61, 8.44, 9.48, 9.86, 9.76, 9.72, 9.91, 10.3, 11.56, None, -80.3, -79.99, -80.97, -80.93, -80.4, -80.09, -78.86, -77.67, -76.58, -75.8, -75.23, -76.64, -78.45, -79.21, -80.03, -80.47, -80.3, None, 34.92, 34.43, 33.92, 33.14, 32.32, 33.35, 34.47, 35.69, 35.53, 36.87, 29.02, 25.0, 24.7, 24.8, 26.5, 28.45, 29.68, 30.98, 31.96, 32.99, 34.27, None, 42.35, 41.6, 40.9, 39.34, 38.51, 37.59, 36.32, 36.85, 37.9, 38.99, 39.81, 41.73, 42.59, 42.78, None, -9.03, -9.39, -6.75, -4.35, -1.9, 0.34, 1.83, 3.04, 0.81, 0.11, 0.11, -0.68, -2.15, -4.37, -5.38, -6.24, -7.45, -7.17, -7.37, -7.5, -7.03, -6.85, -6.67, -7.42, -8.26, -9.03, None, 24.31, 24.06, 23.34, 25.86, 27.98, 27.42, 27.29, 25.6, 24.31, None, 37.91, 39.1, 40.03, 41.16, 42.01, 42.0, 41.74, 42.31, 42.78, 42.93, 43.68, 47.79, 43.66, 42.13, 41.17, 39.85, 38.89, 38.44, 36.86, 35.82, 35.3, 34.25, 33.57, 33.29, 33.97, 34.26, 34.83, 35.86, 36.43, 37.91, None, 28.59, 29.98, 30.22, 30.44, 31.52, 30.21, 26.26, 22.87, 21.32, 21.06, 22.44, 25.4, 23.9, 23.54, 20.65, 22.36, 24.74, 26.18, 29.02, None, 178.37, 178.55, 177.38, 177.67, 178.37, None, 179.36, 178.6, 179.41, 180.0, None, -179.92, -180.0, -179.92, None, -61.2, -59.15, -57.75, -59.4, -60.7, None, 9.56, 8.78, 8.75, 9.56, None, 3.59, 4.8, 5.9, 6.66, 7.59, 7.19, 6.77, 6.02, 6.84, 7.1, 7.01, 7.44, 4.56, 2.99, 0.7, -1.5, -1.38, -2.23, -4.49, -3.3, -1.93, 1.34, 2.51, 3.12, None, 11.09, 9.41, 8.83, 9.29, 9.83, 11.28, 12.36, 13.08, 13.28, 14.28, 14.32, 14.3, 13.11, 12.5, 11.48, 11.09, None, -5.66, -6.95, -7.37, -6.73, None, -3.01, -3.06, -2.22, -2.09, -1.11, 0.18, 1.68, 1.05, 0.55, -2.49, -3.62, -5.25, -4.31, -3.42, -5.27, -4.77, -3.09, -2.95, -3.63, -5.08, -5.05, -5.64, -5.79, -4.21, None, 41.55, 41.45, 40.32, 40.08, 42.39, 43.93, 45.47, 46.4, 46.64, 45.96, 44.97, 42.62, None, 1.06, -1.06, -2.86, -3.24, -2.56, -2.96, -1.2, -0.44, -0.05, 0.37, 0.71, 0.57, 1.06, None, -8.44, -8.93, -9.4, -9.76, -10.23, -10.49, -10.62, -11.12, -12.15, -12.6, -13.25, -14.07, -14.58, -14.84, -14.69, -14.12, -13.74, -13.72, -13.22, -12.28, -11.66, -11.46, -11.04, -10.59, -9.89, -9.33, -8.91, -8.38, -8.62, -8.28, -8.03, -8.31, -7.83, -8.3, -8.28, None, -16.84, -15.62, -15.08, -14.38, -13.84, -14.71, -15.51, -15.93, None, -15.13, -16.09, -16.31, -16.68, -15.82, -13.7, -13.83, -13.9, -14.38, -15.13, None, 9.49, 9.65, 11.29, 9.49, None, 23.7, 25.03, 25.75, 26.16, 24.74, 23.7, None, 26.6, 26.06, 24.93, 24.41, 23.34, 22.63, 23.35, 23.53, 24.04, 23.41, 23.15, 21.67, 21.12, 20.22, 20.61, 21.0, 21.67, 22.6, 22.95, 24.49, 26.11, 26.6, None, -46.76, -39.9, -35.09, -20.85, -26.52, -31.4, -24.84, -22.07, -20.62, -12.77, -16.29, -20.05, -18.9, -19.67, -20.04, -19.83, -20.67, -21.59, -20.76, -23.57, -22.3, -24.79, -22.13, -23.54, -25.54, -26.36, -22.35, -27.75, -31.78, -34.2, -37.04, -39.81, -40.68, -42.82, -42.87, -44.79, -48.26, -49.9, -52.14, -53.66, -53.97, -51.48, -50.87, -52.56, -54.68, -54.36, -51.39, -54.0, -55.83, -55.33, -57.32, -58.59, -63.39, -68.5, -71.4, -66.76, -73.3, -69.37, -65.32, -67.15, -62.23, -60.28, -54.13, -50.39, -46.6, -46.9, None, -90.1, -91.23, -92.23, -92.09, -91.75, -90.44, -90.71, -91.45, -91.0, -89.14, -89.23, -88.6, -88.23, -89.15, -89.15, -89.59, -89.72, -90.1, None, -52.56, -53.42, -53.78, -54.52, -54.18, -54.4, -53.96, -52.88, -51.66, -52.56, None, -59.76, -58.48, -58.08, -57.15, -57.91, -58.04, -57.28, -56.54, -57.34, -58.11, -58.54, -59.65, -59.97, -59.54, -60.11, -60.21, -61.41, -61.16, -60.3, -60.55, None, -87.32, -87.79, -87.86, -88.5, -88.84, -89.35, -89.23, -88.68, -88.12, -87.62, -87.37, -86.44, -86.0, -85.44, -84.98, -84.37, -83.77, -83.15, -83.63, -84.23, -84.65, -84.92, -85.15, -85.51, -85.8, -86.31, -86.76, -86.88, -87.32, None, 18.83, 19.39, 18.55, 17.0, 16.32, 15.75, 16.46, 17.3, 18.56, 17.51, 16.02, 15.38, 14.9, 13.95, 13.68, 14.41, 14.94, 15.32, 15.77, 16.88, 18.46, None, -73.19, -71.71, -71.7, -71.69, -72.37, -73.45, -74.46, -73.45, -72.33, -72.78, -73.19, None, 16.2, 16.34, 16.98, 17.86, 18.78, 19.66, 20.24, 20.8, 22.09, 22.71, 21.63, 20.22, 18.83, 17.63, 16.56, 16.2, None, 120.72, 118.97, 120.43, 120.72, None, 124.44, 123.46, 123.98, 125.07, 124.44, None, 117.9, 118.88, 117.97, 116.74, 117.63, None, 122.9, 121.25, 119.92, 121.34, 122.9, None, 108.62, 110.76, 112.98, 115.71, 113.46, 111.52, 109.43, 108.28, 106.28, 106.05, 108.07, 108.62, None, 134.72, 134.11, 134.5, 134.72, None, 127.25, 126.18, 127.0, None, 130.47, 129.99, 128.59, 128.14, 130.47, None, 134.14, 135.46, 137.44, 139.18, 141.0, 141.03, 139.13, 137.61, 138.67, 137.93, 135.16, 133.37, 132.76, 131.99, 133.78, 132.23, 130.94, 131.87, 133.99, None, 125.24, 123.69, 121.06, 120.04, 121.48, 123.26, 122.39, 122.45, 123.17, 122.63, 122.72, 121.49, 120.9, 120.31, 120.43, 119.37, 119.5, 118.77, 119.32, 120.04, 121.67, 124.08, 125.24, None, 128.69, 128.12, 128.38, 127.7, 127.6, 128.0, 128.69, None, 117.88, 117.81, 117.52, 116.53, 116.0, 114.47, 113.26, 111.7, 110.22, 109.57, 108.95, 109.66, 110.51, 111.8, 112.86, 114.62, 115.52, 117.02, 117.31, 117.88, None, 105.82, 103.87, 102.16, 100.9, 99.26, 98.6, 97.18, 95.38, 95.94, 98.37, 99.69, 101.66, 103.08, 103.44, 104.37, 104.89, 106.11, 105.82, None, 77.84, 78.81, 79.18, 78.74, 81.11, 80.09, 82.0, 84.68, 86.02, 88.06, 88.04, 88.73, 88.84, 90.37, 92.03, 91.7, 93.41, 95.4, 96.59, 97.33, 97.05, 96.42, 95.16, 94.55, 93.33, 93.06, 92.67, 91.87, 91.16, 91.92, 91.8, 89.92, 89.36, 88.21, 88.31, 88.7, 88.88, 88.89, 86.98, 86.5, 83.94, 82.19, 81.69, 80.32, 80.23, 79.86, 79.34, 79.19, 77.94, 76.59, 75.75, 74.86, 74.44, 73.12, 72.82, 71.18, 69.16, 69.35, 68.84, 70.84, 70.17, 70.62, 72.82, 74.42, 75.26, 74.1, 74.24, 76.87, None, -6.2, -6.79, -9.98, -9.69, -7.57, -7.57, -6.2, None, 53.92, 55.51, 56.62, 58.44, 60.38, 61.21, 60.53, 60.54, 60.94, 61.78, 61.37, 62.73, 63.23, 61.87, 59.62, 57.4, 56.49, 54.72, 52.48, 50.85, 49.58, 48.57, 48.0, 47.85, 46.11, 45.65, 46.08, 44.77, 44.42, 44.79, 45.46, 46.51, 48.06, 48.01, 48.88, 50.15, 52.26, 53.92, None, 45.42, 46.15, 45.42, 47.33, 47.69, 48.01, 47.97, 46.57, 41.89, 39.2, 41.01, 41.29, 42.35, 43.94, 44.77, None, -14.51, -13.61, -17.79, -19.97, -21.78, -22.18, -24.33, -22.13, -19.06, -16.17, None, 35.72, 35.18, 35.23, 34.93, 35.42, 34.27, 34.49, 34.96, 35.13, 35.55, 35.84, 35.72, None, 15.52, 15.31, 14.34, 12.43, 13.74, 15.52, None, 9.21, 9.67, 8.81, 8.39, 8.71, None, 12.38, 13.7, 13.14, 12.38, 12.59, 14.03, 15.93, 15.89, 17.52, 18.48, 17.74, 16.45, 17.05, 16.1, 15.69, 16.11, 15.41, 14.7, 13.63, 12.11, 10.51, 9.7, 8.43, 7.44, 7.01, 7.1, 6.84, 7.76, 8.49, 9.18, 10.36, 11.05, 12.15, None, -77.57, -76.37, -76.9, -77.77, -78.22, -77.57, None, 35.55, 36.83, 39.2, 37.0, 37.67, 36.74, 36.07, 34.92, 35.4, 35.55, None, 134.64, 134.2, 133.28, 132.36, 132.92, 133.9, None, 140.98, 140.77, 138.98, 135.79, 135.08, 132.16, 132.0, 130.69, 130.45, 129.41, 130.88, 132.62, 135.68, 137.39, 139.43, 139.88, 141.37, 141.88, 140.98, None, 143.91, 145.32, 144.06, 141.61, 139.96, 140.31, 141.67, 143.14, None, 70.96, 69.07, 68.26, 66.71, 66.02, 64.9, 62.01, 60.24, 58.5, 55.97, 54.76, 52.94, 52.45, 52.5, 50.89, 50.31, 51.32, 53.04, 53.04, 51.19, 49.1, 48.69, 47.32, 47.04, 47.55, 48.7, 52.33, 55.72, 58.36, 59.93, 61.59, 60.93, 61.7, 61.44, 65.67, 69.07, 71.18, 73.51, 74.38, 76.53, 80.04, 81.95, 83.94, 85.12, 86.83, 86.6, 85.72, 83.18, 81.95, 80.87, 80.26, 79.14, 76.0, 74.21, 73.49, 71.19, None, 40.99, 40.88, 40.26, 39.8, 39.2, 37.7, 33.9, 34.18, 35.04, 34.48, 34.62, 35.82, 36.16, 38.12, 38.67, 39.56, 40.77, 41.86, 40.99, None, 70.96, 71.84, 73.65, 75.64, 77.66, 79.64, 80.12, 78.19, 76.53, 74.78, 73.96, 71.78, 69.46, 70.65, 71.77, 71.87, 70.42, 70.96, None, 103.5, 102.58, 102.99, 105.22, 106.5, 107.61, 105.81, 105.2, 103.5, None, 128.35, 129.46, 129.09, 127.39, 126.37, 126.12, 126.17, 126.68, 127.78, 128.35, None, 20.76, 20.59, 20.28, 20.26, 20.64, 20.96, 21.27, 21.63, 21.66, 21.58, 20.76, None, 47.97, 48.09, 47.71, 46.57, 47.97, None, 105.22, 105.59, 104.72, 103.2, 102.41, 101.06, 101.28, 100.55, 100.33, 101.27, 101.65, 102.75, 104.44, 104.18, 105.09, 106.56, 107.56, 106.5, 105.22, None, 35.82, 35.46, 35.48, 36.0, 36.61, 35.82, None, -7.71, -9.0, -10.77, -11.2, -10.7, -10.02, -9.34, -9.21, -8.72, -8.49, -8.6, -7.99, -7.54, -7.71, None, 14.85, 13.58, 11.56, 10.3, 9.91, 9.72, 9.76, 9.86, 9.48, 10.06, 10.64, 11.43, 12.66, 13.92, 15.71, 18.02, 19.57, 19.82, 20.85, 22.9, 23.61, 24.92, 24.8, 24.7, 25.0, 25.0, 23.84, 15.86, None, 81.79, 81.22, 79.87, 80.15, 81.3, None, 28.98, 29.02, 28.29, 27.75, 27.53, 28.54, None, 22.73, 22.76, 21.27, 22.2, 24.86, 25.53, 26.59, 25.54, 23.48, 22.73, None, 6.04, 6.19, 5.67, 6.04, None, 21.06, 21.58, 23.32, 24.31, 25.6, 27.29, 27.86, 27.1, 25.53, 24.86, 22.2, None, -5.19, -3.64, -2.17, -1.73, -1.12, -2.62, -3.65, -4.86, -6.06, -8.67, -8.82, -8.79, -9.74, -10.55, -11.72, -12.5, -14.22, -14.75, -17.02, -16.59, -16.33, -15.43, -14.82, -14.44, -13.14, -12.62, -10.9, -9.56, -9.43, -8.66, -6.91, -5.93, None, 26.62, 27.52, 28.67, 29.05, 29.56, 29.84, 29.76, 29.07, 28.93, 28.49, 28.05, 28.13, 27.23, 26.62, None, 49.54, 50.06, 50.48, 50.2, 49.67, 49.77, 49.44, 48.55, 47.55, 46.28, 44.83, 43.76, 43.35, 43.43, 43.9, 44.46, 44.04, 44.31, 44.94, 45.87, 46.88, 48.01, 48.29, 48.86, 49.54, None, -97.14, -97.7, -97.87, -97.39, -96.53, -95.9, -94.43, -92.79, -91.41, -90.53, -90.28, -88.54, -87.05, -86.85, -87.62, -87.59, -88.09, -88.49, -89.03, -89.14, -91.0, -91.45, -90.71, -90.44, -91.75, -92.09, -92.23, -93.88, -95.25, -96.56, -98.01, -99.7, -101.67, -102.48, -103.92, -105.49, -105.4, -105.27, -105.6, -106.03, -107.92, -109.26, -109.29, -110.39, -111.18, -112.23, -112.81, -113.15, -114.21, -114.94, -114.67, -113.59, -113.27, -112.96, -112.46, -111.62, -110.99, -110.66, -109.77, -109.43, -110.03, -110.95, -112.18, -112.3, -113.46, -113.85, -115.06, -114.57, -114.16, -115.52, -116.26, -117.13, -114.72, -113.3, -109.03, -108.24, -106.14, -105.04, -104.46, -103.11, -101.66, -100.46, -99.52, -99.02, -97.53, None, 20.59, 20.76, 21.58, 22.38, 22.95, 22.6, 21.67, 20.61, 20.59, None, -12.17, -11.67, -10.65, -9.7, -5.54, -5.49, -6.45, -1.55, 2.06, 3.15, 4.27, 3.72, 2.75, 1.02, -0.27, -1.07, -2.19, -3.1, -4.01, -4.43, -5.2, -5.4, -6.05, -6.49, -6.85, -7.9, -8.34, -8.41, -8.58, -8.79, -9.13, -9.57, -10.17, -10.87, -11.3, -11.51, -11.55, -12.12, None, 14.57, 14.44, 14.35, 14.54, None, 14.31, 14.19, 14.26, 14.32, None, 99.54, 98.25, 97.38, 98.49, 98.54, 98.43, 99.21, 99.59, 98.55, 98.76, 98.51, 97.78, 97.16, 95.37, 94.19, 94.32, 93.66, 92.37, 92.65, 93.17, 93.29, 94.11, 94.6, 95.12, 97.13, 97.4, 97.91, 98.68, 98.67, 97.6, 98.9, 99.24, 100.42, 101.18, 100.12, None, 19.8, 19.3, 19.16, 18.45, 18.71, 19.22, 19.63, 20.34, 20.07, None, 87.75, 90.71, 93.1, 94.82, 97.26, 97.83, 99.98, 102.07, 103.68, 105.89, 107.87, 109.4, 111.58, 114.36, 115.49, 116.19, 115.74, 117.3, 118.87, 119.66, 117.42, 115.99, 113.46, 111.87, 111.67, 111.13, 109.24, 106.13, 104.52, 101.83, 99.52, 96.35, 95.31, 93.48, 90.95, 90.97, 88.85, 87.75, None, 34.56, 36.51, 37.47, 38.43, 40.32, 40.44, 40.6, 40.48, 39.45, 37.41, 35.9, 34.79, 35.18, 35.39, 35.53, 35.61, 35.04, 33.01, 32.66, 32.83, 31.99, 31.75, 31.67, 32.24, 32.66, 32.61, 32.85, 32.33, 31.64, 30.34, 30.18, 33.79, 34.46, 34.31, 35.03, 35.77, 35.27, 34.56, 34.56, None, -12.17, -13.44, -14.58, -15.62, -16.46, -16.27, -16.26, -16.28, -17.06, -12.93, -12.87, -11.97, -8.68, -6.45, -5.49, -5.54, -9.7, -10.65, -11.67, -12.17, None, 34.56, 34.56, 35.27, 35.77, 35.03, 34.31, 34.46, 33.79, 32.69, 33.31, 33.32, 33.23, 33.74, 34.28, None, 101.08, 101.81, 102.37, 103.38, 103.33, 103.5, 104.25, 103.52, 101.39, 100.7, 100.2, 100.09, 101.08, None, 118.62, 117.02, 115.52, 114.62, 112.86, 111.8, 110.51, 109.66, 111.17, 111.8, 113.71, 114.66, 115.35, 115.45, 116.73, 117.64, 118.35, 119.11, 118.62, None, 16.34, 15.21, 14.74, 14.39, 13.87, 12.83, 11.79, 12.22, 13.46, 14.21, 18.96, 23.22, 24.68, 25.08, 24.22, 23.2, 20.91, 19.9, 19.89, 18.46, 17.39, 16.82, None, 165.78, 167.12, 166.19, 164.83, 164.03, 165.02, 165.78, None, 2.15, 1.02, 0.43, 0.37, 1.39, 3.64, 4.27, 5.68, 12.0, 14.14, 15.1, 15.49, 15.69, 15.25, 13.54, 13.95, 14.5, 14.18, 13.32, 12.3, 10.99, 10.11, 9.01, 7.33, 6.45, 4.37, 3.97, 3.61, 2.49, None, 8.5, 7.08, 5.9, 5.03, 3.57, 2.75, 2.91, 3.71, 3.8, 3.61, 3.97, 4.37, 6.45, 7.33, 9.01, 10.11, 10.99, 12.3, 13.32, 14.18, 14.47, 13.57, 13.17, 12.75, 12.06, 11.75, 10.5, 9.52, 8.76, None, -85.71, -86.53, -87.17, -87.56, -87.32, -86.88, -86.76, -86.31, -85.8, -85.51, -85.15, -84.92, -84.65, -84.23, -83.63, -83.15, -83.28, -83.41, -83.55, -83.47, -83.72, -83.86, -83.66, -84.19, -84.67, -85.56, None, 6.07, 7.09, 6.59, 6.16, 4.97, 3.31, 4.71, None, 28.17, 30.01, 29.4, 29.02, 26.18, 24.74, 22.36, 20.65, 19.88, 17.73, 16.11, 13.56, 13.57, 11.93, 12.63, 11.47, 10.36, 7.05, 5.31, 5.91, 10.53, 14.76, 19.18, 23.02, 26.37, None, 24.72, 20.73, 20.81, 23.28, None, 18.25, 19.03, 17.59, 15.91, 14.67, 11.22, 13.17, 15.14, 16.99, None, 25.45, 25.92, 20.08, 18.46, 20.46, 22.92, None, 88.12, 88.17, 87.23, 85.25, 83.3, 81.06, 80.48, 81.53, 83.34, 84.23, 85.82, 88.12, None, 173.02, 173.96, 174.25, 173.22, 173.08, 171.45, 170.62, 169.33, 167.76, 166.51, 168.3, 169.67, 171.13, 171.95, 172.8, None, 174.61, 175.36, 175.96, 177.44, 178.52, 177.97, 176.94, 176.89, 176.01, 175.07, 175.23, 173.82, 174.57, 174.7, 174.32, 173.05, 173.01, 174.33, None, 58.86, 58.03, 57.67, 57.69, 56.61, 56.28, 55.27, 54.79, 53.57, 52.78, 55.0, 55.21, 55.53, 55.98, 55.89, 56.85, 58.14, 59.18, 59.81, 59.44, 58.86, None, 56.39, 56.07, 56.49, None, 75.16, 76.19, 76.87, 74.24, 74.1, 75.26, 74.42, 72.82, 70.62, 70.17, 70.84, 68.84, 67.44, 66.37, 62.91, 61.87, 63.23, 62.73, 61.37, 62.55, 64.15, 65.05, 66.38, 67.68, 68.56, 69.32, 69.69, 69.93, 71.16, 71.61, 71.26, 72.92, 74.58, None, -77.88, -78.43, -78.44, -79.12, -79.76, -80.38, -80.0, -80.42, -81.06, -81.52, -82.13, -82.82, -82.97, -82.83, -82.72, -82.93, -82.19, -81.81, -81.44, -80.52, -79.57, -79.06, -78.06, -77.35, -77.24, -77.75, None, -69.59, -70.37, -71.46, -75.24, -76.42, -77.11, -79.04, -79.76, -81.25, -81.41, -80.3, -80.47, -80.03, -79.21, -78.45, -76.64, -75.23, -75.11, -74.12, -73.07, -71.77, -70.81, -70.69, -69.89, -70.93, -72.89, -73.22, -73.72, -73.99, -73.02, -72.56, -71.3, -70.55, -69.53, -68.88, -68.95, -69.16, -68.96, None, 126.38, 126.54, 125.83, 125.68, 124.22, 124.24, 123.3, 122.09, 122.31, 123.49, 124.6, 125.47, 126.22, 126.38, None, 123.98, 123.31, 122.38, 122.84, 123.5, 124.08, None, 118.5, 117.66, 118.99, 119.69, 118.5, None, 121.88, 123.12, 122.64, 121.97, 121.88, None, 125.5, 125.01, 125.28, 124.76, 124.3, 124.88, 125.23, None, 121.53, 120.83, 121.18, None, 121.32, 122.25, 122.17, 122.25, 121.51, 122.26, 123.95, 124.18, 123.3, 122.67, 121.13, 120.68, 120.69, 120.07, 119.88, 120.39, 121.32, None, 155.88, 155.17, 154.51, 154.76, 155.55, 155.88, None, 151.98, 151.3, 150.24, 148.89, 148.4, 149.85, 150.14, 150.81, 151.65, 152.14, 152.32, None, 147.19, 148.73, 149.27, 149.74, 150.69, 149.78, 147.91, 146.57, 144.74, 143.29, 142.63, 141.03, 141.0, 144.58, 145.83, 147.65, 146.97, None, 153.14, 152.64, 151.95, 150.66, 151.48, 152.24, 153.02, None, 15.02, 14.69, 14.07, 14.12, 16.36, 18.62, 19.66, 22.73, 23.48, 23.8, 23.2, 23.53, 23.92, 22.52, 22.56, 20.89, 19.83, 18.91, 18.39, 17.55, 16.72, 16.24, 15.02, None, -66.28, -65.59, -66.6, -67.24, -66.28, None, 130.64, 130.4, 129.67, 129.19, 128.63, 127.53, 127.39, 128.35, 127.78, 126.68, 126.17, 125.57, 125.24, 124.71, 125.22, 125.39, 124.74, 125.08, 126.87, 128.21, 129.6, 130.64, None, -9.03, -8.26, -7.42, -6.67, -6.85, -7.03, -7.5, -7.37, -7.17, -7.45, -8.38, -8.75, -9.29, -9.45, -8.98, -8.79, -9.03, None, -62.69, -62.27, -60.04, -58.18, -57.87, -56.88, -55.8, -55.52, -55.03, -54.29, -54.43, -54.79, -56.49, -58.62, -57.78, -60.03, -62.69, None, 50.81, 51.01, 51.59, 51.39, 50.81, None, 22.71, 23.76, 24.87, 25.95, 26.62, 27.23, 28.13, 28.05, 28.68, 29.6, 29.14, 28.56, 27.24, 25.57, 23.33, 22.66, 22.71, 22.15, 21.48, 20.76, 21.02, 22.1, None, 143.65, 143.17, 143.53, 142.75, 141.91, 141.9, 142.18, 141.68, 142.21, 142.91, 143.24, None, 22.73, 19.66, 21.27, 22.76, 22.73, None, -175.01, -174.57, -169.9, -172.53, -172.96, -174.65, -176.21, -178.36, -178.69, -179.43, -180.0, -174.93, None, 180.0, 178.73, 180.0, None, -178.69, -180.0, -179.02, -177.66, None, 143.6, 140.04, 140.81, 143.48, None, 150.73, 147.98, 146.36, 150.73, None, 145.09, 140.61, 136.97, 138.83, 145.09, None, 57.54, 53.68, 51.6, 52.48, 54.43, 55.9, 57.87, 64.5, 68.16, 68.18, 61.58, 56.99, 55.62, None, 106.97, 108.15, 113.33, 113.89, 110.15, 110.64, 113.02, 113.97, 118.78, 123.2, 125.38, 128.59, 128.46, 131.29, 133.86, 137.5, 139.87, 140.47, 150.35, 157.01, 159.83, 160.94, 164.05, 167.84, 170.82, 170.45, 175.72, 180.0, 179.99, 177.41, 178.91, 179.49, 177.36, 173.68, 170.7, 168.9, 165.84, 163.54, 162.02, 163.19, 162.13, 162.12, 160.02, 158.23, 156.42, 155.43, 156.76, 158.36, 161.87, 164.47, 162.66, 159.3, 154.22, 152.81, 151.34, 148.54, 142.2, 135.13, 137.19, 138.8, 141.35, 140.6, 140.06, 138.22, 135.52, 133.54, 132.28, 130.78, 130.63, 131.29, 131.88, 133.77, 134.5, 133.37, 130.99, 129.4, 127.29, 126.56, 125.07, 122.25, 120.18, 120.74, 119.28, 117.88, 115.49, 114.36, 111.58, 109.4, 107.87, 105.89, 103.68, 102.07, 99.98, 97.83, 97.26, 94.82, 93.1, 90.71, 87.75, 86.83, 85.12, 83.94, 81.95, 80.04, 76.53, 74.38, 73.51, 71.18, 69.07, 65.67, 61.44, 61.7, 60.93, 61.59, 59.93, 58.36, 55.72, 52.33, 48.7, 47.55, 47.04, 47.32, 48.69, 49.1, 47.68, 47.59, 48.58, 47.82, 46.69, 45.78, 44.54, 43.76, 40.92, 39.96, 37.54, 37.4, 37.67, 39.12, 38.26, 39.74, 39.67, 40.07, 38.01, 36.63, 35.38, 34.22, 34.39, 32.72, 32.16, 31.54, 31.5, 32.69, 31.73, 31.38, 30.97, 29.9, 29.23, 27.86, 27.29, 27.42, 27.98, 28.07, 31.14, 30.04, 29.54, 29.05, 28.45, 29.4, 32.13, 36.51, 41.06, 40.02, 33.92, 34.81, 34.94, 37.01, 36.54, 39.59, 39.76, 43.02, 44.53, 44.19, 46.25, 45.56, 46.35, 48.14, 53.72, 53.49, 55.44, 58.8, 61.08, 60.55, 64.89, 69.18, 68.14, 67.26, 66.69, 69.2, 72.59, 71.85, 72.79, 73.67, 71.28, 72.82, 74.19, 74.47, 73.84, 74.4, 74.89, 75.16, 75.29, 75.9, 79.65, 80.61, 82.25, 86.82, 87.17, 90.26, 93.23, 96.68, 100.76, 101.99, 106.07, 106.97, None, 105.08, 101.26, 102.84, 105.08, None, 51.14, 48.89, 47.59, 47.07, 46.8, 48.52, 50.04, 51.14, None, 99.94, 94.97, 92.55, 93.78, 97.88, 99.94, None, 30.42, 30.76, 29.94, 29.02, 29.25, 29.58, 30.42, None, -8.79, -8.67, -8.68, -11.97, -12.87, -12.93, -17.06, -17.0, -14.63, -13.89, -12.03, -11.39, -10.19, -9.41, None, 42.78, 42.35, 41.75, 40.94, 39.8, 39.02, 38.49, 37.48, 37.21, 36.64, 35.64, 34.63, 34.83, 36.07, 36.74, 37.67, 37.0, 39.2, 41.89, 46.57, 47.71, 48.81, 49.47, 50.21, 50.24, 50.66, 51.11, 51.58, 52.0, 55.21, 55.0, 49.12, 47.47, 46.75, 45.4, 44.06, 43.38, 43.22, None, 33.96, 33.84, 33.21, 33.21, 32.67, 32.31, 31.85, 30.84, 29.62, 29.0, 27.97, 27.11, 26.48, 25.79, 24.79, 24.19, 23.81, 23.39, 23.55, 22.86, 22.51, 22.29, 22.04, 22.18, 22.3, 23.02, 23.84, 25.0, 29.02, 36.87, 36.97, 37.48, 38.41, 37.17, 36.75, 36.43, 35.86, 34.83, 34.26, 33.96, None, 33.96, 33.83, 32.95, 34.08, 34.71, 34.62, 33.39, 31.88, 30.83, 29.72, 28.7, 27.98, 27.21, 26.21, 25.12, 24.57, 24.19, 24.79, 25.79, 26.48, 27.11, 27.97, 29.0, 29.62, 30.84, 31.85, 32.31, 32.67, 33.21, 33.21, 33.84, 33.96, None, -16.71, -17.63, -16.7, -16.12, -15.14, -14.1, -12.83, -12.12, -11.55, -11.51, -12.2, -12.5, -13.7, -15.82, -16.68, -15.93, -15.51, -14.71, -13.84, -14.38, -15.08, -15.62, None, 162.12, 161.7, 161.92, None, 160.85, 159.85, 159.7, 160.69, None, 161.68, 160.79, 160.92, 161.68, None, 159.88, 159.13, 158.21, 158.82, 159.88, None, 157.54, 156.9, 156.54, 157.54, None, -11.44, -12.43, -13.12, -12.71, -12.43, -11.92, -10.84, -10.65, -10.51, -10.7, -11.2, None, -87.79, -88.48, -89.26, -90.1, -89.72, -89.59, -89.06, -88.54, -88.07, -87.72, None, 48.94, 47.79, 43.68, 42.93, 42.78, 43.47, 44.12, 45.56, 47.53, 48.38, 48.94, 48.94, None, 49.73, 50.73, 51.13, 51.05, 50.55, 49.45, 47.74, 45.56, 43.14, 41.81, 40.99, 41.86, 42.77, 44.96, 48.49, 48.94, 48.94, 49.27, None, 20.87, 21.56, 22.46, 22.47, 22.41, 22.99, 22.44, 22.38, 21.58, 21.66, 21.63, 21.27, 20.96, 20.64, 20.26, 19.96, 19.48, 19.45, 19.12, 19.01, 19.07, 19.6, 20.76, None, -57.15, -55.84, -53.96, -54.4, -54.18, -54.52, -55.57, -56.07, -56.0, -57.15, -57.6, -57.86, -57.31, None, 18.85, 19.32, 20.42, 21.61, 22.28, 21.87, 20.47, 19.77, 19.17, 18.7, 17.49, 16.88, 17.1, 17.89, 18.1, 18.4, 18.85, None, 13.81, 15.14, 16.2, 16.56, 15.67, 15.33, 14.6, 13.72, 13.7, None, 22.18, 21.37, 17.85, 17.83, 17.87, 16.45, 14.67, 12.94, 11.79, 11.47, 12.63, 11.93, 13.57, 13.56, 16.11, 17.73, 19.88, 20.65, 23.54, 23.9, None, 17.06, 16.43, 17.06, None, 19.36, 18.83, 18.95, 18.71, 18.32, 18.19, 18.15, 18.66, 19.11, 19.36, None, 20.85, 20.97, 20.7, 20.8, None, 32.07, 31.28, 30.68, 31.04, 31.84, 32.07, None, 38.79, 35.72, 35.84, 36.07, 36.45, 35.91, 36.42, 36.74, 38.17, 39.52, 41.21, 41.84, 41.38, 38.79, None, 14.5, 13.95, 13.54, 15.25, 15.69, 15.49, 15.1, 15.86, 23.84, 23.02, 22.3, 22.18, 22.04, 22.29, 22.51, 22.86, 21.72, 20.06, 18.81, 18.39, 16.71, 16.29, 15.28, 15.12, 14.54, 14.17, 14.91, 14.92, 14.89, None, 1.87, 0.84, 0.49, 0.46, 0.37, 0.02, 0.77, 1.43, 1.66, 1.87, None, 102.58, 100.83, 100.1, 99.48, 99.22, 100.28, 101.02, 102.14, 101.15, 100.26, 99.69, 98.99, 98.34, 98.26, 99.04, 99.2, 99.1, 98.19, 98.9, 97.86, 97.8, 98.96, 100.12, 100.61, 101.04, 102.11, 103.0, 103.96, 104.78, 105.54, 104.28, 102.35, None, 71.01, 69.56, 70.55, 73.68, 74.26, 74.83, 73.95, 72.64, 71.84, 71.54, 71.35, 70.38, 70.12, 69.2, 68.14, 68.39, 67.44, 68.54, 69.33, 70.46, 71.01, None, 61.21, 60.38, 58.44, 56.62, 55.51, 53.92, 53.88, 53.36, 52.92, 54.74, 53.72, 52.81, 52.94, 54.76, 55.97, 56.93, 58.63, 60.08, 61.55, 62.37, 64.17, 66.55, 66.22, 65.59, 64.55, 63.19, 62.23, None, 124.97, 125.95, 126.96, 126.97, 125.09, 124.97, None, -61.68, -60.9, -61.77, -61.66, None, 9.48, 8.44, 7.61, 8.14, 8.22, 9.51, 10.18, 11.1, 10.59, 10.81, 10.34, 11.11, 11.43, 10.64, 10.06, 9.48, None, 36.91, 39.51, 41.55, 43.58, 43.66, 44.79, 44.42, 44.77, 43.94, 42.35, 40.67, 38.7, 37.07, 36.69, 36.15, 36.16, 34.71, 32.51, 30.62, 29.7, 27.64, 26.32, 26.17, 28.82, 31.15, 33.51, 36.91, None, 27.19, 26.04, 26.29, 26.12, 28.0, 28.99, 27.62, None, 121.78, 120.75, 120.11, 121.5, 121.78, None, 33.9, 37.7, 39.2, 38.8, 39.47, 39.25, 39.54, 40.32, 38.43, 37.47, 36.51, 34.56, 33.94, 32.76, 31.56, 30.74, 29.62, 29.52, 29.75, 30.51, 30.74, 30.47, 30.82, 30.77, 33.9, None, 31.87, 30.42, 29.58, 29.82, 30.09, 30.85, 30.77, 31.25, 32.69, 34.01, 34.6, 34.67, 33.89, 31.87, None, 31.79, 32.41, 33.75, 34.14, 35.02, 35.36, 37.39, 38.59, 40.08, 39.9, 38.77, 38.22, 36.76, 34.96, 35.51, 36.33, 33.88, 33.55, 32.63, 33.3, 31.68, 30.38, 29.15, 28.23, 28.66, 28.86, 29.17, 30.02, 29.91, 29.42, 29.12, 28.26, 26.86, 26.2, 25.21, 24.4, 23.14, 22.64, 22.28, 22.78, 23.43, 24.03, 24.01, 25.33, 27.45, 28.62, 29.25, 30.56, 30.93, None, -57.63, -55.97, -54.57, -53.21, -53.37, -54.94, -56.22, -57.82, -58.35, -58.14, -57.63, None, -155.54, -155.94, -156.07, -155.85, -155.86, -155.4, -155.06, -154.83, -155.54, None, -156.08, -156.59, -156.71, -156.26, -156.08, None, -156.76, -157.33, -156.76, None, -157.65, -157.78, -158.25, -158.03, -157.65, None, -159.35, -159.8, -159.6, -159.35, None, -94.82, -94.33, -92.61, -90.83, -89.27, -87.44, -85.65, -84.78, -84.6, -84.14, -83.89, -83.47, -82.55, -82.14, -82.9, -83.14, -82.69, -81.28, -78.94, -79.01, -78.72, -76.82, -76.38, -74.87, -71.51, -71.08, -70.31, -69.24, -68.23, -67.79, -66.96, -69.06, -70.65, -70.83, -70.08, -69.88, -70.64, -71.86, -72.88, -72.24, -73.34, -73.95, -73.96, -74.91, -75.2, -75.32, -75.06, -75.94, -75.72, -76.35, -76.33, -76.3, -75.97, -75.73, -77.4, -78.55, -79.2, -80.86, -81.49, -80.98, -80.53, -80.09, -80.38, -81.17, -81.71, -82.71, -82.65, -83.71, -85.11, -85.77, -87.53, -89.18, -89.41, -89.22, -89.78, -90.88, -92.5, -93.85, -95.6, -97.14, -97.38, -97.14, -98.24, -99.3, -100.11, -100.96, -102.48, -103.94, -104.71, -105.63, -106.51, -108.24, -111.02, -114.81, -115.99, -117.3, -118.41, -119.08, -120.37, -120.74, -122.55, -122.95, -123.87, -124.18, -124.53, -124.02, -124.08, -124.69, -123.12, -122.34, -122.84, -117.03, -113.0, -107.05, -100.65, -95.16, -94.82, None, -153.01, -154.52, -153.76, -152.56, -153.01, None, -165.58, -166.85, -166.47, -165.58, None, -171.73, -170.49, -168.69, -169.53, -170.67, -171.79, None, -155.07, -153.9, -152.27, -149.72, -145.69, -143.59, -140.99, -141.0, -139.04, -137.45, -135.48, -134.27, -132.73, -130.01, -130.54, -131.97, -133.54, -135.04, -137.8, -140.83, -143.96, -147.11, -148.02, -149.73, -151.72, -151.41, -150.62, -152.58, -153.29, -155.31, -156.56, -158.43, -160.29, -162.24, -164.79, -163.85, -161.8, -160.07, -158.46, -157.55, -158.19, -159.06, -159.98, -161.36, -162.05, -162.52, -164.66, -165.35, -165.73, -164.56, -163.07, -161.53, -160.96, -160.78, -162.45, -163.55, -166.43, -168.11, -164.47, -163.79, -162.49, -164.43, -166.76, -164.43, -162.93, -160.93, -158.12, -155.07, None, 66.52, 65.22, 63.52, 61.88, 60.47, 59.98, 57.79, 57.1, 55.93, 58.69, 61.06, 63.19, 66.1, 66.51, 67.99, 68.63, 70.39, 71.26, 71.16, 73.06, 71.01, 70.46, 69.33, 68.54, 67.44, 68.39, 67.08, None, -71.33, -71.95, -71.63, -71.7, -71.04, -71.4, -70.29, -69.58, -68.23, -67.3, -65.66, -64.33, -63.08, -62.73, -61.59, -60.67, -59.76, -60.64, -60.54, -61.14, -60.73, -60.97, -62.8, -63.89, -64.82, -64.41, -63.42, -64.08, -64.61, -65.55, -66.88, -67.45, -67.3, -67.62, -67.74, -67.34, -68.27, -69.39, -70.67, -72.2, -72.48, -72.44, -72.79, -73.03, -72.61, -71.97, None, 108.05, 105.88, 106.43, 108.27, 109.34, 108.37, 106.41, 104.8, 104.33, 106.25, 107.49, 107.38, 107.31, 105.93, 103.9, 104.82, 103.2, 102.17, 103.5, 105.33, 106.73, 107.04, None, 167.84, 167.18, 167.84, None, 167.11, 167.0, 166.65, 167.11, None, 35.55, 35.4, 34.97, 34.97, 35.55, None, 53.11, 52.19, 51.17, 48.68, 47.94, 46.72, 45.63, 45.14, 44.49, 43.48, 43.25, 42.89, 42.81, 42.82, 43.22, 43.38, 44.06, 45.4, 46.75, 47.47, 49.12, 52.78, None, 31.52, 30.9, 30.06, 28.22, 26.42, 25.78, 24.68, 22.99, 21.54, 20.07, 19.19, 18.42, 18.24, 17.93, 18.22, 17.06, 16.34, 17.22, 17.84, 19.0, 19.9, 20.76, 20.89, 22.11, 22.82, 23.73, 25.03, 25.77, 26.49, 27.12, 29.43, 30.32, 31.19, 31.93, 31.84, 31.04, 30.68, 31.28, 32.07, 32.58, 32.2, None, 28.98, 28.07, 27.0, 28.11, 28.85, 29.33, None, 32.76, 33.49, 33.11, 32.99, 33.21, 30.27, 28.95, 28.47, 27.04, 26.38, 25.08, 24.68, 23.22, 21.89, 24.02, 24.08, 24.02, 24.26, 24.78, 25.75, 27.16, 28.16, 28.93, 29.62, 28.64, 28.5, 28.45, 29.0, 30.74, 31.56, 32.76, None, 31.19, 30.32, 29.43, 28.02, 27.72, 26.16, 25.65, 26.38, 27.04, 28.47, 28.95, 30.27, 31.17, 31.85, 32.85, 32.65, 32.77, 32.51, 31.19, None] +COAST_LATS = [35.65, 35.4, 36.01, 37.11, 37.66, 37.36, 37.14, 37.34, 37.61, 37.74, 38.49, 37.95, 37.07, 36.95, 37.5, 37.42, 37.02, 36.72, 36.07, 35.15, 34.35, 34.02, 33.11, 31.9, 31.71, 31.3, 30.74, 29.47, 29.34, 29.32, 30.74, 31.55, 32.98, 33.68, 35.65, None, -5.88, -7.22, -8.07, -7.85, -7.74, -7.12, -6.94, -7.29, -8.31, -9.52, -11.08, -11.02, -10.93, -11.72, -12.57, -12.9, -16.9, -17.93, -17.31, -17.42, -16.94, -17.3, -15.79, -14.45, -13.14, -12.04, -10.73, -9.77, -8.96, -7.6, -6.29, -5.97, -5.86, None, -5.68, -5.04, -4.44, -4.99, -5.68, None, 41.86, 41.09, 40.58, 40.11, 39.69, 40.25, 41.41, 41.88, 42.69, 42.59, 42.22, None, 24.25, 24.02, 24.15, 24.8, 26.06, 24.92, 24.27, 23.93, 23.11, 22.5, 24.01, None, -55.2, -54.9, -54.87, -53.1, -54.45, -55.2, None, -22.08, -21.99, -22.25, -24.03, -25.16, -27.12, -27.55, -26.62, -25.55, -26.92, -27.88, -30.22, -32.04, -33.26, -34.43, -35.98, -36.9, -38.72, -38.83, -40.17, -41.03, -40.8, -42.06, -42.04, -42.87, -44.5, -45.04, -46.3, -47.24, -48.7, -50.26, -51.77, -52.3, -52.01, -50.68, -50.38, -48.88, -47.74, -45.56, -44.78, -44.21, -43.41, -42.05, -39.81, -38.55, -36.66, -35.17, -33.27, -31.37, -29.37, -27.52, -26.51, -24.52, -22.99, -21.83, None, 41.09, 40.99, 40.56, 39.9, 39.46, 38.74, 39.47, 39.74, 40.01, 40.74, None, -80.04, -81.0, -80.92, -80.55, -80.29, -79.98, -80.04, None, -79.5, -79.28, -78.87, -78.22, -78.69, -79.5, None, -78.05, -79.09, -80.03, -80.59, -81.03, -80.63, -79.95, -79.18, -78.46, -78.05, -77.83, None, -73.5, -73.48, -74.09, -73.66, -73.32, None, -73.48, -73.83, -73.46, -73.25, None, -71.93, -71.95, -72.44, -72.44, -72.31, -71.72, -71.93, None, -70.96, -71.8, -72.31, -72.48, -72.23, -72.07, -71.27, -71.15, -70.68, -69.51, -68.88, -69.62, -70.51, None, -64.15, -64.21, -64.54, -65.09, -65.86, -66.43, -66.84, -67.58, -68.37, -68.91, -69.62, -70.38, -71.09, -72.38, -73.17, -74.11, -74.58, -75.26, -75.79, -76.22, -76.67, -76.71, -77.1, -77.56, -78.22, -78.38, -79.18, -79.89, -80.42, -81.0, -81.47, -82.04, -82.85, -82.87, -82.26, -81.73, -81.85, -81.65, -81.34, -80.91, -80.59, -79.99, -79.26, -79.46, -79.08, -78.12, -77.65, -77.07, -76.5, -76.28, -76.11, -75.67, -75.13, -74.5, -73.87, -73.15, -72.72, -72.01, -71.27, -71.66, -71.32, -71.03, -71.46, -71.17, -71.64, -71.13, -70.85, -70.46, -69.89, -70.01, -70.83, -70.25, -70.03, -70.03, -69.87, -70.01, -70.4, -70.52, -70.48, -70.32, -69.93, -69.66, -68.84, -68.66, -69.25, -69.52, -69.54, -68.93, -68.46, -68.05, -67.6, -67.37, -67.11, -66.52, -66.05, -65.82, -65.97, -66.68, -67.29, -67.68, -68.01, -67.41, -67.74, -67.93, -68.97, -69.68, -70.31, -70.68, -71.44, -72.17, -72.09, -71.32, -70.72, -69.87, -69.74, -69.46, -68.7, -68.07, -67.54, -67.21, -67.21, -67.15, -66.21, -66.95, -67.23, -67.19, -67.11, -67.39, -67.25, -67.25, -66.58, -65.56, -65.97, -66.93, -66.95, -66.7, -66.13, -65.88, -66.39, -66.66, -67.17, -67.19, -66.56, -66.62, -66.56, -66.66, -66.58, -66.39, -66.29, -65.72, -65.58, -66.45, -66.95, -66.88, -66.82, -66.84, -67.23, -67.9, -68.39, -68.72, -68.89, -68.84, -69.38, -69.6, -70.23, -70.74, -70.78, -70.83, -71.21, -71.7, -72.44, -73.24, -73.81, -74.38, -75.15, -75.87, -76.69, -77.46, -78.18, -78.75, -79.12, -79.73, -80.57, -81.28, -82.06, -82.71, -83.34, -84.04, -84.41, -84.47, -84.72, -84.45, -84.1, -84.12, -84.12, -83.88, -84.24, -84.83, -85.37, -85.3, -85.32, -84.57, -84.3, -83.69, -82.83, -82.04, -81.42, -81.16, -81.34, -80.67, -79.93, -79.36, -79.16, -78.69, -78.03, -76.99, -77.2, -77.5, -77.18, -76.58, -76.11, -75.38, -75.54, -75.09, -74.97, -74.52, -74.36, -74.3, -74.46, -74.42, -74.48, -74.52, -74.19, -74.24, -73.71, -74.38, -74.42, -74.91, -75.13, -74.99, -75.3, -74.54, -74.11, -73.36, -72.75, -72.75, -73.21, -73.62, -73.28, -73.4, -72.56, -73.19, -73.48, -73.64, -73.48, -73.52, -73.64, -73.87, -73.4, -73.15, -72.79, -72.05, -71.25, -70.46, -69.72, -68.95, -68.15, -67.33, -66.58, -65.9, -65.17, -64.64, -64.27, -63.96, -63.39, -63.53, -64.15, None, -48.62, -49.06, -49.71, -49.24, -48.62, None, -40.79, -41.0, -40.88, -42.41, -42.94, -43.58, -42.69, -41.16, -40.79, None, -13.76, -14.17, -14.98, -16.29, -16.91, -18.28, -19.48, -20.39, -21.26, -22.12, -22.4, -24.08, -25.27, -26.64, -28.11, -29.46, -30.92, -32.55, -33.82, -35.17, -36.42, -37.43, -37.81, -38.61, -38.59, -37.9, -38.81, -38.38, -38.02, -36.64, -35.73, -35.13, -35.08, -34.71, -33.64, -33.75, -34.89, -33.95, -32.85, -32.01, -31.5, -31.95, -32.22, -32.96, -33.89, -34.0, -33.93, -34.51, -34.75, -35.03, -34.39, -33.62, -33.26, -32.21, -30.6, -29.46, -28.52, -27.33, -26.12, -25.62, -26.3, -25.0, -24.38, -23.56, -22.48, -22.52, -21.5, -20.7, -20.75, -20.26, -19.95, -19.68, -18.71, -17.8, -16.41, -17.07, -16.11, -15.57, -14.68, -14.23, -14.1, -13.82, -14.87, -14.97, -13.62, -13.11, -12.18, -12.11, -11.27, -11.38, -12.04, -12.25, -12.05, -12.35, -13.29, -13.72, -14.72, -15.55, -16.22, -16.81, -17.37, -17.37, -16.39, -15.04, -14.27, -12.94, -12.41, -11.33, -10.67, -11.78, -12.33, -13.4, None, 48.12, 47.71, 46.85, 46.66, 46.51, 47.12, 46.75, 46.92, 47.35, 47.58, 47.57, 47.7, 47.47, 48.29, 48.88, 48.96, 48.73, 48.6, 48.12, None, 39.74, 39.47, 38.74, 39.34, 39.74, None, 41.22, 41.41, 41.28, 40.53, 40.18, 39.05, 38.32, 38.79, 39.58, 38.77, 39.63, 40.22, 40.81, 41.25, 41.12, 41.18, 41.86, 41.22, None, -4.5, -2.84, -2.35, -2.81, -3.36, -4.09, -4.5, None, 51.35, 51.48, 50.8, 50.09, 49.99, 50.38, 50.8, 51.35, None, 6.26, 6.83, 9.33, 10.18, 11.0, 11.55, 11.94, 12.24, 11.33, 10.33, 9.44, 8.51, 6.26, None, 9.64, 9.86, 9.82, 10.37, 11.38, 12.54, 13.47, 13.54, 14.25, 14.97, 14.92, 14.44, 13.34, 12.63, 11.64, 11.11, 11.02, 10.94, 10.96, 9.64, None, 22.04, 21.48, 21.19, 22.18, 22.81, 21.84, 21.86, 22.06, 23.63, 24.5, 25.24, 26.45, 25.97, 25.13, 24.98, 24.07, 22.99, 23.63, None, 44.23, 43.9, 43.69, 44.18, 43.71, 42.58, 42.14, 41.33, 41.58, 41.34, 42.32, 42.58, 43.21, 44.01, None, 23.76, 24.29, 25.21, 24.34, None, 26.58, 26.79, 26.84, None, 26.59, 26.01, 26.93, 26.59, None, 44.86, 44.42, 43.57, 43.43, 42.65, 43.45, 44.04, 44.82, 45.0, 45.23, 45.08, None, 53.91, 54.28, 55.17, 55.78, 55.92, 55.79, 55.08, 54.16, 53.79, 53.35, 53.17, 52.74, 52.04, 51.32, 51.37, 51.43, 51.59, 51.91, 51.62, 52.02, 52.69, 53.47, None, 17.81, 18.0, 18.49, 18.35, 18.08, 17.49, 17.04, 16.27, 15.89, 17.02, None, 32.31, 32.3, 32.31, 32.29, 32.28, 32.27, 32.26, 32.25, 32.27, 32.28, 32.3, 32.31, 32.33, 32.3, 32.3, 32.29, 32.26, 32.25, 32.25, 32.25, 32.26, 32.27, 32.29, 32.31, 32.33, 32.35, 32.36, 32.37, 32.39, 32.38, 32.37, 32.36, 32.36, 32.35, 32.36, 32.35, 32.33, 32.36, 32.35, 32.34, 32.33, 32.32, 32.31, None, -22.03, -22.8, -21.83, -22.87, -20.37, -18.98, -17.58, -15.66, -14.95, -13.6, -12.56, -11.04, -10.71, -9.93, -10.51, -11.57, -12.63, -13.2, -13.48, -14.35, -15.08, -16.26, -16.88, -17.55, -18.96, -19.97, -19.87, -19.34, -20.51, -22.25, None, -30.22, -27.88, -26.92, -25.55, -25.16, -24.02, -24.0, -23.57, -22.36, -22.28, -20.73, -19.97, -18.96, -17.55, -16.88, -16.26, -15.08, -14.35, -13.48, -13.2, -12.63, -11.57, -10.51, -9.93, -10.71, -11.04, -11.12, -9.49, -10.05, -9.46, -8.42, -7.34, -6.63, -5.74, -4.59, -4.25, -1.56, -0.55, 0.54, 0.6, 1.09, 1.69, 1.72, 1.25, 0.79, 1.33, 1.92, 2.41, 3.13, 4.06, 4.02, 4.01, 4.54, 5.2, 5.01, 4.42, 3.61, 2.25, 1.32, 1.46, 1.68, 1.86, 1.82, 2.22, 2.42, 2.31, 2.38, 2.05, 2.5, 4.16, 3.65, 1.74, 0.22, -0.24, -0.58, -1.55, -2.69, -2.91, -3.7, -5.11, -5.46, -7.34, -9.65, -12.17, -13.06, -15.67, -17.87, -19.6, -21.94, -22.97, -23.35, -24.09, -25.88, -27.18, -28.67, -30.98, -32.25, -33.77, -32.73, -31.49, -30.88, -30.22, None, 4.53, 5.45, 4.32, 4.01, None, 27.77, 26.84, 26.88, 27.1, 28.04, 28.06, 27.77, None, -18.54, -19.29, -20.5, -21.49, -22.09, -23.57, -24.62, -25.17, -25.72, -25.39, -25.5, -26.28, -26.83, -25.87, -24.77, -21.81, -18.22, -18.28, -17.89, -17.74, None, 7.42, 7.75, 7.51, 8.28, 8.98, 9.01, 10.57, 11.14, 10.09, 9.27, 8.67, 7.83, 6.98, 5.95, 5.23, 5.15, 5.17, 4.9, 4.61, 4.63, 4.22, 4.69, 4.71, 3.5, 3.73, 2.27, 3.01, 3.85, 4.73, 5.45, 6.41, None, 46.55, 46.44, 45.97, 46.73, 46.55, None, 49.11, 49.4, 49.96, 49.29, None, 48.51, 48.83, 49.53, 49.99, 50.77, 50.4, 49.95, 49.06, None, 50.69, 50.15, 49.59, 49.56, 48.52, 48.16, 46.66, 46.81, 47.75, 46.92, 47.63, 47.6, 48.25, 49.13, 51.29, 51.59, 50.69, None, 54.04, 52.98, 52.18, 53.1, 53.85, 54.04, None, 62.16, 61.72, 62.09, 62.36, None, 62.71, 62.18, 62.91, 62.71, None, 65.66, 65.37, 64.77, 63.98, 63.73, 63.65, 63.57, 63.64, 64.04, 65.74, None, 67.15, 67.59, 68.29, 67.58, 67.15, None, 69.11, 69.06, 69.4, 70.14, 69.68, 69.11, None, 69.5, 69.26, 67.87, 67.92, 69.88, 69.66, 68.67, 67.6, 66.41, 66.56, 65.21, 64.1, 63.61, 62.84, 60.9, 58.95, 57.85, 57.28, 56.47, 55.72, 55.24, 54.28, 52.16, 51.53, 54.14, 55.14, 56.53, 58.05, 59.85, 62.32, 62.28, 62.44, 61.53, 61.06, 58.96, 58.21, 59.87, 59.44, 56.97, 55.78, 54.95, 53.78, 53.27, 51.77, 51.06, 50.08, 50.3, 49.51, 47.74, 46.99, 49.13, 48.74, 46.99, 45.74, 47.01, 45.92, 44.67, 43.55, 44.47, 45.26, 45.7, 47.35, 47.45, 45.91, 45.31, 45.01, 45.0, 44.1, 43.63, 43.63, 43.27, 42.86, 42.21, 41.68, 41.98, 42.43, 43.57, 45.35, 45.99, 46.12, 46.51, 46.44, 46.64, 47.22, 47.94, 48.02, 48.27, 48.45, 48.67, 49.39, 49.0, 49.0, 49.0, 49.0, 49.0, 49.0, 49.98, 50.83, 52.33, 53.56, 54.8, 55.92, 57.69, 58.86, 59.79, 58.91, 60.0, 60.31, 69.71, 68.99, 69.32, 69.51, 70.19, 70.01, 70.38, 70.16, 69.56, 69.8, 69.01, 68.91, 67.9, 67.81, 67.38, 68.31, 68.7, 68.56, 68.1, 67.81, 68.4, 68.24, 68.09, 69.07, 70.09, 71.92, 71.32, 69.7, None, 73.12, 72.96, 72.96, 71.65, 73.09, 73.08, 71.7, 70.5, 69.58, 69.12, 68.91, 69.12, 68.63, 69.01, 69.17, 70.07, 70.19, 70.6, 70.54, 71.31, 71.56, 72.71, 73.12, None, 73.42, 73.46, 73.64, None, 73.1, 72.86, 72.74, 73.33, 73.76, 73.1, None, 73.16, 73.34, 72.72, 72.35, 72.24, 71.33, 70.92, 70.12, 68.72, 67.85, 66.86, 65.0, 66.39, 65.69, 64.65, 63.39, 62.95, 62.88, 61.93, 62.91, 63.68, 64.68, 64.23, 65.31, 65.45, 66.31, 67.73, 68.55, 69.15, 69.83, 69.87, 69.97, 70.41, 71.22, 72.24, 73.54, 73.16, None, 73.84, 73.76, 72.99, 71.66, 71.36, 72.51, 72.71, 73.84, None, 72.77, 72.06, 73.44, 74.13, 73.86, 72.77, None, 71.38, 71.34, 72.29, 73.68, 74.45, 74.19, 73.48, 72.52, 71.38, None, 74.98, 74.67, 75.38, 75.3, None, 76.72, 75.74, 74.9, 75.64, 76.34, 76.65, 76.72, None, 76.2, 76.01, 75.48, 74.85, 74.39, 75.16, 75.22, 76.48, 75.55, 76.43, 76.68, None, 77.1, 76.78, 76.07, 75.61, 75.48, 75.78, 75.34, 74.66, 74.56, 74.39, 74.84, 75.88, 76.44, 77.16, None, 77.65, 76.53, 76.05, 76.12, 76.86, 77.5, None, 77.52, 77.56, 77.82, 77.52, None, 77.7, 77.73, 78.15, 77.7, None, 78.6, 78.41, 78.85, 78.6, None, 78.06, 78.08, 78.87, 78.77, 78.06, None, 78.32, 78.02, 78.38, 78.92, 79.17, 78.32, None, 79.66, 79.04, 78.22, 78.75, 79.38, 79.71, 80.6, 80.98, 81.26, 80.51, 79.66, None, 83.11, 82.9, 82.36, 81.73, 81.51, 80.62, 79.63, 79.32, 79.02, 78.18, 77.51, 76.98, 76.78, 76.45, 76.42, 76.95, 77.9, 77.54, 78.37, 79.0, 79.74, 80.21, 80.46, 80.52, 81.26, 81.89, 82.12, 82.65, 82.32, 83.02, 83.17, 83.23, 83.11, None, 47.53, 47.1, 46.89, 46.31, 46.04, 46.16, 45.78, 46.43, 46.73, 47.54, 47.62, 47.83, None, -52.64, -54.87, -55.3, -55.58, -55.2, -54.5, -52.84, -53.72, -53.62, -52.52, None, -21.49, -22.74, -24.03, -26.19, -26.9, -28.46, -30.34, -33.09, -34.19, -36.01, -37.58, -38.92, -40.83, -42.25, -43.79, -44.41, -44.97, -46.88, -48.24, -49.32, -50.74, -51.43, -52.14, -52.29, -52.9, -53.86, -52.84, -52.26, -51.04, -48.67, -46.94, -45.76, -44.45, -42.12, -43.22, -39.94, -38.28, -37.12, -33.91, -30.92, -28.86, -25.71, -21.39, -18.35, -17.58, -18.98, -20.37, None, 18.68, 18.51, 19.82, 20.08, 19.26, None, 49.76, 48.73, 47.79, 48.48, 47.21, 45.14, 44.97, 42.93, 42.4, 42.42, 41.47, 41.82, 40.57, 39.64, 38.9, 39.75, 40.95, 39.9, 39.2, 38.06, 37.45, 37.87, 37.45, 36.65, 35.61, 34.36, 32.46, 30.95, 30.14, 29.02, 28.14, 25.74, 23.62, 22.67, 22.55, 21.55, 20.34, 21.01, 21.72, 21.81, 22.79, 23.35, 22.7, 22.46, 21.17, 21.44, 21.56, 22.12, 23.14, 23.9, 25.92, 27.51, 28.34, 28.41, 29.45, 29.28, 27.9, 28.04, 28.3, 27.3, 27.88, 28.2, 28.84, 29.46, 30.42, 30.88, 32.62, 32.99, 34.32, 35.9, 37.13, 37.99, 38.61, 39.43, 39.89, 40.56, 41.07, 41.58, 42.35, 43.18, 45.32, 47.33, 47.45, 48.55, 49.3, 48.07, 46.89, 45.29, 44.98, 44.24, 42.73, 42.52, 42.51, 41.91, 42.13, 42.52, 43.41, 44.07, 45.1, 44.81, 45.73, 46.67, 46.69, 47.75, 47.7, 47.73, 49.13, 49.51, 50.58, 51.96, 52.75, 53.43, 53.16, 51.78, 50.74, None, 4.99, 5.18, 4.99, 4.34, 5.19, 5.71, 6.19, 6.91, 7.69, 8.12, 8.46, 9.38, 10.13, 10.3, 10.14, 10.41, 10.1, 10.37, 9.82, 9.86, 9.64, 7.38, 5.39, None, 2.27, 2.19, 2.26, 3.07, 3.9, 4.5, 5.48, 6.45, 7.06, 6.98, 7.8, 8.72, 9.64, 10.8, 11.9, 12.48, 12.86, 11.56, 9.98, 9.92, 9.55, 8.8, 7.69, 6.41, 5.45, 4.73, 3.85, 3.01, 2.27, 1.96, 2.27, None, 3.51, 2.2, 1.58, 0.6, -0.59, -1.62, -2.29, -3.29, -5.42, -6.52, -8.34, -8.41, -9.16, -10.79, -11.97, -12.18, -13.25, -12.27, -11.61, -11.78, -11.24, -10.95, -10.87, -10.99, -9.89, -8.91, -7.92, -7.3, -6.94, -7.16, -7.99, -7.99, -7.55, -6.62, -5.86, -5.97, -5.79, -5.25, -4.78, -4.5, -4.79, -4.34, -3.54, -1.74, -0.74, -0.06, 0.86, 2.37, 3.5, 4.71, 4.69, 4.22, 4.63, 4.61, 4.9, 5.17, 5.15, 5.23, 4.29, 4.39, 4.17, None, -4.78, -4.61, -3.98, -2.77, -2.39, -2.43, -2.0, -0.55, 1.2, 1.31, 2.27, 1.96, 2.27, 3.73, 3.5, 2.37, 0.86, -0.06, -0.74, -1.74, -3.54, -4.34, -4.79, -4.5, -4.78, None, -0.15, 0.42, 0.4, 0.81, 1.69, 2.27, 2.7, 3.85, 4.67, 5.85, 7.22, 7.64, 8.52, 8.64, 9.44, 10.62, 11.1, 11.23, 11.96, 12.38, 11.78, 11.11, 10.45, 9.15, 8.63, 8.0, 7.42, 6.99, 6.96, 6.21, 6.27, 5.56, 4.5, 3.54, 2.82, 2.25, 1.13, 2.04, 1.71, 0.99, 0.71, -0.19, -1.12, -4.3, -3.74, -2.26, -2.17, -2.31, -1.0, -0.06, None, 8.23, 8.66, 9.05, 9.49, 9.91, 9.8, 9.83, 10.13, 10.75, 11.09, 10.95, 11.0, 10.73, 10.4, 9.57, 9.07, 8.81, 8.42, None, 23.19, 23.11, 22.4, 22.28, 21.21, 21.02, 20.69, 20.05, 19.87, 19.86, 20.67, 21.03, 21.56, 22.04, 22.39, 22.69, 22.15, 21.8, 22.2, 22.79, 23.08, None, 35.14, 35.39, 35.67, 35.06, 35.02, 35.0, 35.16, 35.09, None, 35.06, 34.57, 35.1, 35.09, 35.16, 35.0, 35.02, 35.06, None, 48.6, 48.73, 48.96, 48.88, 49.55, 50.27, 50.73, 51.12, 51.11, 50.7, 50.22, 50.36, 49.99, 49.5, 49.27, 49.0, 48.8, 48.6, None, 54.98, 54.36, 54.2, 54.08, 53.25, 52.62, 51.75, 51.0, 50.93, 50.48, 49.97, 49.31, 48.42, 47.64, 47.67, 47.52, 47.3, 47.53, 47.61, 48.33, 49.2, 49.9, 50.8, 51.85, 53.14, 53.69, 53.53, 54.4, 54.83, None, 12.7, 11.97, 11.46, 11.11, 11.05, 11.63, 12.54, 12.7, None, 55.61, 55.36, 56.11, None, 56.46, 56.19, 54.98, 54.96, 56.54, 57.11, 57.45, 57.22, 56.61, None, 19.71, 19.88, 19.65, 19.31, 18.98, 18.21, 18.38, 18.25, 18.43, 17.6, 18.04, 18.62, 19.17, None, 23.47, 19.6, 19.06, 19.86, 20.61, 24.97, 27.59, 28.84, 29.73, 30.5, 31.64, 32.09, 32.65, 33.92, 35.17, 35.89, 36.61, 36.87, 37.11, 36.89, 36.43, 34.66, 33.34, 32.51, 30.31, 28.96, 27.69, 26.51, 25.37, 24.38, 24.1, None, -3.4, -2.22, -2.25, -1.06, -0.28, 0.77, 1.38, 0.83, 0.26, 0.08, -0.91, -2.61, -3.87, -4.96, -4.35, -4.06, -3.4, None, 29.5, 28.34, 27.65, 28.42, 29.76, 27.7, 25.6, 23.93, 23.1, 22.0, 22.0, 25.68, 30.04, 31.09, 31.59, 31.03, 31.19, 31.56, 30.93, 31.02, 31.22, None, 12.54, 13.45, 14.12, 14.53, 14.51, 14.21, 14.82, 16.96, 17.43, 16.84, 15.44, 13.92, 13.0, 12.46, None, 41.88, 43.03, 43.57, 43.4, 43.42, 42.58, 42.34, 41.89, 41.01, 40.12, 38.74, 37.64, 36.67, 36.68, 35.95, 36.37, 37.1, 37.8, 38.37, 39.63, 40.18, 41.11, 41.88, 41.79, 42.28, 41.88, None, 57.79, 58.26, 59.19, 59.61, 59.48, 58.72, 57.47, 57.85, 57.79, None, 14.96, 14.74, 14.52, 13.77, 12.87, 12.1, 11.36, 11.03, 10.93, 10.02, 9.18, 8.0, 4.96, 4.23, 3.92, 3.84, 3.5, 3.59, 4.45, 4.78, 5.51, 6.83, 7.71, 8.35, 8.68, 10.63, 11.32, 12.58, 14.42, 14.96, None, 69.06, 67.7, 65.81, 64.2, 62.87, 61.78, 60.42, 59.85, 60.72, 62.61, 63.82, 65.11, 66.01, 67.94, 69.11, 68.84, 68.65, 69.83, 69.77, None, -17.34, -18.15, -18.16, -17.38, -17.34, None, -16.8, -16.64, -16.38, -16.56, None, -16.5, -16.07, -16.5, None, -51.85, -51.5, -51.55, -52.2, -52.3, None, 42.15, 41.58, 42.63, 42.15, None, 50.38, 49.99, 49.44, 49.2, 48.33, 47.45, 47.29, 46.27, 45.99, 45.33, 44.25, 43.69, 43.4, 42.47, 42.8, 43.03, 44.02, 47.06, 47.95, 48.9, 49.78, 50.13, 51.15, 50.78, None, -3.98, -2.14, -0.78, 0.27, 1.07, 2.26, 2.19, 2.27, 1.31, 1.2, -0.55, -2.0, -2.43, -2.39, -2.77, -3.98, None, 54.55, 54.07, 54.6, 55.17, None, 58.63, 57.69, 56.87, 55.91, 54.62, 53.33, 52.74, 51.81, 50.77, 50.5, 50.23, 49.96, 51.21, 51.43, 51.99, 52.84, 53.4, 53.98, 54.62, 55.06, 55.78, 56.28, 57.82, 58.55, None, 41.54, 42.65, 43.13, 43.55, 43.22, 42.55, 42.5, 41.86, 41.18, 41.12, 41.25, 41.58, None, 5.93, 5.0, 4.99, 6.25, 8.22, 10.4, 11.01, 11.1, 10.71, 9.47, 8.31, 6.91, 5.93, None, 7.69, 7.31, 7.53, 8.54, 8.41, 8.72, 9.27, 10.05, 9.86, 9.62, 8.9, 9.89, 10.21, 10.88, 11.53, 11.68, 11.81, 12.25, 12.58, 12.35, 12.39, 12.08, 12.21, 11.92, 12.06, 12.33, 12.09, 11.39, 10.81, 10.79, 10.21, 9.79, 8.58, 8.32, 7.69, None, 13.15, 13.62, 13.88, 13.63, 13.51, 13.3, 13.28, 13.13, None, 11.04, 11.52, 11.96, 12.38, 12.52, 12.59, 12.14, 11.68, 11.51, 11.04, None, 1.01, 2.28, 1.06, 1.01, None, 35.71, 35.42, 35.18, 35.0, 35.08, 35.71, None, 41.56, 40.82, 40.95, 40.12, 39.96, 40.26, 39.19, 38.51, 37.66, 37.41, 36.42, 36.84, 38.31, 39.34, 40.11, 40.58, 40.93, 41.13, 41.34, 41.58, 41.33, 41.56, None, 82.63, 83.18, 83.65, 82.73, 82.3, 82.02, 81.79, 81.73, 81.52, 81.72, 80.58, 80.18, 79.4, 77.64, 76.94, 76.1, 75.16, 74.22, 73.46, 73.31, 72.18, 72.33, 71.47, 70.47, 71.43, 70.23, 70.13, 68.47, 68.12, 66.68, 65.94, 65.46, 64.14, 62.68, 61.07, 60.04, 60.86, 62.38, 64.28, 66.1, 67.19, 68.73, 69.93, 69.43, 69.61, 70.82, 70.57, 71.55, 71.65, 72.96, 74.71, 75.52, 76.18, 76.06, 77.01, 77.38, 78.04, 78.91, 79.76, 80.52, 81.32, 82.03, 82.2, 82.44, 81.99, 82.2, None, 13.74, 13.93, 14.54, 15.06, 16.07, 16.41, 16.69, 17.25, 17.82, 17.81, 15.89, 15.71, 15.73, 15.07, 14.68, 14.36, 14.13, 13.74, None, 2.5, 2.05, 2.38, 2.31, 3.19, 4.21, 5.76, 5.41, 4.16, 2.5, None, 8.37, 7.35, 6.81, 5.97, 4.81, 4.06, 3.33, 1.9, 1.95, 1.51, 1.27, 1.79, 2.76, 3.96, 4.57, 5.24, 5.96, 6.7, 7.04, 7.78, None, 12.98, 13.38, 13.89, 13.85, 14.14, 14.42, 14.87, 15.35, 15.69, 15.88, 15.85, 15.78, 16.01, 15.89, 16.0, 15.84, 15.42, 15.0, 14.88, 14.75, 14.67, 14.79, 14.56, 14.08, 13.84, 13.77, 13.75, 13.25, 12.98, None, 45.91, 45.24, 45.08, 45.23, 45.0, 44.82, 44.04, 43.45, 42.65, 42.85, 43.51, 44.32, 45.08, 44.8, 45.48, 45.47, 45.47, 45.73, 46.24, 46.38, 45.76, None, 19.92, 19.71, 18.79, 18.32, 18.21, 18.22, 18.34, 18.53, 18.67, 19.48, 19.92, None, 46.85, 47.71, 48.12, 47.76, 48.08, 48.27, 48.33, 48.62, 48.42, 47.88, 46.99, 46.13, 45.91, 45.95, 46.5, 46.85, None, -10.24, -9.56, -9.67, -10.24, None, -10.14, -10.24, -9.29, -9.09, -10.14, None, -8.1, -8.28, -8.91, -9.03, -8.45, None, -8.09, -8.93, -8.44, -8.54, -8.09, None, -6.78, -6.47, -7.59, -8.37, -8.35, -8.3, -7.74, -7.77, -6.92, -5.9, -6.35, -6.78, None, -6.21, -6.14, -5.45, -6.21, None, -3.46, -3.61, -3.13, None, -3.09, -3.45, -3.43, -2.84, -3.09, None, -1.15, -3.37, -1.7, -2.05, -2.6, -9.12, -8.1, -8.41, -7.32, -5.39, -4.46, -4.02, -3.75, -2.82, -2.48, -2.21, -1.43, -0.7, -0.78, None, 1.42, 0.24, 0.38, -0.52, -0.96, -1.08, -1.52, -3.19, -4.68, -5.63, -4.46, -4.57, -3.6, -2.93, -5.53, -5.38, -3.49, -2.8, -1.35, 0.57, 1.01, 0.92, 1.42, None, 1.13, 0.36, -0.78, -0.27, 1.81, 1.63, 1.13, None, 1.83, 0.78, -0.8, -2.48, -3.66, -3.5, -3.12, -2.99, -2.93, -1.31, 0.42, 2.01, 0.77, 0.9, 1.5, 1.43, 3.17, 4.31, 3.23, 1.83, None, -5.85, -5.04, -3.61, -2.05, 0.18, 1.82, 3.31, 4.97, 5.44, 4.27, 3.17, 2.08, 0.56, -0.71, -1.08, -2.34, -3.06, -5.85, None, 35.49, 33.51, 32.48, 31.52, 30.18, 28.79, 27.93, 27.23, 26.63, 26.41, 27.45, 28.09, 27.1, 26.88, 26.84, 27.77, 28.64, 29.03, 28.83, 28.26, 27.7, 27.26, 26.0, 24.68, 24.08, 22.7, 22.04, 23.62, 23.5, 24.13, 25.15, 25.27, 26.01, 25.77, 24.87, 24.23, 22.88, 21.69, 21.5, 20.15, 18.3, 17.02, 16.31, 15.9, 13.84, 12.06, 10.31, 9.22, 8.25, 8.9, 11.31, 12.74, 14.62, 17.93, 20.42, 20.76, 22.09, 22.84, 24.36, 25.22, 26.49, 27.99, 28.96, 30.98, 32.27, 33.44, 34.75, 34.65, None, 53.87, 52.26, 51.82, 53.88, 55.13, 54.06, 53.87, None, 37.2, 37.96, 38.12, 37.52, 36.53, 35.65, 33.68, 32.98, 31.55, 30.74, 29.3, 28.26, 27.22, 26.24, 25.38, 25.74, 27.14, 26.48, 27.58, 28.81, 29.99, 29.93, 30.99, 31.71, 33.02, 34.75, 35.68, 37.17, 38.28, 39.71, 38.87, 38.77, 39.58, 38.79, 38.32, 37.37, 36.7, 37.2, None, 35.98, 35.09, 33.97, 32.47, 30.98, 30.45, 29.98, 29.1, 31.19, 32.16, 34.42, 36.36, 37.23, 37.26, 37.17, None, 66.46, 65.13, 63.68, 63.64, 64.4, 65.08, 65.61, 66.41, 66.28, 66.53, None, 32.71, 32.53, 31.75, 31.35, 31.1, 31.22, 31.61, 32.83, 33.09, 33.26, 32.87, 32.71, None, 38.23, 37.13, 37.0, 37.61, 38.03, 38.23, None, 41.21, 39.18, 38.91, 40.38, 40.9, None, 46.77, 46.02, 45.74, 44.89, 44.09, 42.76, 41.96, 41.54, 40.88, 40.17, 40.28, 39.8, 38.9, 37.99, 38.21, 38.96, 40.05, 40.6, 41.19, 41.7, 42.93, 44.04, 44.23, 43.69, 44.25, 45.33, 45.99, 45.82, 46.01, 46.44, 46.48, 46.75, 47.12, None, 18.49, 18.16, 17.87, 17.86, 18.45, 18.49, None, 32.39, 32.31, 32.16, 31.51, 30.34, 29.87, 29.2, 29.5, 31.49, 32.39, None, 34.15, 33.2, 33.29, 32.99, 34.06, 34.36, None, 37.14, 35.84, 34.67, 33.46, 34.6, 33.9, 33.15, 31.03, 32.32, 33.3, 34.23, 35.43, 35.53, 36.83, 38.22, 40.56, 41.38, 39.18, 37.14, None, 44.17, 44.38, 42.99, 42.68, 41.57, 43.33, 44.77, 44.51, None, 42.27, 41.38, 40.66, 41.17, 41.99, 43.73, 43.5, 44.78, 45.59, 41.31, 42.04, 42.12, 42.03, 42.79, 44.03, 44.61, 45.25, 45.26, 46.85, 47.05, 46.4, 47.08, 47.72, 49.15, 50.45, 50.61, 51.72, 50.62, 51.06, 50.84, 51.27, 52.45, 52.98, 54.01, 54.6, 55.39, 54.13, 54.04, 53.55, 54.18, 50.86, 50.81, 50.89, 50.12, 49.83, 48.55, 47.45, 47.33, 45.32, 43.18, 42.35, 42.86, 42.99, 43.3, 42.5, 42.7, None, -0.86, -2.08, -2.57, -3.68, -4.68, -3.1, -0.95, 0.52, 1.91, 3.56, 4.85, 5.34, 4.45, 3.6, 3.62, 3.42, 4.26, 3.92, -0.86, None, 42.27, 42.85, 43.09, 42.88, 42.96, 42.5, 42.12, 41.19, 40.43, 40.37, 39.66, 39.28, 39.53, 39.94, 40.15, 41.39, 41.52, 42.27, None, 10.63, 12.19, 14.23, 14.27, 14.57, 13.54, 11.57, 10.89, 10.63, None, 38.61, 36.78, 35.08, 34.48, 34.93, 36.73, 37.75, 37.8, 38.3, 38.61, None, 42.05, 41.86, 42.32, 42.81, 43.22, 43.13, 42.91, 42.68, 42.44, 42.25, 42.05, None, 29.98, 29.31, 28.53, 29.1, 29.98, None, 14.27, 15.57, 17.43, 18.31, 17.93, 17.51, 19.46, 20.11, 20.79, 21.2, 22.32, 21.68, 20.76, 19.62, 18.67, 16.6, 15.2, 14.57, 14.27, None, 33.28, 33.09, 33.91, 34.64, 34.2, 33.28, None, 4.36, 4.83, 6.14, 7.11, 7.94, 8.43, 7.93, 7.31, 7.71, 7.4, 6.47, 6.13, 5.31, 4.36, None, 22.86, 23.04, 24.1, 24.38, 25.37, 26.51, 27.69, 28.96, 30.31, 30.96, 31.76, 32.37, 32.79, 32.71, 31.38, 30.76, 30.53, 31.75, 32.71, 32.64, 32.19, 31.9, 31.09, 30.04, 25.68, 20.0, 19.58, 23.41, None, 7.52, 6.2, 6.76, 9.82, 8.56, None, -28.96, -29.74, -30.23, -30.65, -29.24, -28.65, None, 54.33, 54.86, 55.19, 56.34, 56.37, 56.1, 55.17, 54.28, 53.91, 54.33, None, 50.13, 49.46, 49.53, 50.13, None, 56.03, 57.41, 57.01, 57.79, 57.85, 57.47, 56.76, 55.78, 56.1, 56.37, 56.34, None, 35.76, 35.4, 35.17, 33.92, 32.65, 32.09, 31.64, 30.5, 29.73, 28.84, 27.66, 27.12, 26.86, 26.99, 26.1, 24.77, 22.31, 21.5, 21.42, 22.16, 23.02, 24.36, 25.1, 26.25, 27.64, 28.04, 28.83, 29.93, 32.04, 33.24, 34.11, 35.76, None, 48.22, 48.47, 48.12, 47.51, 46.93, 46.53, 46.35, 46.52, 46.26, 45.6, 45.94, 46.81, 47.83, 48.22, None, -12.47, -13.56, -15.23, -16.0, -15.71, -16.88, -17.95, -20.5, -23.78, -25.18, -25.35, -24.46, -22.78, -21.34, -20.83, -19.44, -18.33, -16.85, -16.18, -15.79, -15.21, -14.09, -13.78, -12.49, -12.47, None, 25.87, 24.27, 22.44, 21.41, 19.89, 18.83, 18.14, 18.52, 18.88, 19.87, 21.0, 21.49, 21.54, 20.85, 19.65, 19.04, 18.52, 18.49, 18.0, 17.81, 17.82, 17.25, 16.69, 16.41, 16.07, 15.06, 14.54, 15.94, 16.13, 15.65, 16.11, 16.71, 17.65, 17.98, 18.75, 19.95, 20.53, 21.08, 21.87, 22.77, 24.55, 25.58, 26.44, 27.16, 27.94, 28.95, 30.02, 31.17, 31.52, 31.39, 30.16, 29.06, 28.75, 28.43, 27.53, 26.66, 25.29, 24.3, 23.81, 23.19, 22.82, 24.0, 24.74, 26.01, 26.77, 26.9, 27.72, 27.74, 28.57, 29.56, 30.84, 32.54, 32.72, 32.04, 31.34, 31.75, 31.4, 30.64, 29.57, 28.97, 29.78, 28.7, 27.54, 26.37, 25.84, None, 41.86, 42.05, 42.25, 42.32, 41.34, 41.13, 40.93, 41.09, 41.86, None, 14.62, 15.39, 15.13, 15.26, 15.5, 16.33, 24.96, 22.79, 20.14, 19.69, 19.16, 16.18, 15.41, 14.97, 14.92, 14.97, 14.25, 13.54, 13.47, 12.54, 11.38, 10.37, 10.1, 10.41, 10.14, 10.3, 10.49, 10.91, 11.14, 11.81, 12.31, 12.19, 11.84, 12.18, 12.08, 12.44, 13.14, 13.99, None, 35.85, 35.82, 35.98, 35.89, None, 36.03, 36.04, 36.08, 36.04, None, 20.19, 19.71, 18.45, 16.84, 15.31, 14.62, 13.27, 11.89, 9.93, 11.44, 13.12, 14.84, 16.93, 15.71, 16.04, 18.21, 19.73, 20.67, 21.32, 22.28, 23.04, 23.85, 25.16, 26.57, 27.08, 27.88, 28.34, 27.51, 25.92, 23.9, 23.14, 22.12, 21.56, 21.44, 20.42, None, 42.5, 42.2, 41.96, 42.48, 43.2, 43.52, 43.21, 42.9, 42.59, None, 49.3, 50.33, 50.5, 50.01, 49.73, 51.01, 51.63, 51.26, 50.09, 50.41, 49.79, 49.29, 49.38, 50.25, 49.81, 49.13, 47.73, 47.7, 47.75, 46.69, 46.67, 45.73, 44.81, 45.1, 44.07, 43.41, 42.52, 42.13, 41.91, 42.51, 42.52, 42.73, 44.24, 44.98, 45.29, 46.89, 48.07, 49.3, None, -11.52, -11.72, -11.57, -11.29, -10.32, -11.76, -14.2, -15.41, -16.72, -17.59, -18.84, -19.78, -21.25, -22.14, -23.07, -23.71, -24.48, -25.36, -26.15, -26.74, -26.29, -25.48, -23.66, -21.12, -20.3, -19.42, -17.98, -16.39, -16.07, -15.88, -14.8, -14.45, -14.61, -15.48, -16.8, -15.9, -13.89, -13.58, -11.52, None, 14.62, 16.04, 16.6, 16.37, 16.14, 17.17, 19.1, 20.09, 21.0, 21.33, 23.28, 25.93, 27.4, 24.96, 16.33, 15.5, 15.26, 15.13, 15.39, 14.62, None, -11.52, -13.58, -13.89, -15.9, -16.8, -15.48, -14.61, -14.45, -13.71, -12.44, -10.8, -9.68, -9.42, -10.16, None, 6.2, 5.81, 6.13, 4.86, 3.73, 2.79, 1.63, 1.23, 2.76, 3.94, 5.31, 6.46, 6.2, None, 4.48, 4.31, 3.17, 1.43, 1.5, 0.9, 0.77, 2.01, 1.85, 2.89, 3.89, 4.01, 4.32, 5.45, 6.92, 6.42, 5.71, 5.02, 4.48, None, -28.58, -27.09, -25.39, -22.66, -21.7, -19.67, -18.07, -17.11, -16.97, -17.35, -17.79, -17.52, -17.35, -17.66, -17.89, -17.87, -18.25, -21.85, -28.46, -29.05, -28.78, -28.08, None, -21.08, -22.16, -22.13, -21.15, -20.11, -20.46, -21.08, None, 11.94, 12.85, 13.99, 14.93, 15.32, 15.57, 16.85, 19.6, 23.47, 22.49, 21.31, 20.73, 19.96, 16.63, 14.37, 13.35, 12.86, 12.48, 13.56, 13.04, 13.39, 13.28, 12.83, 13.1, 13.49, 13.75, 12.96, 11.66, 12.23, None, 4.77, 4.46, 4.26, 5.61, 6.26, 7.87, 9.14, 10.06, 10.73, 11.66, 12.96, 13.75, 13.49, 13.1, 12.83, 13.28, 13.39, 13.04, 13.56, 12.48, 11.9, 10.8, 9.64, 8.72, 7.8, 6.98, 7.06, 6.45, 5.48, None, 11.09, 11.81, 12.46, 13.06, 12.98, 13.25, 13.75, 13.77, 13.84, 14.08, 14.56, 14.79, 14.67, 14.75, 14.88, 15.0, 14.68, 13.97, 13.13, 12.42, 11.89, 11.37, 10.94, 10.79, 11.08, 11.22, None, 53.51, 53.14, 51.85, 50.8, 51.48, 51.35, 53.09, None, 71.19, 70.19, 69.16, 69.77, 69.83, 68.65, 68.84, 69.11, 68.41, 68.01, 67.3, 64.79, 64.05, 63.13, 61.29, 59.43, 59.47, 58.08, 59.66, 62.61, 64.49, 67.81, 69.82, 70.2, 70.99, None, 77.85, 77.68, 78.25, 78.08, None, 79.7, 78.56, 77.64, 76.77, 77.74, 78.87, 80.01, 79.67, 80.05, None, 80.41, 79.52, 79.57, 79.86, 80.6, 80.66, None, 27.88, 26.81, 26.4, 26.73, 27.36, 28.42, 29.73, 30.42, 29.46, 28.84, 28.2, 27.88, None, -40.92, -40.93, -41.77, -42.97, -43.85, -44.24, -45.91, -46.64, -46.29, -45.85, -44.12, -43.56, -42.51, -41.51, -40.49, None, -36.16, -36.53, -37.56, -37.96, -37.7, -39.17, -39.45, -40.07, -41.29, -41.43, -40.46, -39.51, -38.8, -37.38, -36.53, -35.24, -34.45, -35.27, None, 21.11, 20.48, 19.74, 18.94, 18.57, 17.88, 17.63, 16.95, 16.71, 17.35, 20.0, 22.71, 23.52, 24.13, 24.92, 24.24, 23.75, 22.99, 22.53, 21.71, 21.11, None, 25.9, 26.06, 26.31, None, 37.13, 35.9, 34.65, 34.75, 33.44, 32.27, 30.98, 28.96, 27.99, 26.49, 25.22, 24.36, 23.94, 25.43, 25.22, 26.24, 27.22, 28.26, 29.3, 29.32, 29.34, 29.47, 30.74, 31.3, 31.71, 31.9, 33.11, 34.02, 34.35, 35.15, 36.07, 36.72, 37.02, None, 7.22, 8.05, 8.39, 9.0, 8.58, 8.3, 7.55, 7.27, 7.82, 7.71, 8.18, 8.29, 8.23, 8.63, 8.93, 9.48, 9.21, 8.95, 8.79, 9.11, 9.61, 9.45, 9.25, 8.67, 7.94, 7.71, None, -17.58, -18.35, -17.36, -15.27, -13.82, -12.22, -8.39, -7.19, -6.14, -4.74, -3.4, -4.06, -4.35, -4.96, -3.87, -2.61, -0.91, -0.06, -1.0, -2.31, -2.17, -2.26, -3.74, -4.3, -4.4, -5.27, -6.09, -6.92, -7.52, -9.03, -9.52, -10.08, -11.01, -10.95, -12.9, -14.45, -15.32, -16.5, None, 8.41, 7.19, 7.29, 6.05, 6.16, 7.36, 7.42, 6.9, 8.03, 8.69, 8.51, 8.99, 9.29, 8.41, None, 10.28, 9.32, 9.71, 10.26, 10.94, 11.23, None, 9.32, 9.07, 10.38, 10.55, 9.32, None, 11.89, 11.58, 10.74, 10.91, 11.89, None, 12.16, 11.31, 10.36, 10.84, 11.5, 11.79, 12.54, None, 13.07, 12.7, 13.43, None, 18.5, 18.48, 17.81, 16.26, 15.12, 14.22, 13.78, 13.0, 13.03, 13.19, 13.64, 14.27, 14.76, 14.97, 16.36, 17.6, 18.5, None, -6.82, -6.54, -5.14, -5.34, -6.2, -6.82, None, -5.48, -5.84, -6.32, -6.03, -5.44, -5.51, -5.0, -5.46, -4.76, -4.15, -4.87, None, -7.39, -9.1, -9.51, -9.87, -10.58, -10.39, -10.13, -8.94, -7.63, -8.25, -9.33, -9.12, -2.6, -3.86, -4.88, -6.08, -6.72, None, -4.5, -4.18, -3.46, -2.74, -2.78, -3.24, -3.98, None, 51.11, 52.09, 52.98, 53.76, 54.51, 54.68, 54.43, 54.33, 53.91, 53.09, 52.49, 51.58, 50.42, 49.48, 49.09, 49.33, 49.22, 49.44, 49.99, 50.36, 50.22, 50.7, 51.11, None, 18.51, 18.23, 17.98, 18.37, 18.51, None, 42.4, 42.28, 41.6, 40.66, 40.19, 39.76, 39.21, 38.61, 38.3, 37.8, 37.75, 37.75, 37.86, 38.11, 38.67, 39.39, 39.66, 40.57, 41.82, 41.47, 42.42, 42.4, None, 41.88, 42.28, 41.79, 41.88, 41.11, 40.18, 39.63, 38.37, 37.8, 37.1, 36.98, 37.65, 38.36, 39.39, 40.16, 41.18, 41.88, None, -22.25, -20.51, -19.34, -19.87, -20.73, -22.28, -22.36, -23.57, -24.0, -24.02, -25.16, -26.62, -27.55, -27.12, -25.16, -24.03, -22.25, None, 24.75, 26.01, 25.8, 24.63, 24.75, None, 47.88, 47.99, 47.74, 47.99, 48.22, 47.83, 46.81, 45.94, 45.3, 45.29, 44.82, 43.71, 44.18, 43.69, 43.9, 44.23, 44.58, 44.48, 45.18, 45.73, 46.32, 47.67, None, 50.75, 49.31, 46.84, 46.74, 46.81, 48.86, 50.95, 53.3, 54.23, 53.7, 51.76, None, 54.33, 54.43, 55.19, 54.86, 54.33, None, 66.58, 67.06, 65.98, 65.44, 64.25, 64.63, 65.36, 65.39, 66.11, 65.4, 68.96, 67.21, None, 70.83, 71.1, 70.83, None, 70.89, 71.52, 71.56, 71.13, None, 73.21, 73.32, 73.77, 73.48, None, 75.08, 74.78, 75.5, 75.08, None, 75.56, 74.85, 75.26, 76.14, 75.56, None, 70.72, 70.76, 71.47, 72.23, 73.63, 74.63, 75.61, 76.44, 76.94, 76.23, 75.26, 73.33, 71.54, None, 76.97, 76.72, 76.22, 75.33, 74.48, 74.04, 73.98, 73.59, 73.59, 72.97, 73.56, 73.04, 71.98, 70.79, 71.39, 71.35, 71.49, 72.85, 71.61, 71.03, 70.45, 69.44, 69.67, 69.58, 69.01, 70.1, 69.88, 68.96, 64.97, 64.61, 63.25, 62.57, 62.52, 61.65, 60.34, 60.57, 60.16, 59.87, 58.24, 57.62, 56.12, 54.86, 53.2, 51.94, 51.7, 55.38, 57.36, 58.06, 60.34, 62.55, 61.64, 61.77, 59.76, 58.88, 59.5, 59.16, 59.04, 54.73, 53.98, 54.25, 53.09, 51.24, 48.45, 46.31, 43.99, 42.81, 43.28, 42.22, 42.9, 44.11, 45.32, 46.12, 47.58, 48.18, 47.79, 49.44, 50.74, 51.78, 53.16, 53.43, 52.75, 51.96, 50.58, 49.51, 49.81, 50.25, 49.38, 49.29, 49.79, 50.41, 50.09, 51.26, 51.63, 51.01, 49.73, 50.01, 50.5, 50.33, 49.3, 49.83, 50.12, 50.89, 50.81, 50.86, 54.18, 53.55, 54.04, 54.13, 55.39, 54.6, 54.01, 52.98, 52.45, 51.27, 50.84, 51.06, 50.62, 51.72, 50.61, 50.45, 49.15, 47.72, 47.08, 46.4, 45.64, 43.66, 41.81, 41.15, 41.83, 42.09, 42.71, 42.74, 43.38, 43.43, 44.66, 45.4, 46.64, 47.26, 47.55, 47.9, 48.78, 49.6, 49.92, 50.23, 50.77, 51.26, 51.77, 52.24, 52.06, 52.74, 53.17, 53.35, 53.79, 54.16, 55.08, 55.79, 55.92, 56.76, 57.47, 58.72, 59.48, 60.5, 62.36, 63.55, 64.95, 66.94, 68.36, 69.16, 69.91, 69.06, 67.46, 66.27, 66.76, 65.9, 64.41, 63.85, 64.76, 64.52, 65.5, 66.42, 66.76, 67.95, 68.25, 67.57, 66.67, 67.52, 68.86, 68.2, 68.44, 68.88, 68.94, 69.85, 69.23, 68.62, 69.36, 69.93, 71.03, 72.84, 72.78, 71.41, 70.39, 68.41, 66.32, 66.53, 67.28, 68.33, 69.07, 70.63, 72.12, 72.85, 71.34, 71.87, 72.32, 72.58, 73.85, 73.94, 75.12, 75.64, 76.05, 75.92, 76.43, 77.29, 77.37, 76.97, None, 78.31, 79.23, 79.28, 78.31, None, 80.55, 80.34, 80.01, 80.56, 80.77, 80.51, 80.92, 80.55, None, 78.88, 79.04, 80.14, 81.02, 80.75, 78.88, None, -1.13, -2.29, -2.35, -2.84, -2.22, -1.34, -1.13, None, 27.12, 27.66, 27.4, 25.93, 23.28, 21.33, 21.0, 21.42, 21.86, 23.69, 26.03, 26.88, 26.86, 27.09, None, 16.35, 17.08, 17.83, 19.49, 20.34, 21.99, 23.69, 24.29, 25.08, 25.83, 27.38, 28.06, 28.96, 29.2, 29.87, 30.34, 31.51, 32.16, 31.19, 29.1, 28.53, 27.69, 27.11, 26.28, 25.61, 25.0, 24.56, 24.25, 23.0, 22.71, 20.0, 18.62, 17.12, 17.28, 17.33, 17.41, 17.58, 16.67, None, 9.46, 9.98, 10.72, 12.18, 12.02, 11.68, 10.53, 9.71, 10.08, 9.6, 9.4, 9.64, 9.55, 10.41, 9.81, 8.73, 8.67, 9.27, 10.09, 11.14, 11.68, 12.65, 12.96, 13.79, 14.33, 15.68, 19.58, 20.0, 22.0, 22.0, 20.84, 18.61, 18.0, 17.26, 16.29, 14.42, 12.58, 11.32, 10.63, 9.46, None, 9.46, 8.38, 7.78, 7.23, 6.59, 4.85, 3.79, 3.56, 3.51, 4.6, 4.46, 4.41, 5.55, 6.55, 7.5, 8.23, 8.73, 9.81, 10.41, 9.55, 9.64, 9.4, 9.6, 10.08, 9.71, 10.53, 11.68, 12.02, 12.18, 10.72, 9.98, 9.46, None, 13.59, 14.73, 15.62, 16.46, 16.59, 16.3, 15.3, 13.99, 13.14, 12.44, 12.47, 12.33, 12.59, 12.52, 12.38, 13.13, 13.28, 13.3, 13.51, 13.63, 13.88, 13.62, None, -10.48, -10.82, -10.45, None, -9.87, -9.79, -9.24, -9.61, None, -9.6, -8.92, -8.32, -9.6, None, -8.34, -8.11, -7.42, -7.56, -8.34, None, -7.35, -7.18, -6.6, -7.35, None, 6.79, 7.26, 8.16, 9.34, 9.84, 10.05, 9.69, 8.98, 8.35, 7.94, 7.11, None, 13.38, 13.16, 13.46, 13.74, 14.13, 14.36, 14.34, 13.98, 13.96, 13.79, None, 9.45, 8.0, 9.18, 10.02, 10.93, 11.28, 10.45, 10.7, 11.13, 11.38, 11.39, 9.97, None, 11.58, 12.02, 11.75, 10.64, 9.2, 6.8, 4.22, 2.05, 0.29, -1.45, -0.86, 3.92, 4.25, 5.0, 8.84, 9.97, 11.39, 11.43, None, 45.42, 44.77, 44.7, 44.41, 44.01, 43.21, 42.58, 42.32, 42.25, 42.44, 42.68, 42.91, 43.13, 43.22, 42.81, 43.11, 43.35, 43.57, 44.42, 44.86, 45.52, 46.17, 45.73, None, 5.97, 5.95, 5.76, 4.21, 3.19, 2.31, 2.42, 2.22, 1.82, 2.77, 3.33, 4.58, 5.07, None, 49.5, 49.57, 49.43, 49.47, 48.83, 48.32, 48.56, 48.2, 48.11, 47.88, 47.87, 48.47, 48.82, 48.9, 49.04, 49.32, 49.5, None, 46.51, 46.66, 46.85, 46.5, 45.83, 45.45, 45.63, 45.5, 46.02, None, 65.72, 64.41, 62.75, 60.64, 58.95, 57.04, 56.2, 55.36, 57.44, 59.43, 61.29, 63.13, 64.05, 64.79, 67.3, 68.01, 68.41, 69.11, 67.94, 66.01, None, 57.39, 56.18, 57.39, None, 57.96, 57.44, 57.37, 57.2, 56.93, 57.11, 57.39, 57.93, 57.99, 57.96, None, 63.82, 63.72, 63.59, 63.78, None, -26.73, -27.29, -26.4, -25.73, -25.84, -26.73, None, 33.38, 32.71, 32.87, 33.82, 34.59, 35.41, 36.04, 36.82, 36.9, 36.72, 37.07, 36.61, 35.63, 33.38, None, 12.86, 13.35, 14.37, 16.63, 19.96, 20.73, 21.31, 23.41, 19.58, 15.68, 14.33, 13.79, 12.96, 12.65, 11.68, 11.14, 10.57, 9.01, 8.98, 8.28, 7.51, 7.75, 7.42, 8.38, 8.97, 10.02, 9.99, 10.89, 12.22, None, 6.14, 6.28, 7.41, 8.68, 10.19, 11.02, 10.47, 9.83, 9.13, 6.14, None, 12.19, 12.63, 13.41, 10.85, 9.24, 8.3, 6.86, 6.22, 5.69, 6.64, 6.85, 7.91, 7.79, 8.97, 10.96, 12.8, 13.83, 15.12, 16.18, 17.57, 18.63, 19.75, 20.42, 19.51, 18.41, 18.11, 17.96, 18.24, 16.44, 14.72, 14.42, 13.39, None, 40.24, 40.1, 39.6, 39.43, 38.61, 37.99, 37.42, 37.05, 36.74, 37.91, 38.26, 38.14, 37.59, 37.15, 37.02, 38.16, 39.14, 39.53, 40.73, 40.5, 40.24, None, 35.65, 36.53, 37.52, 38.12, 37.96, 37.2, 38.95, 39.98, 40.88, 40.95, 42.12, 41.14, 42.12, 42.04, 41.31, 41.83, 42.75, 41.43, 41.27, 40.05, 38.89, 37.97, 37.39, 37.31, 36.31, 35.86, 35.27, None, -8.89, -8.43, -8.27, -8.67, -9.39, -8.89, None, 10.76, 10.86, 10.0, 10.37, None, 30.31, 32.51, 33.34, 34.66, 36.43, 37.35, 36.72, 36.9, 35.95, 34.83, 33.79, 33.29, 32.37, 31.76, 30.96, 30.31, None, 41.34, 41.1, 41.54, 41.09, 40.25, 39.71, 38.28, 37.17, 37.26, 37.23, 37.09, 36.71, 36.62, 36.26, 35.82, 36.65, 36.8, 36.11, 36.68, 36.14, 36.66, 38.21, 39.46, 40.46, 41.09, 42.02, 41.34, None, 40.69, 40.62, 40.94, 41.83, 42.01, 41.3, 41.0, None, 24.39, 21.97, 23.56, 25.3, 24.39, None, -0.95, -3.1, -4.68, -6.48, -7.1, -8.01, -9.11, -10.32, -11.29, -11.57, -11.72, -11.52, -9.69, -9.23, -8.76, -8.34, -6.52, -5.42, -4.45, -3.57, -3.03, -2.41, -1.7, -1.01, -0.95, None, -1.03, -1.13, -1.34, -0.21, 1.06, 1.85, 2.34, 3.78, 3.79, 4.25, 3.05, 1.18, 0.11, -1.03, None, 52.1, 52.29, 52.34, 51.57, 51.21, 50.58, 50.38, 49.93, 49.31, 48.23, 47.83, 47.1, 46.7, 46.27, 45.41, 45.11, 44.36, 45.03, 45.52, 46.08, 46.71, 46.03, 45.46, 45.49, 45.94, 46.44, 46.38, 46.42, 46.67, 47.35, 47.85, 48.16, 48.37, 48.22, 47.89, 47.98, 48.1, 48.15, 48.83, 49.03, 50.31, 50.71, 51.62, 51.91, 51.59, 51.43, 51.37, 51.32, 52.04, None, -30.22, -30.88, -31.49, -32.73, -33.77, -34.95, -34.86, -34.46, -33.26, -32.04, -30.22, None, 19.08, 19.06, 19.7, 19.98, 20.27, 20.08, 19.86, 19.45, 19.08, None, 20.64, 20.78, 20.93, 20.92, 20.64, None, 21.18, 21.1, 21.18, None, 21.32, 21.28, 21.54, 21.72, 21.32, None, 21.98, 22.07, 22.24, 21.98, None, 49.39, 48.67, 48.45, 48.27, 48.02, 47.94, 47.22, 46.64, 46.44, 46.51, 46.12, 45.99, 45.35, 43.57, 42.43, 41.98, 41.68, 42.21, 42.86, 43.27, 43.63, 43.63, 44.1, 45.0, 45.01, 45.31, 45.91, 47.45, 47.35, 45.7, 44.81, 43.98, 43.09, 42.34, 41.78, 41.92, 41.48, 41.32, 41.22, 41.12, 40.63, 40.75, 40.43, 38.94, 39.25, 38.96, 38.4, 37.22, 37.94, 39.15, 38.08, 37.92, 36.9, 35.55, 34.51, 33.86, 33.16, 32.03, 30.73, 29.18, 28.04, 26.21, 25.21, 25.2, 25.87, 27.5, 28.55, 29.94, 29.64, 30.15, 30.27, 30.32, 29.89, 29.29, 29.31, 29.15, 29.55, 29.71, 28.74, 27.83, 26.69, 25.87, 26.06, 26.84, 28.11, 29.38, 29.76, 29.27, 30.12, 31.08, 31.75, 31.34, 31.33, 32.53, 32.61, 33.05, 33.74, 34.08, 34.45, 35.16, 37.55, 38.11, 39.77, 41.14, 42.77, 44.62, 46.86, 48.18, 48.04, 47.36, 49.0, 49.0, 49.0, 49.0, 49.0, 49.0, 49.39, None, 57.12, 56.99, 57.82, 57.9, 57.12, None, 59.91, 59.94, 60.38, 59.91, None, 63.78, 63.69, 63.3, 62.98, 63.38, 63.41, None, 71.15, 70.89, 70.6, 70.53, 70.12, 70.15, 69.71, 60.31, 60.0, 58.91, 59.79, 58.86, 57.69, 55.92, 54.8, 55.5, 57.18, 58.19, 58.5, 59.73, 60.0, 60.88, 59.98, 59.71, 59.16, 60.73, 61.28, 60.06, 58.86, 57.73, 56.98, 55.99, 55.64, 55.02, 54.4, 55.04, 55.89, 56.42, 57.22, 58.33, 58.62, 58.42, 58.57, 58.67, 59.27, 59.99, 60.27, 61.07, 62.07, 63.15, 63.06, 63.46, 64.22, 64.79, 64.56, 64.56, 64.69, 65.67, 66.58, 66.08, 66.74, 67.62, 68.36, 68.92, 69.86, 70.45, 70.82, 71.15, None, 37.36, 38.4, 39.36, 41.08, 41.22, 42.22, 42.17, 41.32, 45.0, 45.5, 44.41, 43.65, 43.0, 41.99, 41.14, 40.67, 42.08, 42.17, 41.14, 40.87, 40.24, 40.5, 40.73, 39.53, 39.14, 38.16, 37.36, None, 11.78, 11.42, 10.45, 9.07, 9.86, 10.97, 11.85, 11.46, 10.89, 10.55, 10.2, 10.39, 10.7, 10.42, 9.87, 8.58, 8.37, 7.42, 6.86, 6.23, 5.2, 4.54, 4.01, 4.02, 4.06, 3.13, 2.41, 1.92, 1.33, 0.79, 1.25, 2.6, 3.32, 3.84, 5.22, 6.1, 6.15, 6.1, 7.09, 7.34, 7.63, 8.41, 9.09, 9.74, 10.82, 11.61, None, 21.55, 19.75, 18.0, 16.08, 13.43, 11.01, 9.53, 9.24, 10.49, 10.96, 12.34, 14.2, 15.91, 17.49, 19.27, 19.89, 20.77, 22.46, 22.7, 23.35, 22.79, 21.81, None, -16.47, -16.16, -16.47, None, -14.93, -15.61, -15.39, -14.93, None, 32.39, 31.49, 31.62, 31.87, 32.39, None, 16.65, 15.94, 15.18, 14.0, 14.01, 13.4, 13.29, 12.95, 12.72, 12.64, 13.77, 14.8, 15.26, 15.91, 16.67, 17.58, 17.41, 17.33, 17.28, 17.12, 18.62, 17.35, None, -29.26, -29.91, -31.14, -32.77, -33.61, -33.94, -33.99, -33.92, -34.26, -34.8, -34.46, -34.0, -33.87, -32.61, -31.66, -29.88, -28.58, -28.36, -28.86, -28.97, -24.77, -25.87, -26.83, -26.28, -25.5, -25.39, -25.72, -25.17, -24.62, -23.57, -22.09, -22.27, -22.25, -24.37, -25.84, -25.73, -26.4, -27.29, -26.73, -27.47, -28.75, None, -28.96, -28.85, -29.88, -30.55, -30.07, -29.26, None, -9.23, -10.53, -11.61, -12.78, -13.97, -15.51, -16.04, -16.47, -17.94, -17.85, -17.66, -17.35, -17.52, -16.08, -12.91, -12.19, -11.24, -10.95, -11.24, -11.78, -11.61, -12.27, -13.25, -12.18, -11.97, -10.79, -9.16, -8.41, -8.34, -8.76, -9.23, None, -22.25, -22.27, -22.09, -21.49, -20.5, -19.29, -18.54, -17.85, -17.94, -16.47, -16.04, -15.51, -15.86, -16.32, -16.71, -18.67, -19.72, -20.4, -22.25, None] \ No newline at end of file diff --git a/src/weather_model_graphs/visualise/plot_3d.py b/src/weather_model_graphs/visualise/plot_3d.py new file mode 100644 index 0000000..0dd2fb1 --- /dev/null +++ b/src/weather_model_graphs/visualise/plot_3d.py @@ -0,0 +1,560 @@ +""" +3D interactive graph visualisation using Plotly, with support for +flat and concentric spherical layouts. +""" + +from __future__ import annotations + +import warnings +from typing import Literal + +from .geo_data import COAST_LONS, COAST_LATS + +import networkx as nx +import numpy as np + +try: + import plotly.graph_objects as _go + + HAS_PLOTLY = True +except ImportError: + HAS_PLOTLY = False + + +DEFAULT_COMPONENT_COLORS: dict[str, str] = { + "g2m": "blue", + "m2m": "green", + "m2g": "red", + "unknown": "#9E9E9E", +} + +_GRID_MARKER = "circle" +_MESH_MARKER = "diamond" +_GRID_Z_FLAT = -1 # z‑coordinate for grid nodes in flat mode + +# Spherical layout defaults +_DEFAULT_SPHERE_RADIUS_BASE = 1.0 +_DEFAULT_SPHERE_RADIUS_STEP = 0.5 # additional radius per level +_GRID_RADIUS = 0.8 + + +def _lat_lon_to_cartesian( + lat: float, lon: float, radius: float +) -> tuple[float, float, float]: + """ + Convert latitude/longitude (degrees) to 3D Cartesian coordinates on a sphere of given radius. + + Parameters + ---------- + lat : float + Latitude in degrees. + lon : float + Longitude in degrees. + radius : float + Sphere radius. + + Returns + ------- + tuple[float, float, float] + (x, y, z) coordinates. + """ + lat_rad = np.radians(lat) + lon_rad = np.radians(lon) + x = radius * np.cos(lat_rad) * np.cos(lon_rad) + y = radius * np.cos(lat_rad) * np.sin(lon_rad) + z = radius * np.sin(lat_rad) + return x, y, z + +def _build_coastline_trace(radius: float) -> "_go.Scatter3d": + """Génère la trace des continents pour Plotly.""" + xs, ys, zs = [], [], [] + for lat, lon in zip(COAST_LATS, COAST_LONS): + if lat is None: + xs.append(None); ys.append(None); zs.append(None) + else: + # On appelle la fonction de conversion qui existe déjà juste au-dessus + x, y, z = _lat_lon_to_cartesian(lat, lon, radius) + xs.append(x); ys.append(y); zs.append(z) + + return _go.Scatter3d( + x=xs, y=ys, z=zs, + mode="lines", + name="coastlines", + line=dict(color="#424242", width=1), + opacity=0.4, + hoverinfo="none" + ) + +def _get_positions_flat( + graph: nx.DiGraph, +) -> tuple[np.ndarray, np.ndarray, np.ndarray, list]: + """ + Compute node positions using the flat layout (x=lon, y=lat, z=level). + + Grid nodes (no 'level' attribute) are placed at z = _GRID_Z_FLAT. + + Parameters + ---------- + graph : networkx.DiGraph + Graph with node attributes 'pos' (lat, lon) and optionally 'level'. + + Returns + ------- + tuple[np.ndarray, np.ndarray, np.ndarray, list] + (x, y, z, node_ids) arrays and the ordered node list. + """ + node_ids = list(graph.nodes()) + xs, ys, raw_levels = [], [], [] + + for node in node_ids: + attrs = graph.nodes[node] + pos = attrs["pos"] # (lat, lon) + xs.append(float(pos[1])) # x = longitude + ys.append(float(pos[0])) # y = latitude + raw_levels.append(attrs.get("level")) # None for grid nodes + + mesh_levels = [lvl for lvl in raw_levels if lvl is not None] + level_offset = min(mesh_levels) if mesh_levels else 0 + + zs = [] + for level in raw_levels: + if level is not None: + zs.append(float(level - level_offset)) + else: + zs.append(float(_GRID_Z_FLAT)) + + return np.array(xs), np.array(ys), np.array(zs), node_ids + + +def _get_positions_concentric( + graph: nx.DiGraph, + base_radius: float = _DEFAULT_SPHERE_RADIUS_BASE, + radius_step: float = _DEFAULT_SPHERE_RADIUS_STEP, +) -> tuple[np.ndarray, np.ndarray, np.ndarray, list]: + """ + Compute node positions using a concentric spherical layout. + + Each mesh level is placed on a sphere of radius = base_radius + (level - min_level) * step. + Grid nodes are placed on a sphere slightly smaller than the innermost mesh level. + + Parameters + ---------- + graph : networkx.DiGraph + Graph with node attributes 'pos' (lat, lon) and optionally 'level'. + base_radius : float, default=1.0 + Radius for the innermost mesh level. + radius_step : float, default=0.5 + Additional radius added per increasing mesh level. + + Returns + ------- + tuple[np.ndarray, np.ndarray, np.ndarray, list] + (x, y, z, node_ids) arrays and the ordered node list. + """ + node_ids = list(graph.nodes()) + + lats, lons, levels = [], [], [] + for node in node_ids: + attrs = graph.nodes[node] + pos = attrs["pos"] # (lat, lon) + lats.append(float(pos[0])) + lons.append(float(pos[1])) + levels.append(attrs.get("level")) + + mesh_levels = [lvl for lvl in levels if lvl is not None] + if not mesh_levels: + warnings.warn( + "No mesh nodes found in graph. Falling back to flat layout.", + UserWarning, + stacklevel=2, + ) + return _get_positions_flat(graph) + + min_level = min(mesh_levels) + + # Map each level to its sphere radius + radius_map = {} + for lvl in mesh_levels: + radius_map[lvl] = base_radius + (lvl - min_level) * radius_step + + xs, ys, zs = [], [], [] + for lat, lon, lvl in zip(lats, lons, levels): + if lvl is None: + # Grid node – place on a sphere slightly smaller than innermost mesh level + r = base_radius - radius_step * 0.5 + if r <= 0: + r = 0.5 + x, y, z = _lat_lon_to_cartesian(lat, lon, r) + else: + r = radius_map[lvl] + x, y, z = _lat_lon_to_cartesian(lat, lon, r) + xs.append(x) + ys.append(y) + zs.append(z) + + return np.array(xs), np.array(ys), np.array(zs), node_ids + + +def _node_id_to_index(node_ids: list) -> dict: + """ + Build a mapping from node identifier to its position in a list. + + Parameters + ---------- + node_ids : list + List of node identifiers. + + Returns + ------- + dict + Mapping node_id -> index. + """ + return {nid: i for i, nid in enumerate(node_ids)} + + +def _build_edge_traces( + graph: nx.DiGraph, + x_nodes: np.ndarray, + y_nodes: np.ndarray, + z_nodes: np.ndarray, + node_index: dict, + component_colors: dict[str, str], + edge_width: float, +) -> list: + """ + Create Plotly scatter traces for edges, one per component. + + Edges of the same component are batched into a single trace using None + separators to keep file size small. + + Parameters + ---------- + graph : networkx.DiGraph + Graph with edge attribute 'component'. + x_nodes, y_nodes, z_nodes : np.ndarray + Node position arrays. + node_index : dict + Mapping from node ID to index in position arrays. + component_colors : dict + Mapping component name to CSS color. + edge_width : float + Line width for edges. + + Returns + ------- + list + List of plotly.graph_objects.Scatter3d objects. + """ + component_edges: dict[str, list[tuple]] = {} + for u, v, attrs in graph.edges(data=True): + comp = attrs.get("component", "unknown") + component_edges.setdefault(comp, []).append((u, v)) + + traces = [] + for comp, edges in sorted(component_edges.items()): + ex, ey, ez = [], [], [] + for u, v in edges: + ui, vi = node_index[u], node_index[v] + ex.extend([x_nodes[ui], x_nodes[vi], None]) + ey.extend([y_nodes[ui], y_nodes[vi], None]) + ez.extend([z_nodes[ui], z_nodes[vi], None]) + + color = component_colors.get(comp, component_colors.get("unknown", "#9E9E9E")) + trace = _go.Scatter3d( + x=ex, + y=ey, + z=ez, + mode="lines", + name=comp, + line=dict(color=color, width=edge_width), + hoverinfo="none", + ) + traces.append(trace) + return traces + + +def _build_node_traces( + graph: nx.DiGraph, + x_nodes: np.ndarray, + y_nodes: np.ndarray, + z_nodes: np.ndarray, + node_ids: list, + node_size: float, +) -> list: + """ + Create Plotly scatter traces for nodes, separated by type (grid / mesh level). + + Parameters + ---------- + graph : networkx.DiGraph + Graph with node attributes 'pos' and optionally 'level'. + x_nodes, y_nodes, z_nodes : np.ndarray + Node position arrays. + node_ids : list + Node identifiers in the same order as position arrays. + node_size : float + Base marker size for mesh nodes (grid nodes slightly smaller). + + Returns + ------- + list + List of plotly.graph_objects.Scatter3d objects. + """ + groups: dict[str, dict] = {} + for i, node in enumerate(node_ids): + attrs = graph.nodes[node] + pos = attrs["pos"] + + if "level" not in attrs or attrs["level"] is None: + key = "grid" + symbol = _GRID_MARKER + label = "grid" + else: + level = int(attrs["level"]) + key = f"mesh_level_{level}" + symbol = _MESH_MARKER + label = f"mesh level {level}" + + if key not in groups: + groups[key] = { + "x": [], + "y": [], + "z": [], + "text": [], + "symbol": symbol, + "label": label, + } + + hover = f"node: {node}
pos: ({pos[0]:.3f}, {pos[1]:.3f})
{label}" + groups[key]["x"].append(x_nodes[i]) + groups[key]["y"].append(y_nodes[i]) + groups[key]["z"].append(z_nodes[i]) + groups[key]["text"].append(hover) + + # Color palette for mesh levels + mesh_palette = [ + "#E91E63", + "#9C27B0", + "#673AB7", + "#3F51B5", + "#00BCD4", + "#009688", + "#8BC34A", + "#FF9800", + ] + mesh_level_keys = sorted(k for k in groups if k.startswith("mesh_level_")) + level_colors = { + k: mesh_palette[i % len(mesh_palette)] for i, k in enumerate(mesh_level_keys) + } + + traces = [] + # Grid nodes first + if "grid" in groups: + g = groups["grid"] + traces.append( + _go.Scatter3d( + x=g["x"], + y=g["y"], + z=g["z"], + mode="markers", + name="grid", + marker=dict( + size=node_size * 0.7, + color="#78909C", + symbol=g["symbol"], + opacity=0.6, + ), + text=g["text"], + hoverinfo="text", + ) + ) + + # Mesh nodes, ordered by level + for key in mesh_level_keys: + g = groups[key] + traces.append( + _go.Scatter3d( + x=g["x"], + y=g["y"], + z=g["z"], + mode="markers", + name=g["label"], + marker=dict( + size=node_size, + color=level_colors[key], + symbol=g["symbol"], + opacity=0.9, + line=dict(width=0.5, color="white"), + ), + text=g["text"], + hoverinfo="text", + ) + ) + return traces + + +def _build_layout( + title: str | None, + layout_type: Literal["flat", "concentric"], +) -> "_go.Layout": + """ + Create a Plotly layout with appropriate axis labels for the chosen layout. + + Parameters + ---------- + title : str or None + Figure title. + layout_type : {"flat", "concentric"} + Layout style. + + Returns + ------- + plotly.graph_objects.Layout + Configured layout object. + """ + axis_style = dict( + backgroundcolor="white", + gridcolor="#E0E0E0", + showbackground=True, + zerolinecolor="#BDBDBD", + tickfont=dict(size=10), + ) + if layout_type == "flat": + scene = dict( + xaxis=dict(title="x (longitude)", **axis_style), + yaxis=dict(title="y (latitude)", **axis_style), + zaxis=dict(title="level", **axis_style), + aspectmode="data", + ) + else: # concentric + scene = dict( + xaxis=dict(title="x", **axis_style), + yaxis=dict(title="y", **axis_style), + zaxis=dict(title="z", **axis_style), + aspectmode="data", + ) + return _go.Layout( + title=dict(text=title or "Weather Model Graph (3D)", x=0.5), + scene=scene, + legend=dict(title=dict(text="component / node kind"), itemsizing="constant"), + margin=dict(l=0, r=0, b=0, t=50), + paper_bgcolor="white", + ) + + +def render_with_plotly( + graph: nx.DiGraph, + *, + show: bool = True, + title: str | None = None, + node_size: float = 4.0, + edge_width: float = 1.5, + component_colors: dict[str, str] | None = None, + layout: Literal["flat", "concentric"] = "flat", + add_coastlines: bool = False, + sphere_base_radius: float = _DEFAULT_SPHERE_RADIUS_BASE, + sphere_radius_step: float = _DEFAULT_SPHERE_RADIUS_STEP, +) -> "_go.Figure": + """ + Render a weather-model-graphs networkx.DiGraph in 3D using Plotly. + + Node positions are taken from the 'pos' node attribute (latitude, longitude). + Mesh nodes may have an integer 'level' attribute used for layering. + Grid nodes (without 'level') are placed at the bottom in flat layout, + or on an inner sphere in concentric layout. + + Parameters + ---------- + graph : networkx.DiGraph + Graph with 'pos' attribute on all nodes; optionally 'level' on mesh nodes. + show : bool, default=True + If True, call fig.show() before returning. + title : str or None, optional + Figure title. Default: "Weather Model Graph (3D)". + node_size : float, default=4.0 + Marker size for mesh nodes. Grid nodes are slightly smaller. + edge_width : float, default=1.5 + Line width for edges. + component_colors : dict or None, optional + Mapping from edge component name to CSS color. Missing components fall back + to DEFAULT_COMPONENT_COLORS. Pass an empty dict to use all defaults. + layout : {"flat", "concentric"}, default="flat" + - "flat" : x = longitude, y = latitude, z = level (grid at -1). + - "concentric" : nodes placed on concentric spheres; mesh level N on a sphere + of radius = base_radius + (N - min_level) * step. Grid nodes on a sphere + slightly smaller than the innermost mesh sphere. + sphere_base_radius : float, default=1.0 + Radius for the innermost mesh level (used only in concentric layout). + sphere_radius_step : float, default=0.5 + Additional radius added per increasing mesh level (concentric layout). + + Returns + ------- + plotly.graph_objects.Figure + Interactive 3D figure. + """ + if not HAS_PLOTLY: + raise ImportError( + "plotly is required for 3D visualisation but is not installed.\n" + "Install it with: pip install plotly\n" + "or: pip install weather-model-graphs[visualisation]" + ) + + if graph.number_of_nodes() == 0: + raise ValueError("Cannot render an empty graph (no nodes).") + + missing_pos = [n for n in graph.nodes() if "pos" not in graph.nodes[n]] + if missing_pos: + raise ValueError( + f"{len(missing_pos)} node(s) are missing the required 'pos' attribute. " + f"First offending node: {missing_pos[0]!r}" + ) + + colors = {**DEFAULT_COMPONENT_COLORS, **(component_colors or {})} + + if layout == "concentric": + x_nodes, y_nodes, z_nodes, node_ids = _get_positions_concentric( + graph, + base_radius=sphere_base_radius, + radius_step=sphere_radius_step, + ) + else: # flat + x_nodes, y_nodes, z_nodes, node_ids = _get_positions_flat(graph) + + node_index = _node_id_to_index(node_ids) + + traces = [] + if add_coastlines: + # Coastlines are added at the top of the figure + traces.append(_build_coastline_trace(radius=0.99)) + if graph.number_of_edges() > 0: + edge_traces = _build_edge_traces( + graph=graph, + x_nodes=x_nodes, + y_nodes=y_nodes, + z_nodes=z_nodes, + node_index=node_index, + component_colors=colors, + edge_width=edge_width, + ) + traces.extend(edge_traces) + else: + warnings.warn( + "Graph has no edges; rendering node positions only.", stacklevel=2 + ) + + node_traces = _build_node_traces( + graph=graph, + x_nodes=x_nodes, + y_nodes=y_nodes, + z_nodes=z_nodes, + node_ids=node_ids, + node_size=node_size, + ) + traces.extend(node_traces) + + fig = _go.Figure(data=traces, layout=_build_layout(title, layout)) + + if show: + fig.show() + return fig \ No newline at end of file From 423e2aa64c74eb1b169ca19df2e23c63b61073c8 Mon Sep 17 00:00:00 2001 From: Prince Date: Mon, 30 Mar 2026 18:36:23 +0000 Subject: [PATCH 2/2] feat: add optional coastline layer to 3D visualization --- CHANGELOG.md | 12 ++ pyproject.toml | 1 + tests/test_graph_plot_3d.py | 292 ++++++++++++++++++++++++++++++++++++ 3 files changed, 305 insertions(+) create mode 100644 tests/test_graph_plot_3d.py diff --git a/CHANGELOG.md b/CHANGELOG.md index e036489..d51bb03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add `__version__` attribute to the package init [\#56](https://github.com/mllam/weather-model-graphs/pull/56) @AdMub + +- Add 3D interactive graph visualisation via `wmg.visualise.render_with_plotly`, + + rendering node positions (x, y) with mesh `level` mapped to the z-axis and + grid nodes placed at z = -1. Edges are batched per component (`g2m`, `m2m`, + `m2g`) into single `Scatter3d` traces with `None` separators, keeping HTML + output small for large graphs. `plotly` is an optional dependency installable + via `pip install weather-model-graphs[visualisation]`. + + [\#118](https://github.com/mllam/weather-model-graphs/pull/118), @yuvraajnarula + + ## [v0.3.0](https://github.com/mllam/weather-model-graphs/releases/tag/v0.3.0) diff --git a/pyproject.toml b/pyproject.toml index 01eb298..ade7f20 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,6 +24,7 @@ visualisation = [ "matplotlib>=3.8.4", "ipykernel>=6.29.4", "cartopy>=0.24.1", + "plotly>=5.0.0", ] docs = [ "jupyter-book>=1.0.0", diff --git a/tests/test_graph_plot_3d.py b/tests/test_graph_plot_3d.py new file mode 100644 index 0000000..608d9a9 --- /dev/null +++ b/tests/test_graph_plot_3d.py @@ -0,0 +1,292 @@ +""" +Tests for weather_model_graphs.visualise.plot_3d.render_with_plotly. + +These tests follow the same conventions as tests/test_graph_plots.py and are +designed to run without a display (``show=False`` is always passed). +""" + +import warnings + +import networkx as nx +import numpy as np +import pytest + +import weather_model_graphs as wmg +from weather_model_graphs.visualise.plot_3d import ( + DEFAULT_COMPONENT_COLORS, + render_with_plotly, +) + +pytest.importorskip("plotly", reason="plotly not installed skipping 3D plot tests") + + +def _make_xy(n: int = 15) -> np.ndarray: + """Return an (n*n, 2) array of evenly-spaced 2-D coordinates.""" + lin = np.linspace(0, 10, n) + xx, yy = np.meshgrid(lin, lin) + return np.stack([xx.ravel(), yy.ravel()], axis=1) + + +@pytest.fixture +def xy(): + return _make_xy(15) # 15x15 = 225 points for better hierarchical level creation + + +@pytest.fixture +def flat_graph(xy): + return wmg.create.create_all_graph_components( + coords=xy, + m2m_connectivity="flat", + m2m_connectivity_kwargs=dict(mesh_node_distance=3), + g2m_connectivity="nearest_neighbour", + m2g_connectivity="nearest_neighbour", + ) + + +@pytest.fixture +def multiscale_graph(xy): + return wmg.create.create_all_graph_components( + coords=xy, + m2m_connectivity="flat_multiscale", + m2m_connectivity_kwargs=dict( + mesh_node_distance=1, + level_refinement_factor=3, + max_num_levels=2, + ), + g2m_connectivity="nearest_neighbour", + m2g_connectivity="nearest_neighbour", + ) + + +@pytest.fixture +def hierarchical_graph(xy): + return wmg.create.create_all_graph_components( + coords=xy, + m2m_connectivity="hierarchical", + m2m_connectivity_kwargs=dict( + mesh_node_distance=1, + level_refinement_factor=3, + max_num_levels=2, + ), + g2m_connectivity="nearest_neighbour", + m2g_connectivity="nearest_neighbour", + ) + + +def _trace_names(fig) -> set[str]: + """Return the set of trace names present in a Plotly figure.""" + return {t.name for t in fig.data} + + +class TestRenderSmoke: + """render_with_plotly returns a Figure without raising for valid graphs.""" + + def test_flat_graph_returns_figure(self, flat_graph): + import plotly.graph_objects as go + + fig = render_with_plotly(flat_graph, show=False) + assert isinstance(fig, go.Figure) + + def test_multiscale_graph_returns_figure(self, multiscale_graph): + import plotly.graph_objects as go + + fig = render_with_plotly(multiscale_graph, show=False) + assert isinstance(fig, go.Figure) + + def test_hierarchical_graph_returns_figure(self, hierarchical_graph): + import plotly.graph_objects as go + + fig = render_with_plotly(hierarchical_graph, show=False) + assert isinstance(fig, go.Figure) + + def test_concentric_layout_works(self, flat_graph): + """Smoke test for concentric layout.""" + fig = render_with_plotly(flat_graph, show=False, layout="concentric") + assert fig is not None + + def test_show_false_does_not_raise(self, flat_graph): + """Passing show=False must not attempt to open a browser.""" + fig = render_with_plotly(flat_graph, show=False) + assert fig is not None + + +class TestTraceStructure: + """Figure must contain the expected component and node-kind traces.""" + + def test_component_traces_present(self, flat_graph): + fig = render_with_plotly(flat_graph, show=False) + names = _trace_names(fig) + # All three standard components must appear as edge traces + assert "g2m" in names + assert "m2m" in names + assert "m2g" in names + + def test_grid_node_trace_present(self, flat_graph): + fig = render_with_plotly(flat_graph, show=False) + assert "grid" in _trace_names(fig) + + def test_mesh_node_traces_present(self, flat_graph): + fig = render_with_plotly(flat_graph, show=False) + mesh_traces = [n for n in _trace_names(fig) if n.startswith("mesh level")] + assert len(mesh_traces) >= 1 + + def test_hierarchical_has_multiple_mesh_levels(self, hierarchical_graph): + fig = render_with_plotly(hierarchical_graph, show=False) + mesh_traces = [n for n in _trace_names(fig) if n.startswith("mesh level")] + # Hierarchical graphs should have at least 2 mesh levels + assert len(mesh_traces) >= 2, ( + f"Expected at least 2 mesh levels for hierarchical graph, " + f"but found {len(mesh_traces)} levels: {mesh_traces}" + ) + + def test_no_duplicate_trace_names_per_type(self, flat_graph): + """Each component name should appear exactly once as an edge trace.""" + fig = render_with_plotly(flat_graph, show=False) + names = [t.name for t in fig.data] + for comp in ("g2m", "m2m", "m2g"): + assert ( + names.count(comp) == 1 + ), f"Expected exactly 1 trace named '{comp}', got {names.count(comp)}" + + +class TestZAxis: + """Grid nodes must sit at z = -1 in flat layout; concentric layout uses spheres.""" + + def test_grid_nodes_at_correct_z_flat(self, flat_graph): + # We'll test by rendering and checking that the grid trace has z = -1 + # But easier: extract coordinates via the internal _get_positions_flat? + # We'll test by checking that for flat layout, grid nodes have z = -1. + # We can use the fact that the grid trace is named "grid". + fig = render_with_plotly(flat_graph, show=False, layout="flat") + grid_trace = next(t for t in fig.data if t.name == "grid") + # All grid nodes should have the same z coordinate = -1 + assert all( + z == -1 for z in grid_trace.z + ), "Grid nodes in flat layout should have z = -1" + + def test_mesh_nodes_have_non_negative_z_flat(self, flat_graph): + fig = render_with_plotly(flat_graph, show=False, layout="flat") + mesh_traces = [t for t in fig.data if t.name.startswith("mesh level")] + for trace in mesh_traces: + assert all( + z >= 0 for z in trace.z + ), f"Mesh trace {trace.name} has negative z" + + def test_concentric_layout_has_non_negative_z(self, flat_graph): + # In concentric layout, z values are coordinates on spheres, can be positive or negative. + # We just check that the figure is created. + fig = render_with_plotly(flat_graph, show=False, layout="concentric") + assert fig is not None + + +class TestEdgeBatching: + """Edge traces must use None separators — not one trace per edge.""" + + def test_edge_traces_use_none_separators(self, flat_graph): + fig = render_with_plotly(flat_graph, show=False) + edge_trace_names = {"g2m", "m2m", "m2g"} + for trace in fig.data: + if trace.name in edge_trace_names: + assert None in list( + trace.x + ), f"Trace '{trace.name}' should use None separators in x-coords" + + def test_number_of_edge_traces_equals_components(self, flat_graph): + """There should be one edge trace per component, not one per edge.""" + fig = render_with_plotly(flat_graph, show=False) + edge_traces = [t for t in fig.data if t.name in {"g2m", "m2m", "m2g"}] + # flat graph has exactly g2m, m2m, m2g — three traces total + assert len(edge_traces) == 3 + + +class TestComponentDict: + """render_with_plotly should work on individual sub-graphs too.""" + + def test_render_each_component_separately(self, xy): + components = wmg.create.create_all_graph_components( + coords=xy, + m2m_connectivity="flat", + m2m_connectivity_kwargs=dict(mesh_node_distance=3), + g2m_connectivity="nearest_neighbour", + m2g_connectivity="nearest_neighbour", + return_components=True, + ) + import plotly.graph_objects as go + + for name, subgraph in components.items(): + fig = render_with_plotly(subgraph, show=False, title=name) + assert isinstance(fig, go.Figure), f"Expected Figure for component '{name}'" + + +class TestParameters: + def test_custom_title_appears_in_layout(self, flat_graph): + fig = render_with_plotly(flat_graph, show=False, title="My Custom Title") + assert "My Custom Title" in fig.layout.title.text + + def test_default_title_used_when_none(self, flat_graph): + fig = render_with_plotly(flat_graph, show=False) + assert fig.layout.title.text # not empty + + def test_custom_component_colors_applied(self, flat_graph): + custom = {"g2m": "#FF0000"} + fig = render_with_plotly(flat_graph, show=False, component_colors=custom) + g2m_trace = next(t for t in fig.data if t.name == "g2m") + assert g2m_trace.line.color == "#FF0000" + + def test_default_colors_used_for_unspecified_components(self, flat_graph): + custom = {"g2m": "#FF0000"} # only override g2m + fig = render_with_plotly(flat_graph, show=False, component_colors=custom) + m2m_trace = next(t for t in fig.data if t.name == "m2m") + assert m2m_trace.line.color == DEFAULT_COMPONENT_COLORS["m2m"] + + def test_node_size_accepted(self, flat_graph): + """node_size parameter must not raise.""" + fig = render_with_plotly(flat_graph, show=False, node_size=8.0) + assert fig is not None + + def test_edge_width_accepted(self, flat_graph): + """edge_width parameter must not raise.""" + fig = render_with_plotly(flat_graph, show=False, edge_width=3.0) + assert fig is not None + + def test_layout_parameter_accepted(self, flat_graph): + """layout parameter must not raise.""" + fig = render_with_plotly(flat_graph, show=False, layout="concentric") + assert fig is not None + fig2 = render_with_plotly(flat_graph, show=False, layout="flat") + assert fig2 is not None + + +class TestErrorHandling: + def test_empty_graph_raises_value_error(self): + empty = nx.DiGraph() + with pytest.raises(ValueError, match="empty graph"): + render_with_plotly(empty, show=False) + + def test_missing_pos_raises_value_error(self): + g = nx.DiGraph() + g.add_node(0) # no pos attribute + g.add_node(1, pos=np.array([1.0, 2.0])) + with pytest.raises(ValueError, match="'pos'"): + render_with_plotly(g, show=False) + + def test_no_edges_emits_warning(self): + """A node-only graph should warn but still render.""" + g = nx.DiGraph() + g.add_node(0, pos=np.array([0.0, 0.0])) + g.add_node(1, pos=np.array([1.0, 1.0])) + with warnings.catch_warnings(record=True) as caught: + warnings.simplefilter("always") + fig = render_with_plotly(g, show=False) + assert any("no edges" in str(w.message).lower() for w in caught) + assert fig is not None + + +class TestPublicConstants: + def test_default_colors_has_standard_keys(self): + for key in ("g2m", "m2m", "m2g"): + assert key in DEFAULT_COMPONENT_COLORS + + def test_default_colors_are_strings(self): + for v in DEFAULT_COMPONENT_COLORS.values(): + assert isinstance(v, str) \ No newline at end of file