Metadata-Version: 2.1
Name: hockey-rink
Version: 0.1.1
Summary: A Python library for plotting hockey rinks with Matplotlib.
Home-page: https://github.com/the-bucketless/hockey_rink
Author: The Bucketless
Author-email: thebucketless@protonmail.com
License: GNU General Public License v3 (GPLv3)
Description: # Hockey Rink
        
        ![](examples/circular-rink.png)
        
        A Python library for plotting hockey rinks with Matplotlib.
        
        ## Installation
        ```pip install hockey_rink```
        
        ## Current Rinks
        The following shows the custom rinks currently available for plotting.
        
        ```
        from hockey_rink import NHLRink, IIHFRink, NWHLRink
        import matplotlib.pyplot as plt
        
        fig, axs = plt.subplots(1, 3, sharey=True, figsize=(12, 6), gridspec_kw={"width_ratios": [1, 98.4/85, 1]})
        nhl_rink = NHLRink(rotation=90)
        iihf_rink = IIHFRink(rotation=90)
        nwhl_rink = NWHLRink(rotation=90)
        axs[0] = nhl_rink.draw(ax=axs[0])
        axs[1] = iihf_rink.draw(ax=axs[1])
        axs[2] = nwhl_rink.draw(ax=axs[2])
        ```
        
        ![](examples/rinks.png)
        
        The NWHL logo comes from [the NWHL site](https://www.nwhl.zone/news/nwhl-unveils-isobel-cup-logo-for-2021-season).
        
        ## Customization
        There is also room for customization.  The image at the top was created as follows:  
          
        ```rink = Rink(rotation=45, boards={"length": 150, "width": 150, "radius": 75})```
        
        Rinks also allow for additional features to be added.  Custom features should inherit from RinkFeature and
        override the _get_centered_xy method.  The draw method can also be overridden if the desired feature can't be drawn
        with a matplotlib Polygon, though _get_centered_xy should still provide the feature's boundaries.  CircularImage
        provides an example of this by inheriting from RinkCircle.
        
        If a custom feature is to be constrained to only display within the rink, the returned object needs to have a 
        set_clip_path method.
        
        ## Plots
        There are currently wrappers available for the following Matplotlib plots:  
            - plot  
            - scatter  
            - arrow  
            - hexbin  
            - pcolormesh (heatmap in Hockey Rink)  
            - contour  
            - contourf  
            
        If you'd like to bypass the wrappers, you can convert coordinates to the proper scale with convert_xy:  
          
        ```
        rink = Rink()
        x, y = rink.convert_xy(x, y)
        ```
        
        When plotting to a partially drawn surface, the plot will be applied to the entire rink, not what's visible.  This can
        be avoided by setting plot_range (or plot_xlim and plot_ylim) in the plotting functions where they're available.
        
        It's also important to realize that the plotting functions only allow arguments to be passed without keywords for the
        coordinates.  
        ie) ```hexbin(x, y, values)``` will throw an error.
        
        The correct call is ```hexbin(x, y, values=values)```
        
        ## Examples
        
        Let's look at some NWHL data via the [Big Data Cup](https://www.stathletes.com/big-data-cup/).
        
        The first game is Minnesota vs Boston, so we'll go with that and do a scatter plot of each team's shots.
        
        ```
        from hockey_rink import NWHLRink
        import pandas as pd
        
        df = pd.read_csv("https://raw.githubusercontent.com/bigdatacup/Big-Data-Cup-2021/main/hackathon_nwhl.csv")
        game_df = df.loc[(df["Home Team"] == "Minnesota Whitecaps") & (df["Away Team"] == "Boston Pride")]
        shots = game_df.loc[(game_df.Event.isin(["Shot", "Goal"]))]
        boston_shots = shots[shots.Team == "Boston Pride"]
        minnesota_shots = shots[shots.Team == "Minnesota Whitecaps"]
        rink = NWHLRink(x_shift=100, y_shift=42.5)
        ax = rink.draw()
        rink.scatter(boston_shots["X Coordinate"], boston_shots["Y Coordinate"])
        rink.scatter(200 - minnesota_shots["X Coordinate"], 85 - minnesota_shots["Y Coordinate"])
        ```
        
        ![](examples/nwhl-shots.png)
        
        Extending the example, let's look at all of Boston's passes.
        
        ```
        boston_passes = game_df.loc[(game_df.Team == "Boston Pride") & (game_df.Event == "Play")]
        ax.clear()
        rink.draw()
        arrows = rink.arrow(boston_passes["X Coordinate"], boston_passes["Y Coordinate"], 
                            boston_passes["X Coordinate 2"], boston_passes["Y Coordinate 2"], color="yellow")
        ```
        
        ![](examples/boston-passes.png)
        
        For some of the other plots, let's look at some NHL shooting percentages.
        
        To mix things up a little, binsize will take different values in each plot and the heatmap won't include shots from
        below the goal line.  We'll also throw in a colorbar for the contour plot.
        ```
        from hockey_rink import NHLRink
        import matplotlib.pyplot as plt
        import pandas as pd
        
        pbp = pd.read_csv("https://hockey-data.harryshomer.com/pbp/nhl_pbp20192020.csv.gz", compression="gzip")
        pbp["goal"] = (pbp.Event == "GOAL").astype(int)
        pbp["x"] = np.abs(pbp.xC)
        pbp["y"] = pbp.yC * np.sign(pbp.xC)
        shots = pbp.loc[(pbp.Ev_Zone == "Off") & ~pbp.x.isna() & ~pbp.y.isna() & (pbp.Event.isin(["GOAL", "SHOT", "MISS"]))]
        
        fig, axs = plt.subplots(1, 3, figsize=(14, 8))
        rink = NHLRink(rotation=270)
        for i in range(3):
            rink.draw(ax=axs[i], display_range="ozone")
        contour_img = rink.contourf(shots.x, shots.y, values=shots.goal, ax=axs[0], cmap="bwr", 
                                    plot_range="ozone", binsize=10, levels=50, statistic="mean")
        plt.colorbar(contour_img, ax=axs[0], orientation="horizontal")
        rink.heatmap(shots.x, shots.y, values=shots.goal, ax=axs[1], cmap="magma",
                     plot_xlim=(25, 89), statistic="mean", vmax=0.2, binsize=3)
        rink.hexbin(shots.x, shots.y, values=shots.goal, ax=axs[2], binsize=(8, 12), plot_range="ozone", zorder=25, alpha=0.85)
        ```
        
        ![](examples/shooting-pct.png)
        
        ## Inspiration
        This project was partly inspired by [mplsoccer](https://github.com/andrewRowlinson/mplsoccer).
        
        Hopefully, it can lower a barrier for someone looking to get involved in hockey analytics.
        
        ## Contact
        You can find me on twitter [@the_bucketless](https://twitter.com/the_bucketless) or email me at thebucketless@protonmail.com if you'd like to get in touch.
        
Platform: UNKNOWN
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: Matplotlib
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Programming Language :: Python :: 3.6
Description-Content-Type: text/markdown
