Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit bb614b3

Browse files
authored
Merge branch 'master' into dashboard-wrapper
2 parents 2a3a301 + 4b06dfd commit bb614b3

File tree

28 files changed

+2732
-2630
lines changed

28 files changed

+2732
-2630
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
66
## Added
77
- dashboards can now be created using the API and uploaded to Plotly. Use `import plotly.dashboard_objs` to be create a dashboard a `Dashboard` object. You can learn more about `Dashboard` objects by running `help(plotly.dashboard_objs.Dashboard)` and `help(plotly.plotly.plotly.dashboard_ops)` for uploading and retrieving dashboards from the cloud.
88

9+
910
## [2.0.2] - 2017-02-20
1011
### Fixed
1112
- Offline plots created with `plotly.offline.plot` now resize as expected when the window is resized.

plotly/figure_factory/_annotated_heatmap.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,14 @@ def create_annotated_heatmap(z, x=None, y=None, annotation_text=None,
7171
Example 1: Simple annotated heatmap with default configuration
7272
```
7373
import plotly.plotly as py
74-
from plotly.figure_factory create_annotated_heatmap
74+
import plotly.figure_factory as FF
7575
7676
z = [[0.300000, 0.00000, 0.65, 0.300000],
7777
[1, 0.100005, 0.45, 0.4300],
7878
[0.300000, 0.00000, 0.65, 0.300000],
7979
[1, 0.100005, 0.45, 0.00000]]
8080
81-
figure = create_annotated_heatmap(z)
81+
figure = FF.create_annotated_heatmap(z)
8282
py.iplot(figure)
8383
```
8484
"""

plotly/figure_factory/_distplot.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ def make_hist(self):
286286
histnorm=self.histnorm,
287287
name=self.group_labels[index],
288288
legendgroup=self.group_labels[index],
289-
marker=dict(color=self.colors[index]),
289+
marker=dict(color=self.colors[index % len(self.colors)]),
290290
autobinx=False,
291291
xbins=dict(start=self.start[index],
292292
end=self.end[index],
@@ -324,7 +324,7 @@ def make_kde(self):
324324
name=self.group_labels[index],
325325
legendgroup=self.group_labels[index],
326326
showlegend=False if self.show_hist else True,
327-
marker=dict(color=self.colors[index]))
327+
marker=dict(color=self.colors[index % len(self.colors)]))
328328
return curve
329329

330330
def make_normal(self):
@@ -361,7 +361,7 @@ def make_normal(self):
361361
name=self.group_labels[index],
362362
legendgroup=self.group_labels[index],
363363
showlegend=False if self.show_hist else True,
364-
marker=dict(color=self.colors[index]))
364+
marker=dict(color=self.colors[index % len(self.colors)]))
365365
return curve
366366

367367
def make_rug(self):
@@ -385,6 +385,6 @@ def make_rug(self):
385385
showlegend=(False if self.show_hist or
386386
self.show_curve else True),
387387
text=self.rug_text[index],
388-
marker=dict(color=self.colors[index],
388+
marker=dict(color=self.colors[index % len(self.colors)],
389389
symbol='line-ns-open'))
390390
return rug

plotly/figure_factory/_violin.py

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,8 @@ def violinplot(vals, fillcolor='#1f77b4', rugplot=True):
194194

195195

196196
def violin_no_colorscale(data, data_header, group_header, colors,
197-
use_colorscale, group_stats,
198-
height, width, title):
197+
use_colorscale, group_stats, rugplot,
198+
height, width, title):
199199
"""
200200
Refer to FigureFactory.create_violin() for docstring.
201201
@@ -223,7 +223,8 @@ def violin_no_colorscale(data, data_header, group_header, colors,
223223
if color_index >= len(colors):
224224
color_index = 0
225225
plot_data, plot_xrange = violinplot(vals,
226-
fillcolor=colors[color_index])
226+
fillcolor=colors[color_index],
227+
rugplot=rugplot)
227228
layout = graph_objs.Layout()
228229

229230
for item in plot_data:
@@ -250,7 +251,7 @@ def violin_no_colorscale(data, data_header, group_header, colors,
250251

251252

252253
def violin_colorscale(data, data_header, group_header, colors, use_colorscale,
253-
group_stats, height, width, title):
254+
group_stats, rugplot, height, width, title):
254255
"""
255256
Refer to FigureFactory.create_violin() for docstring.
256257
@@ -303,7 +304,8 @@ def violin_colorscale(data, data_header, group_header, colors, use_colorscale,
303304

304305
plot_data, plot_xrange = violinplot(
305306
vals,
306-
fillcolor='rgb{}'.format(intermed_color)
307+
fillcolor='rgb{}'.format(intermed_color),
308+
rugplot=rugplot
307309
)
308310
layout = graph_objs.Layout()
309311

@@ -343,7 +345,7 @@ def violin_colorscale(data, data_header, group_header, colors, use_colorscale,
343345

344346

345347
def violin_dict(data, data_header, group_header, colors, use_colorscale,
346-
group_stats, height, width, title):
348+
group_stats, rugplot, height, width, title):
347349
"""
348350
Refer to FigureFactory.create_violin() for docstring.
349351
@@ -375,7 +377,8 @@ def violin_dict(data, data_header, group_header, colors, use_colorscale,
375377

376378
for k, gr in enumerate(group_name):
377379
vals = np.asarray(gb.get_group(gr)[data_header], np.float)
378-
plot_data, plot_xrange = violinplot(vals, fillcolor=colors[gr])
380+
plot_data, plot_xrange = violinplot(vals, fillcolor=colors[gr],
381+
rugplot=rugplot)
379382
layout = graph_objs.Layout()
380383

381384
for item in plot_data:
@@ -401,18 +404,18 @@ def violin_dict(data, data_header, group_header, colors, use_colorscale,
401404

402405

403406
def create_violin(data, data_header=None, group_header=None, colors=None,
404-
use_colorscale=False, group_stats=None, height=450,
405-
width=600, title='Violin and Rug Plot'):
407+
use_colorscale=False, group_stats=None, rugplot=True,
408+
height=450, width=600, title='Violin and Rug Plot'):
406409
"""
407410
Returns figure for a violin plot
408411
409412
:param (list|array) data: accepts either a list of numerical values,
410413
a list of dictionaries all with identical keys and at least one
411414
column of numeric values, or a pandas dataframe with at least one
412-
column of numbers
415+
column of numbers.
413416
:param (str) data_header: the header of the data column to be used
414417
from an inputted pandas dataframe. Not applicable if 'data' is
415-
a list of numeric values
418+
a list of numeric values.
416419
:param (str) group_header: applicable if grouping data by a variable.
417420
'group_header' must be set to the name of the grouping variable.
418421
:param (str|tuple|list|dict) colors: either a plotly scale name,
@@ -422,18 +425,19 @@ def create_violin(data, data_header=None, group_header=None, colors=None,
422425
tuple of the form (a, b, c) where a, b and c belong to [0, 1].
423426
If colors is a list, it must contain valid color types as its
424427
members.
425-
:param (bool) use_colorscale: Only applicable if grouping by another
428+
:param (bool) use_colorscale: only applicable if grouping by another
426429
variable. Will implement a colorscale based on the first 2 colors
427430
of param colors. This means colors must be a list with at least 2
428431
colors in it (Plotly colorscales are accepted since they map to a
429-
list of two rgb colors)
432+
list of two rgb colors).
430433
:param (dict) group_stats: a dictioanry where each key is a unique
431434
value from the group_header column in data. Each value must be a
432435
number and will be used to color the violin plots if a colorscale
433-
is being used
434-
:param (float) height: the height of the violin plot
435-
:param (float) width: the width of the violin plot
436-
:param (str) title: the title of the violin plot
436+
is being used.
437+
:param (bool) rugplot: determines if a rugplot is draw on violin plot.
438+
:param (float) height: the height of the violin plot.
439+
:param (float) width: the width of the violin plot.
440+
:param (str) title: the title of the violin plot.
437441
438442
Example 1: Single Violin Plot
439443
```
@@ -558,7 +562,8 @@ def create_violin(data, data_header=None, group_header=None, colors=None,
558562
data = data[data_header].values.tolist()
559563

560564
# call the plotting functions
561-
plot_data, plot_xrange = violinplot(data, fillcolor=valid_colors[0])
565+
plot_data, plot_xrange = violinplot(data, fillcolor=valid_colors[0],
566+
rugplot=rugplot)
562567

563568
layout = graph_objs.Layout(
564569
title=title,
@@ -596,13 +601,13 @@ def create_violin(data, data_header=None, group_header=None, colors=None,
596601
# validate colors dict choice below
597602
fig = violin_dict(
598603
data, data_header, group_header, valid_colors,
599-
use_colorscale, group_stats, height, width, title
604+
use_colorscale, group_stats, rugplot, height, width, title
600605
)
601606
return fig
602607
else:
603608
fig = violin_no_colorscale(
604609
data, data_header, group_header, valid_colors,
605-
use_colorscale, group_stats, height, width, title
610+
use_colorscale, group_stats, rugplot, height, width, title
606611
)
607612
return fig
608613
else:
@@ -622,6 +627,6 @@ def create_violin(data, data_header=None, group_header=None, colors=None,
622627

623628
fig = violin_colorscale(
624629
data, data_header, group_header, valid_colors,
625-
use_colorscale, group_stats, height, width, title
630+
use_colorscale, group_stats, rugplot, height, width, title
626631
)
627632
return fig

plotly/files.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,22 @@
2222
'sharing': 'public',
2323
'auto_open': True}}
2424

25-
try:
26-
os.mkdir(TEST_DIR)
27-
os.rmdir(TEST_DIR)
28-
if not os.path.exists(PLOTLY_DIR):
29-
os.mkdir(PLOTLY_DIR)
30-
f = open(TEST_FILE, 'w')
31-
f.write('testing\n')
32-
f.close()
33-
os.remove(TEST_FILE)
34-
_file_permissions = True
35-
except:
36-
_file_permissions = False
25+
26+
def _permissions():
27+
try:
28+
os.mkdir(TEST_DIR)
29+
os.rmdir(TEST_DIR)
30+
if not os.path.exists(PLOTLY_DIR):
31+
os.mkdir(PLOTLY_DIR)
32+
with open(TEST_FILE, 'w') as f:
33+
f.write('testing\n')
34+
os.remove(TEST_FILE)
35+
return True
36+
except:
37+
return False
38+
39+
40+
_file_permissions = _permissions()
3741

3842

3943
def check_file_permissions():

plotly/graph_objs/graph_objs.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
from plotly import exceptions, graph_reference
3535
from plotly.graph_objs import graph_objs_tools
3636

37+
_subplot_regex = re.compile(r'(?P<digits>\d+$)')
38+
3739

3840
class PlotlyBase(object):
3941
"""
@@ -506,7 +508,7 @@ def _get_subplot_attributes(self):
506508

507509
def _get_subplot_key(self, key):
508510
"""Some keys can have appended integers, this handles that."""
509-
match = re.search(r'(?P<digits>\d+$)', key)
511+
match = _subplot_regex.search(key)
510512
if match:
511513
root_key = key[:match.start()]
512514
if (root_key in self._get_subplot_attributes() and

plotly/graph_reference.py

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,8 @@ def get_attributes_dicts(object_name, parent_object_names=()):
229229
return attributes_dicts
230230

231231

232-
def get_valid_attributes(object_name, parent_object_names=()):
232+
@utils.memoize()
233+
def _get_valid_attributes(object_name, parent_object_names):
233234
attributes = get_attributes_dicts(object_name, parent_object_names)
234235
# These are for documentation and quick lookups. They're just strings.
235236
valid_attributes = set()
@@ -245,6 +246,11 @@ def get_valid_attributes(object_name, parent_object_names=()):
245246
return valid_attributes
246247

247248

249+
def get_valid_attributes(object_name, parent_object_names=()):
250+
# Enforce that parent_object_names is hashable (a tuple).
251+
return _get_valid_attributes(object_name, tuple(parent_object_names))
252+
253+
248254
def get_deprecated_attributes(object_name, parent_object_names=()):
249255
attributes = get_attributes_dicts(object_name, parent_object_names)
250256
# These are for documentation and quick lookups. They're just strings.
@@ -340,21 +346,10 @@ def attribute_path_to_object_names(attribute_container_path):
340346
return tuple(object_names)
341347

342348

343-
def get_role(object_name, attribute, value=None, parent_object_names=()):
344-
"""
345-
Values have types associated with them based on graph_reference.
346-
347-
'data' type values are always kept
348-
'style' values are kept if they're sequences (but not strings)
349-
350-
:param (str) object_name: The name of the object containing 'attribute'.
351-
:param (str) attribute: The attribute we want the `role` of.
352-
:param (*) value: If the value is an array, the return can be different.
353-
:param parent_object_names: An iterable of obj names from graph reference.
354-
:returns: (str) This will be 'data', 'style', or 'info'.
355-
356-
"""
357-
if object_name in TRACE_NAMES and attribute == 'type':
349+
@utils.memoize()
350+
def _get_role(object_name, attribute, value_type, parent_object_names=()):
351+
"""Private, more easily memoized version of get_role."""
352+
if attribute == 'type' and object_name in TRACE_NAMES:
358353
return 'info'
359354
attributes_dicts = get_attributes_dicts(object_name, parent_object_names)
360355
matches = []
@@ -372,12 +367,8 @@ def get_role(object_name, attribute, value=None, parent_object_names=()):
372367
for match in matches:
373368
role = match['role']
374369
array_ok = match.get('arrayOk')
375-
if value is not None and array_ok:
376-
iterable = hasattr(value, '__iter__')
377-
stringy = isinstance(value, six.string_types)
378-
dicty = isinstance(value, dict)
379-
if iterable and not stringy and not dicty:
380-
role = 'data'
370+
if array_ok and value_type == 'array':
371+
role = 'data'
381372
roles.append(role)
382373

383374
# TODO: this is ambiguous until the figure is in place...
@@ -388,6 +379,36 @@ def get_role(object_name, attribute, value=None, parent_object_names=()):
388379
return role
389380

390381

382+
def get_role(object_name, attribute, value=None, parent_object_names=()):
383+
"""
384+
Values have types associated with them based on graph_reference.
385+
386+
'data' type values are always kept
387+
'style' values are kept if they're sequences (but not strings)
388+
389+
:param (str) object_name: The name of the object containing 'attribute'.
390+
:param (str) attribute: The attribute we want the `role` of.
391+
:param (*) value: If the value is an array, the return can be different.
392+
:param parent_object_names: An iterable of obj names from graph reference.
393+
:returns: (str) This will be 'data', 'style', or 'info'.
394+
395+
"""
396+
if value is None:
397+
value_type = 'none'
398+
elif isinstance(value, dict):
399+
value_type = 'dict'
400+
elif isinstance(value, six.string_types):
401+
value_type = 'string'
402+
elif hasattr(value, '__iter__'):
403+
value_type = 'array'
404+
else:
405+
value_type = 'unknown'
406+
407+
# Enforce that parent_object_names is hashable (a tuple).
408+
return _get_role(object_name, attribute, value_type,
409+
tuple(parent_object_names))
410+
411+
391412
def _is_valid_sub_path(path, parent_paths):
392413
"""
393414
Check if a sub path is valid given an iterable of parent paths.

plotly/grid_objs/grid_objs.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99

1010
from requests.compat import json as _json
1111

12-
from plotly import exceptions, utils
12+
from plotly import exceptions, optional_imports, utils
13+
14+
pd = optional_imports.get_module('pandas')
1315

1416
__all__ = None
1517

@@ -148,7 +150,20 @@ def __init__(self, columns_or_json, fid=None):
148150
```
149151
"""
150152
# TODO: verify that columns are actually columns
151-
if isinstance(columns_or_json, dict):
153+
if pd and isinstance(columns_or_json, pd.DataFrame):
154+
duplicate_name = utils.get_first_duplicate(columns_or_json.columns)
155+
if duplicate_name:
156+
err = exceptions.NON_UNIQUE_COLUMN_MESSAGE.format(duplicate_name)
157+
raise exceptions.InputError(err)
158+
159+
# create columns from dataframe
160+
all_columns = []
161+
for name in columns_or_json.columns:
162+
all_columns.append(Column(columns_or_json[name].tolist(), name))
163+
self._columns = all_columns
164+
self.id = ''
165+
166+
elif isinstance(columns_or_json, dict):
152167
# check that fid is entered
153168
if fid is None:
154169
raise exceptions.PlotlyError(

0 commit comments

Comments
 (0)