quicklooks 0.0.11__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. quicklooks-0.0.11/LICENSE +21 -0
  2. quicklooks-0.0.11/MANIFEST.in +1 -0
  3. quicklooks-0.0.11/PKG-INFO +44 -0
  4. quicklooks-0.0.11/README.md +21 -0
  5. quicklooks-0.0.11/quicklooks/__init__.py +28 -0
  6. quicklooks-0.0.11/quicklooks/bar_plot.py +127 -0
  7. quicklooks-0.0.11/quicklooks/chart_skeleton.py +260 -0
  8. quicklooks-0.0.11/quicklooks/cs_attributes.py +115 -0
  9. quicklooks-0.0.11/quicklooks/dist_plot.py +140 -0
  10. quicklooks-0.0.11/quicklooks/fonts/lato/text.ttf +0 -0
  11. quicklooks-0.0.11/quicklooks/fonts/lato/title.ttf +0 -0
  12. quicklooks-0.0.11/quicklooks/fonts/montserrat/text.ttf +0 -0
  13. quicklooks-0.0.11/quicklooks/fonts/montserrat/title.ttf +0 -0
  14. quicklooks-0.0.11/quicklooks/fonts/oswald/text.ttf +0 -0
  15. quicklooks-0.0.11/quicklooks/fonts/oswald/title.ttf +0 -0
  16. quicklooks-0.0.11/quicklooks/fonts/roboto/text.ttf +0 -0
  17. quicklooks-0.0.11/quicklooks/fonts/roboto/title.ttf +0 -0
  18. quicklooks-0.0.11/quicklooks/fonts/rubik/text.ttf +0 -0
  19. quicklooks-0.0.11/quicklooks/fonts/rubik/title.ttf +0 -0
  20. quicklooks-0.0.11/quicklooks/fonts/source_sans/text.ttf +0 -0
  21. quicklooks-0.0.11/quicklooks/fonts/source_sans/title.ttf +0 -0
  22. quicklooks-0.0.11/quicklooks/fonts/work_sans/text.ttf +0 -0
  23. quicklooks-0.0.11/quicklooks/fonts/work_sans/title.ttf +0 -0
  24. quicklooks-0.0.11/quicklooks/legend.py +49 -0
  25. quicklooks-0.0.11/quicklooks/line_plot.py +144 -0
  26. quicklooks-0.0.11/quicklooks/plot_and_text_styling.py +214 -0
  27. quicklooks-0.0.11/quicklooks/reference_line.py +91 -0
  28. quicklooks-0.0.11/quicklooks/save_chart.py +19 -0
  29. quicklooks-0.0.11/quicklooks/scatter_plot.py +108 -0
  30. quicklooks-0.0.11/quicklooks/templates.py +39 -0
  31. quicklooks-0.0.11/quicklooks/text.py +64 -0
  32. quicklooks-0.0.11/quicklooks.egg-info/PKG-INFO +44 -0
  33. quicklooks-0.0.11/quicklooks.egg-info/SOURCES.txt +36 -0
  34. quicklooks-0.0.11/quicklooks.egg-info/dependency_links.txt +1 -0
  35. quicklooks-0.0.11/quicklooks.egg-info/requires.txt +5 -0
  36. quicklooks-0.0.11/quicklooks.egg-info/top_level.txt +1 -0
  37. quicklooks-0.0.11/setup.cfg +4 -0
  38. quicklooks-0.0.11/setup.py +35 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Alex Breslav
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ recursive-include quicklooks/fonts *
@@ -0,0 +1,44 @@
1
+ Metadata-Version: 2.1
2
+ Name: quicklooks
3
+ Version: 0.0.11
4
+ Summary: quicklook is a Python package for visualizing data quickly using matplotlib.
5
+ Home-page: https://www.linkedin.com/in/alexanderbreslav/
6
+ Author: Alex Breslav
7
+ Author-email: alexdsbreslav@gmail.com
8
+ License: MIT
9
+ Keywords: matplotlib,data-visualization,python
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3.9
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: numpy
19
+ Requires-Dist: matplotlib
20
+ Requires-Dist: pandas
21
+ Requires-Dist: datetime
22
+ Requires-Dist: seaborn
23
+
24
+ ![example_plot](https://github.com/alexdsbreslav/quicklook/assets/21344372/1eb05d0b-5712-4bda-8500-78a5aa76f110)
25
+
26
+ # quicklooks
27
+ quicklook is a Python package for visualizing data quickly.
28
+ Check out the documentation by clicking [here](https://github.com/alexdsbreslav/quicklook/tree/master/how_to_use_quicklook) or by navigating to the folder `how_to_use_quicklook`.
29
+
30
+ ## Why quicklooks?
31
+ Creating attractive, ready-to-share data visualizations takes forever. quickook is a cut-and-paste Python package that does the design work for you and makes it easy to create beautifuly simple data visualizations.
32
+
33
+ ## Who is quicklooks best for?
34
+ quicklook is for any data scientist, product manager, or researcher that knows a little bit of Python and is analyzing their data in a Jupyter Notebook. My goal in writing quicklook was to make data viz more efficient, but in the process, I've also created a package that is easy to use for beginners.
35
+
36
+ ## To install...
37
+ Directions to come; I am currently overhauling the package and will upload to pip for easy installation.
38
+
39
+ ## Documentation
40
+ The [documentation is here](https://github.com/alexdsbreslav/quicklook/tree/master/how_to_use_quicklook).
41
+
42
+ ## Acknowledgments
43
+ quicklook is built using [Matplotlib](https://matplotlib.org/), [NumPy](https://numpy.org/), [Pandas](https://pandas.pydata.org/), [Coolors](https://coolors.co/), and [seaborn](https://seaborn.pydata.org/).
44
+
@@ -0,0 +1,21 @@
1
+ ![example_plot](https://github.com/alexdsbreslav/quicklook/assets/21344372/1eb05d0b-5712-4bda-8500-78a5aa76f110)
2
+
3
+ # quicklooks
4
+ quicklook is a Python package for visualizing data quickly.
5
+ Check out the documentation by clicking [here](https://github.com/alexdsbreslav/quicklook/tree/master/how_to_use_quicklook) or by navigating to the folder `how_to_use_quicklook`.
6
+
7
+ ## Why quicklooks?
8
+ Creating attractive, ready-to-share data visualizations takes forever. quickook is a cut-and-paste Python package that does the design work for you and makes it easy to create beautifuly simple data visualizations.
9
+
10
+ ## Who is quicklooks best for?
11
+ quicklook is for any data scientist, product manager, or researcher that knows a little bit of Python and is analyzing their data in a Jupyter Notebook. My goal in writing quicklook was to make data viz more efficient, but in the process, I've also created a package that is easy to use for beginners.
12
+
13
+ ## To install...
14
+ Directions to come; I am currently overhauling the package and will upload to pip for easy installation.
15
+
16
+ ## Documentation
17
+ The [documentation is here](https://github.com/alexdsbreslav/quicklook/tree/master/how_to_use_quicklook).
18
+
19
+ ## Acknowledgments
20
+ quicklook is built using [Matplotlib](https://matplotlib.org/), [NumPy](https://numpy.org/), [Pandas](https://pandas.pydata.org/), [Coolors](https://coolors.co/), and [seaborn](https://seaborn.pydata.org/).
21
+
@@ -0,0 +1,28 @@
1
+ '''
2
+ PLACEHOLDER FOR INSTRUCTIONS
3
+ '''
4
+
5
+ # ---- chart skeleton
6
+ from .chart_skeleton import chart_skeleton
7
+ from .cs_attributes import chart_size
8
+ from .cs_attributes import chart_xlabel
9
+ from .cs_attributes import chart_ylabel
10
+ from .cs_attributes import color_libraries
11
+ from .cs_attributes import fonts
12
+
13
+ # ---- plots
14
+ from .bar_plot import bar_plot
15
+ from .line_plot import line_plot
16
+ from .dist_plot import distribution_plot
17
+ from .scatter_plot import scatter_plot
18
+
19
+ # ---- reference items
20
+ from .reference_line import reference_line
21
+ from .legend import legend
22
+ from .text import text
23
+
24
+ # ---- templates
25
+ from .templates import templates
26
+
27
+ # ---- save function
28
+ from .save_chart import save_chart
@@ -0,0 +1,127 @@
1
+ import numpy as np
2
+ import matplotlib.pyplot as plt
3
+
4
+ class bar_plot:
5
+ """
6
+ bar = ql.bar_plot(chart_skeleton,
7
+ xlabels = ,
8
+ y = ,
9
+ yerror = None, #If no values, None
10
+ bars_per_xlabel = 1,
11
+ bar_index = 0,
12
+ color = chart_skeleton.color_library.default,
13
+ opacity = 1,
14
+ label = '',
15
+ layer_order = 1)
16
+ """
17
+
18
+ def __init__(self, chart_skeleton, xlabels, y, yerror, bars_per_xlabel,
19
+ bar_index, color, opacity, label, layer_order):
20
+
21
+ if not chart_skeleton.ax:
22
+ raise Exception('''The chart skeleton has not been built.
23
+ You must build a chart skeleton for each new plot that you want \
24
+ to create.''')
25
+
26
+ if chart_skeleton.xaxis_type == 'timeseries':
27
+ raise Exception('''The chart skeleton xtick_label is set to a
28
+ timeseries (e.g., months, days). This is not
29
+ compatible with a scatter plot.''')
30
+
31
+ if type(xlabels) in [str, int, float, bool]:
32
+ raise TypeError('''x is not properly defined.
33
+ x should be a 1 dimensional array of values.''')
34
+
35
+ if type(y) in [str, int, float, bool]:
36
+ raise TypeError('''y is not properly defined.
37
+ y should be a 1 dimensional array of values.''')
38
+
39
+ if type(yerror) in [str, int, float, bool]:
40
+ raise TypeError('''yerror is not properly defined. If you do not
41
+ need error represented on your line plot, set yerror = None.\n'
42
+ 'If you need yerror on your line plot,
43
+ ensure that it is a 1 dimensional array of values.''')
44
+
45
+ if type(bar_index) is not int:
46
+ raise TypeError('''bar_index is not properly defined.
47
+ It must be an integer between 0 and bars_per_xlabel''')
48
+
49
+ if type(bars_per_xlabel) is not int or bars_per_xlabel < 1:
50
+ raise TypeError('''bars_per_xlabel is not properly defined.
51
+ It must be an integer >= 1''')
52
+
53
+ if bar_index >= bars_per_xlabel:
54
+ raise IndexError('''bar_index is not properly defined.
55
+ It must be an integer between 0 and bars_per_xlabel-1''')
56
+
57
+ # ---- check data shapes
58
+ if np.shape(np.shape(xlabels))[0] != 1:
59
+ raise ValueError('''x is not properly defined.; it is a {} x {} array.
60
+ x must be 1-dimensional array.'''.format(np.shape(xlabels)[0],
61
+ np.shape(xlabels)[1]))
62
+ if np.shape(np.shape(y))[0] != 1:
63
+ raise ValueError('''y is not properly defined.; it is a {} x {} array.
64
+ y must be 1-dimensional array.'''.format(np.shape(y)[0],
65
+ np.shape(y)[1]))
66
+ if np.shape(xlabels) != np.shape(y):
67
+ raise ValueError('''x and y are not the same shape. x has {} values
68
+ and y has {} values'''.format(np.shape(xlabels)[0], np.shape(y)[0]))
69
+
70
+ xlim = (-0.5,len(xlabels)-0.5)
71
+ plt.xlim(xlim[0], xlim[1]);
72
+ plt.xticks(ticks=range(len(xlabels)), labels=xlabels);
73
+ label_to_x = dict(zip(xlabels, chart_skeleton.ax.get_xticks()))
74
+
75
+ # ---- adjust for number of xlabels
76
+ width = 0.8 if len(xlabels) <= 2 else 0.8-(len(xlabels)*0.01)
77
+ # ---- adjust for number of bars at xlabel
78
+ width = width/bars_per_xlabel
79
+
80
+ # --- get offsets based on number of bars at xlabel
81
+ idx = [i for i in range(bars_per_xlabel)]
82
+ bar_offsets = [(i - np.median(idx))*1.1 for i in idx]
83
+ offset = bar_offsets[bar_index]*width
84
+
85
+ # ---- get x and y locs
86
+ ylim = chart_skeleton.ax.get_ylim()
87
+ x_loc = [label_to_x[i]+offset for i in xlabels]
88
+ bottom = np.array([(i/abs(i)) * ((ylim[1]-ylim[0])*0.002) for i in y])
89
+ height = y-bottom
90
+ zorder = 1
91
+
92
+ line = color[0]
93
+ fill = color[1]
94
+ edge = color[2]
95
+
96
+ bar = chart_skeleton.ax.bar(x=x_loc, width=width,
97
+ height=height, bottom=bottom,
98
+ color=fill,
99
+ edgecolor=edge,
100
+ linewidth=2,
101
+ joinstyle='round',
102
+ alpha=opacity,
103
+ label=label,
104
+ zorder = layer_order + 2)
105
+
106
+ if yerror is not None:
107
+ total_bars = bars_per_xlabel * len(x_loc)
108
+ if total_bars >= 30:
109
+ err_width = 2
110
+ elif total_bars >= 20:
111
+ err_width = 3
112
+ elif total_bars >= 10:
113
+ err_width = 4
114
+ else:
115
+ err_width = 5
116
+
117
+ for i in range(len(x_loc)):
118
+ chart_skeleton.ax.plot(np.full(10,x_loc[i]),
119
+ np.linspace(y[i]-yerror[i], y[i]+yerror[i],10),
120
+ linewidth=err_width, color=edge, alpha=opacity,
121
+ zorder = layer_order + 2+0.1, solid_capstyle='round');
122
+ else:
123
+ error = None
124
+
125
+ self.bar_obj = bar
126
+ self.xlim = xlim
127
+ self.zorder = layer_order + 2
@@ -0,0 +1,260 @@
1
+ import matplotlib.pyplot as plt
2
+ from .plot_and_text_styling import *
3
+ from .cs_attributes import *
4
+ from datetime import datetime
5
+ from dateutil import relativedelta
6
+ import matplotlib.dates as mdates
7
+
8
+ class chart_skeleton:
9
+ """
10
+ chart_skeleton = ql.chart_skeleton(
11
+ size = ql.chart_size.notebook,
12
+ color_library = ql.color_libraries.skygrove,
13
+ font = ql.fonts.rubik,
14
+ title = '',
15
+ xlabel = '',
16
+ ylabel = '',
17
+ x_min_max = (0,1), y_min_max = (0,1),
18
+ xtick_interval = 0.25, ytick_interval = 0.25,
19
+ xtick_labels = ql.chart_xlabel.default,
20
+ ytick_labels = ql.chart_ylabel.default,
21
+ horizontal_gridlines_on = False,
22
+ vertical_gridlines_on = False);
23
+ """
24
+
25
+ def __init__(self, size, color_library, font, title, ylabel, xlabel, x_min_max,
26
+ y_min_max, xtick_interval, ytick_interval, xtick_labels,
27
+ ytick_labels, horizontal_gridlines_on, vertical_gridlines_on):
28
+
29
+ # ---- size
30
+ # ---- affects markersize for line and scatter plots
31
+ self.size = size
32
+
33
+ # ---- colors
34
+ self.color_library = color_library
35
+
36
+ # ---- font
37
+ self.font = font
38
+
39
+ # ---- title
40
+ if type(title) is not str:
41
+ raise AttributeError('title not properly define: must be a string \
42
+ (e.g., Daily Active Users)')
43
+
44
+ # ---- ylabel
45
+ if type(ylabel) is not str:
46
+ raise AttributeError('ylabel not properly define: must be a string \
47
+ (e.g., "Daily Active Users")')
48
+
49
+ # ---- xlabel
50
+ if type(xlabel) is not str:
51
+ raise AttributeError('xlabel not properly define: must be a string \
52
+ (e.g., "Date")')
53
+
54
+ # ---- y_min_max
55
+ # ---- req for reference_line
56
+ if type(y_min_max) is tuple and y_min_max[1] > y_min_max[0]:
57
+ self.y_min_max = y_min_max
58
+ yrange = y_min_max[1] - y_min_max[0]
59
+ self.yrange = yrange
60
+
61
+ else:
62
+ raise AttributeError('y_min_max must be a tuple (e.g., (0,1) where\
63
+ the second value is greater than the first')
64
+
65
+ # ---- xtick_labels
66
+ if type(xtick_labels) not in [str, list]:
67
+ raise Exception('xtick_labels not properly defined: xtick_labels \
68
+ must be set to default, percents, or defined \
69
+ as a list of strings.')
70
+
71
+ # ---- set xaxis_type (will overwrite if timeseries)
72
+ xaxis_type = 'default'
73
+
74
+ # ---- check that label type and min_max match
75
+ if xtick_labels in ['years', 'months', 'quarters', 'days']:
76
+ if type(x_min_max[0]) is not str or type(x_min_max[1]) is not str:
77
+ raise TypeError('''If xtick label is set to a timeseries,
78
+ x_min_max must be a tuple with two date strings in the format
79
+ YYYY-MM-DD''')
80
+ # ---- if they do, convert str to datetime
81
+ else:
82
+ x_min_max = (datetime.strptime(x_min_max[0], '%Y-%m-%d'),
83
+ datetime.strptime(x_min_max[1], '%Y-%m-%d'))
84
+
85
+ xaxis_type = 'timeseries'
86
+
87
+ # ---- req for reference line
88
+ self.xaxis_type = xaxis_type
89
+
90
+ # ---- ytick_labels
91
+ if type(ytick_labels) not in [str, list]:
92
+ raise Exception('''ytick_labels not properly defined: ytick_labels
93
+ must be set to default, percents, or defined as a
94
+ list of strings.''')
95
+
96
+ # ---- check xtick labels
97
+ # ---- for timeseries
98
+ def_error = False
99
+ int_error = False
100
+
101
+ if xaxis_type == 'timeseries':
102
+ xrange = (x_min_max[1] - x_min_max[0]).days
103
+ rd = relativedelta.relativedelta(x_min_max[1], x_min_max[0])
104
+
105
+ if xtick_labels == 'days':
106
+ def_error = True if xtick_interval > xrange else False
107
+ int_error = True if 20*xtick_interval < xrange else False
108
+
109
+ elif xtick_labels == 'months':
110
+ if 2 > rd.years * 12 + rd.months:
111
+ raise Exception('''xtick_interval not properly defined.
112
+ Use days if the date range <= 3 months''')
113
+ elif 15 < rd.years * 12 + rd.months:
114
+ raise Exception('''xtick_interval not properly defined.
115
+ Use quarters if the date range > 15 months''')
116
+
117
+ elif xtick_labels == 'quarters':
118
+ if 9 > rd.years * 12 + rd.months:
119
+ raise Exception('''xtick_interval not properly defined.
120
+ Use months if the date range <= 9 months''')
121
+ elif 48 < rd.years * 12 + rd.months:
122
+ raise Exception('''xtick_interval not properly defined.
123
+ Use quarters if the date range > 16 quarters''')
124
+
125
+ elif xtick_labels == 'years':
126
+ def_error = True if xtick_interval > rd.years else False
127
+ int_error = True if 20*xtick_interval < rd.years else False
128
+
129
+ # ---- for everything else
130
+ else:
131
+ xrange = x_min_max[1] - x_min_max[0]
132
+ def_error = True if xtick_interval > xrange else False
133
+ int_error = True if 20*xtick_interval < xrange else False
134
+
135
+ if def_error:
136
+ raise Exception('''xtick_interval not properly defined.
137
+ Decrease the xtick_interval or change the xtick_labels''')
138
+ if int_error:
139
+ raise Exception('''xtick_interval is too small.
140
+ Increase the xtick_interval or change the xtick_labels''')
141
+
142
+
143
+ self.x_min_max = x_min_max
144
+ # ---- req for reference line
145
+ self.xrange = xrange
146
+
147
+ # ---- check ytick_labels
148
+ if ytick_interval > yrange:
149
+ raise Exception('''ytick_interval not properly defined;
150
+ decrease the ytick_interval''')
151
+
152
+ elif 20*ytick_interval < yrange:
153
+ raise Exception('''ytick_interval is too small;
154
+ increase the ytick_interval.''')
155
+
156
+ # ---- vertical gridlines
157
+ if type(vertical_gridlines_on) is not bool:
158
+ raise AttributeError('Vertical gridlines is not properly defined: \
159
+ vertical_gridlines_on must be set to \
160
+ True or False.')
161
+
162
+ # ---- horizontal gridlines
163
+ if type(horizontal_gridlines_on) is not bool:
164
+ raise AttributeError('Horizontal gridlines is not properly defined: \
165
+ horizontal_gridlines_on must be set to \
166
+ True or False.')
167
+
168
+ # ----------------------------------------------------------------------
169
+ # style the plot -------------------------------------------------------
170
+ # ----------------------------------------------------------------------
171
+ # ---- define plot style based on style and size choice
172
+ ps = chart_skeleton_style(size, ylabel)
173
+ fs = font_style(size, self)
174
+
175
+ # ---- req for legend and text
176
+ self.plot_style = ps
177
+ self.font_style = fs
178
+
179
+ # ---- create the plot
180
+ fig, ax = plt.subplots(nrows=1, figsize = ps.figsize)
181
+ self.ax = ax
182
+
183
+ # ---- add the title
184
+ ax.set_title(title, color = color_library.text,
185
+ pad = ps.title_pad, fontproperties = fs.title)
186
+
187
+ # ---- create a patch to set the background color of the plot
188
+ ax.patch.set_xy((-0.16, -0.14))
189
+ ax.patch.set_height(1.2)
190
+ ax.patch.set_width(1.28)
191
+ ax.set_facecolor(color_library.background)
192
+
193
+ # ---- set facecolor of fig (around ax face)
194
+ fig.set_facecolor(color_library.background)
195
+
196
+ # ---- add grid lines if necessary
197
+ if horizontal_gridlines_on == True:
198
+ ax.yaxis.grid(which='major', linestyle=':',
199
+ linewidth = ps.linewidth, color = '0.8', zorder=1)
200
+
201
+ if vertical_gridlines_on == True:
202
+ ax.xaxis.grid(which='major', linestyle=':',
203
+ linewidth = ps.linewidth, color = '0.8', zorder=1)
204
+
205
+ # ---- style the axis lines
206
+ for spine in ['top', 'right']:
207
+ ax.spines[spine].set_visible(False)
208
+ for spine in ['bottom', 'left']:
209
+ ax.spines[spine].set_linewidth(ps.linewidth)
210
+ ax.spines[spine].set_color(color_library.text)
211
+ ax.spines[spine].set_zorder(2)
212
+
213
+ # ---- style the axis ticks
214
+ for i in range(2):
215
+ ax.tick_params(['x','y'][i],
216
+ colors=color_library.text,
217
+ width = ps.linewidth, pad = ps.tick_pad[i],
218
+ length = ps.tick_length)
219
+
220
+ for tick in ax.get_xticklabels():
221
+ tick.set_font_properties(fs.label)
222
+ for tick in ax.get_yticklabels():
223
+ tick.set_font_properties(fs.label)
224
+
225
+ # ---- set the axis limits and number of ticks
226
+ ax.set_ylim(y_min_max)
227
+ ax.set_xlim(x_min_max)
228
+
229
+ # ---- set the number of ticks on the axes
230
+ ax.yaxis.set_major_locator(plt.MultipleLocator(ytick_interval))
231
+ if xaxis_type == 'default':
232
+ ax.xaxis.set_major_locator(plt.MultipleLocator(xtick_interval))
233
+ else:
234
+ if xtick_labels == 'years':
235
+ ax.xaxis.set_major_locator(mdates.YearLocator(base=1))
236
+ print('xtick_interval ignored when xtick_label = years\n')
237
+ elif xtick_labels == 'quarters':
238
+ ax.xaxis.set_major_locator(mdates.MonthLocator((1,4,7,10)))
239
+ print('xtick_interval ignored when xtick_label = quarters\n')
240
+ elif xtick_labels == 'months':
241
+ ax.xaxis.set_major_locator(mdates.MonthLocator(interval=1))
242
+ print('xtick_interval ignored when xtick_label = months\n')
243
+ elif xtick_labels == 'days':
244
+ ax.xaxis.set_major_locator(mdates.DayLocator(interval=xtick_interval))
245
+
246
+ # ---- label the y axis
247
+ ax.set_ylabel(ylabel, color=color_library.text,
248
+ rotation = 90 if size == 'half_slide' else 0, labelpad = ps.label_pad[1],
249
+ horizontalalignment = 'center',
250
+ linespacing = 1.6, fontproperties = fs.label)
251
+
252
+ # ---- label the x axis
253
+ ax.set_xlabel(xlabel, color = color_library.text,
254
+ labelpad = ps.label_pad[0], fontproperties = fs.label)
255
+
256
+ # ---- set the x and y tick labels
257
+ set_tick_labels(xtick_labels, 'x', ax, x_min_max)
258
+ set_tick_labels(ytick_labels, 'y', ax, y_min_max)
259
+
260
+ plt.tight_layout()
@@ -0,0 +1,115 @@
1
+ class chart_ylabel:
2
+ default = 'default'
3
+ percents = 'percents'
4
+ millions = '1m'
5
+ hundredK = '100k'
6
+ thousands = '1k'
7
+
8
+ class chart_xlabel:
9
+ default = 'default'
10
+ percents = 'percents'
11
+ years = 'years'
12
+ quarters = 'quarters'
13
+ months = 'months'
14
+ days = 'days'
15
+
16
+ class chart_size:
17
+ notebook = 'notebook'
18
+ half_slide = 'half_slide'
19
+ full_slide = 'full_slide'
20
+
21
+ class fonts:
22
+ lato = 'lato'
23
+ montserrat = 'montserrat'
24
+ oswald = 'oswald'
25
+ roboto = 'roboto'
26
+ rubik = 'rubik'
27
+ source_sans = 'source_sans'
28
+ work_sans = 'work_sans'
29
+
30
+ class color_libraries:
31
+ class mariglow:
32
+ default = ['#9AA7FE', '#4B64FE', '#203DFE'] #blue
33
+ background = '#ffffff'
34
+ text = '#000000'
35
+ color_list = ['orange', 'peach', 'navy', 'blue']
36
+ orange = ['#EF7B57', '#E94819', '#BB3911']
37
+ peach = ['#FAF3EF', '#ECCFC0', '#DEAB91']
38
+ navy = ['#2C4177', '#1A2747', '#0B101E']
39
+ blue = ['#9AA7FE', '#4B64FE', '#203DFE']
40
+ light_gray = ['#f1f3f5', '#e9ecef', '#dee2e6']
41
+ gray = ['#ced4da', '#adb5bd', '#868e96']
42
+ dark_gray = ['#495057', '#343a40', '#212529']
43
+ black = ['#000000', '#000000', '#000000']
44
+
45
+ class skygrove:
46
+ default = ['#6E80D8', '#3E56CC', '#2B3FA1'] #blue
47
+ background = '#ffffff'
48
+ text = '#000000'
49
+ color_list = ['blue', 'periwinkle', 'sea_green', 'green_tea']
50
+ blue = ['#6E80D8', '#3E56CC', '#2B3FA1']
51
+ periwinkle = ['#EBEFFF', '#ADBEFF', '#708DFF']
52
+ sea_green = ['#57B27C', '#3E885B', '#2D6242']
53
+ green_tea = ['#EAF0D1', '#D5E1A3', '#BFD274']
54
+ light_gray = ['#f1f3f5', '#e9ecef', '#dee2e6']
55
+ gray = ['#ced4da', '#adb5bd', '#868e96']
56
+ dark_gray = ['#495057', '#343a40', '#212529']
57
+ black = ['#000000', '#000000', '#000000']
58
+
59
+ class opencolor:
60
+ default = ['#4dabf7','#339af0','#228be6'] #blue
61
+ background = '#ffffff'
62
+ text = '#000000'
63
+ color_list = ['light_red', 'red', 'dark_red',
64
+ 'light_pink', 'pink', 'dark_pink',
65
+ 'light_grape', 'grape', 'dark_grape',
66
+ 'light_violet', 'violet', 'dark_violet',
67
+ 'light_indigo', 'indigo', 'dark_indigo',
68
+ 'light_blue', 'blue', 'dark_blue',
69
+ 'light_cyan', 'cyan', 'dark_cyan',
70
+ 'light_teal', 'teal', 'dark_teal',
71
+ 'light_green', 'green', 'dark_green',
72
+ 'light_lime', 'lime', 'dark_lime',
73
+ 'light_yellow', 'yellow', 'dark_yellow',
74
+ 'light_orange', 'orange', 'dark_orange']
75
+
76
+ light_red = ['#ffe3e3','#ffc9c9','#ffa8a8']
77
+ red = ['#ff8787','#ff6b6b','#fa5252']
78
+ dark_red = ['#f03e3e','#e03131','#c92a2a']
79
+ light_pink = ['#ffdeeb','#fcc2d7','#faa2c1']
80
+ pink = ['#f783ac','#f06595','#e64980']
81
+ dark_pink = ['#d6336c','#c2255c','#a61e4d']
82
+ light_grape = ['#f3d9fa','#eebefa','#e599f7']
83
+ grape = ['#da77f2','#cc5de8','#be4bdb']
84
+ dark_grape = ['#ae3ec9','#9c36b5','#862e9c']
85
+ light_violet = ['#e5dbff','#d0bfff','#b197fc']
86
+ violet = ['#9775fa','#845ef7','#7950f2']
87
+ dark_violet = ['#7048e8','#6741d9','#5f3dc4']
88
+ light_indigo = ['#dbe4ff','#bac8ff','#91a7ff']
89
+ indigo = ['#748ffc','#5c7cfa','#4c6ef5']
90
+ dark_indigo = ['#4263eb','#3b5bdb','#364fc7']
91
+ light_blue = ['#d0ebff','#a5d8ff','#74c0fc']
92
+ blue = ['#4dabf7','#339af0','#228be6']
93
+ dark_blue = ['#1c7ed6','#1971c2','#1864ab']
94
+ light_cyan = ['#c5f6fa','#99e9f2','#66d9e8']
95
+ cyan = ['#3bc9db','#22b8cf','#15aabf']
96
+ dark_cyan = ['#1098ad','#0c8599','#0b7285']
97
+ light_teal = ['#c3fae8','#96f2d7','#63e6be']
98
+ teal = ['#38d9a9','#20c997','#12b886']
99
+ dark_teal = ['#0ca678','#099268','#087f5b']
100
+ light_green = ['#d3f9d8','#b2f2bb','#8ce99a']
101
+ green = ['#69db7c','#51cf66','#40c057']
102
+ dark_green = ['#37b24d','#2f9e44','#2b8a3e']
103
+ light_lime = ['#e9fac8','#d8f5a2','#c0eb75']
104
+ lime = ['#a9e34b','#94d82d','#82c91e']
105
+ dark_lime = ['#74b816','#66a80f','#5c940d']
106
+ light_yellow = ['#fff3bf','#ffec99','#ffe066']
107
+ yellow = ['#ffd43b','#fcc419','#fab005']
108
+ dark_yellow = ['#f59f00','#f08c00','#e67700']
109
+ light_orange = ['#ffe8cc','#ffd8a8','#ffc078']
110
+ orange = ['#ffa94d','#ff922b','#fd7e14']
111
+ dark_orange = ['#f76707','#e8590c','#d9480f']
112
+ light_gray = ['#f1f3f5', '#e9ecef', '#dee2e6']
113
+ gray = ['#ced4da', '#adb5bd', '#868e96']
114
+ dark_gray = ['#495057', '#343a40', '#212529']
115
+ black = ['#000000', '#000000', '#000000']