Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 814c1d5

Browse filesBrowse files
committed
Merge pull request plotly#312 from plotly/dendrogram-andrew-tweaks
Dendrogram andrew tweaks
2 parents 390c09d + 3815a8f commit 814c1d5
Copy full SHA for 814c1d5

File tree

Expand file treeCollapse file tree

6 files changed

+652
-6
lines changed
Filter options
Expand file treeCollapse file tree

6 files changed

+652
-6
lines changed

‎CHANGELOG.md

Copy file name to clipboardExpand all lines: CHANGELOG.md
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,15 @@ This project adheres to [Semantic Versioning](http://semver.org/).
44

55
## [Unreleased]
66

7+
## [1.8.7] - 2015-10-01
8+
### Added
9+
- The FigureFactory can now create dendrogram plots with `.create_dendrogram`.
10+
711
## [1.8.6] - 2015-09-28
12+
### Fixed
813
- Saving "world_readable" to your config file via `plotly.tools.set_config` actually works.
14+
15+
### Added
916
- You can also save `auto_open` and `sharing` to the config file so that you can forget these
1017
keyword argument in `py.iplot` and `py.plot`.
1118

‎plotly/tests/test_core/test_tools/test_figure_factory.py

Copy file name to clipboardExpand all lines: plotly/tests/test_core/test_tools/test_figure_factory.py
-1Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
import datetime
55
from nose.tools import raises
6-
76
import plotly.tools as tls
87
from plotly.exceptions import PlotlyError
98
from plotly.graph_objs import graph_objs

‎plotly/tests/test_optional/optional_utils.py

Copy file name to clipboardExpand all lines: plotly/tests/test_optional/optional_utils.py
+82Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,93 @@
33
import matplotlib
44
# Force matplotlib to not use any Xwindows backend.
55
matplotlib.use('Agg')
6+
7+
import numpy as np
8+
69
from plotly.matplotlylib import Exporter, PlotlyRenderer
10+
from plotly.tests.utils import is_num_list
11+
from plotly.utils import get_by_path, node_generator
712

813

914
def run_fig(fig):
1015
renderer = PlotlyRenderer()
1116
exporter = Exporter(renderer)
1217
exporter.run(fig)
1318
return renderer
19+
20+
21+
class NumpyTestUtilsMixin(object):
22+
"""Provides some helper functions to make testing easier."""
23+
24+
def _format_path(self, path):
25+
str_path = [repr(p) for p in path]
26+
return '[' + ']['.join(sp for sp in str_path) + ']'
27+
28+
def assert_dict_equal(self, d1, d2, msg=None):
29+
"""
30+
Uses `np.allclose()` on number arrays.
31+
32+
:raises: (AssertionError) Using TestCase's self.failureException
33+
34+
"""
35+
self.assertIsInstance(d1, dict, 'First argument is not a dictionary')
36+
self.assertIsInstance(d2, dict, 'Second argument is not a dictionary')
37+
38+
for node, path in node_generator(d1):
39+
40+
# first check that this sub-dict is contained in both dicts
41+
try:
42+
comp_node = get_by_path(d2, path)
43+
except (KeyError, IndexError):
44+
standard_msg = (
45+
'Path {} exists in dict 1, but not dict 2.'
46+
.format(path)
47+
)
48+
self.fail(self._formatMessage(msg, standard_msg))
49+
self.assertIsInstance(
50+
comp_node, dict, 'Value at path {} is not a dict.'.format(path)
51+
)
52+
53+
# check that each key in the first is contained in the second
54+
for key, val in node.items():
55+
if isinstance(val, dict):
56+
continue # this gets tested as its own node
57+
58+
# check that the values at this key are equal
59+
val_path = path + (key, )
60+
try:
61+
comp_val = comp_node[key]
62+
except KeyError:
63+
standard_msg = (
64+
'Path {} exists in dict 1, but not dict 2.'
65+
.format(self._format_path(val_path))
66+
)
67+
self.fail(self._formatMessage(msg, standard_msg))
68+
69+
if (isinstance(val, np.ndarray) or
70+
isinstance(comp_val, np.ndarray)):
71+
if np.array_equal(val, comp_val):
72+
continue
73+
elif val == comp_val:
74+
continue
75+
76+
if is_num_list(val) and is_num_list(comp_val):
77+
if np.allclose(val, comp_val):
78+
continue
79+
80+
standard_msg = (
81+
'Value comparison failed at path {}.\n'
82+
'{} != {}'
83+
.format(self._format_path(val_path), val, comp_val)
84+
)
85+
self.fail(self._formatMessage(msg, standard_msg))
86+
87+
# finally, check that keys in the second are in the first
88+
for key in comp_node:
89+
val_path = path + (key, )
90+
if key not in node:
91+
standard_msg = (
92+
'Path {} exists in dict 2, but not dict 1.'
93+
.format(self._format_path(val_path))
94+
)
95+
self.fail(self._formatMessage(msg, standard_msg))

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.