def test_change_plotter_datasource_when_sorting(self): df = self.df model = self.analyzer_klass(source_df=df) plot_manager = DataFramePlotManager(data_source=df) plot_manager2 = DataFramePlotManager(data_source=df) # Connect the 3 managers: model.plot_manager_list.append(plot_manager) model.plot_manager_list.append(plot_manager2) with self.assertTraitChanges(plot_manager, "data_source"): with self.assertTraitChanges(plot_manager2, "data_source"): model.sort_by_col = "b"
def setUp(self): super(TestPlotManagerExportVega, self).setUp() if isdir(self.target_dir): rmtree(self.target_dir) self.converter = "to_vega" self.model = DataFramePlotManager(data_source=TEST_DF) self.exporter = NonInteractiveExporter( df_plotter=self.model, target_dir=self.target_dir, export_format=VEGA_FORMAT, export_data=EXPORT_NO ) self.target_filename = "temp.json" self.target_file = join(self.target_dir, self.target_filename)
def setUp(self): self.config = HistogramPlotConfigurator(data_source=TEST_DF) self.config.x_col_name = "a" self.desc = PlotDescriptor(x_col_name="a", plot_config=self.config, plot_title="Plot 0") self.config2 = BarPlotConfigurator(data_source=TEST_DF) self.config2.x_col_name = "a" self.config2.y_col_name = "b" self.desc2 = PlotDescriptor(x_col_name="a", y_col_name="b", plot_config=self.config2, plot_title="Plot 1") self.config3 = ScatterPlotConfigurator(data_source=TEST_DF) self.config3.x_col_name = "a" self.config3.y_col_name = "b" self.desc3 = PlotDescriptor(x_col_name="a", y_col_name="b", plot_config=self.config3, plot_title="Plot 2") self.config4 = ScatterPlotConfigurator(data_source=TEST_DF) self.config4.x_col_name = "a" self.config4.y_col_name = "b" self.config4.z_col_name = "d" self.desc4 = PlotDescriptor(x_col_name="a", y_col_name="b", z_col_name="d", plot_config=self.config4, plot_title="Plot 3") self.model = DataFramePlotManager(contained_plots=[self.desc], data_source=TEST_DF) self.target_dir = join(HERE, "test_dir") if isdir(self.target_dir): rmtree(self.target_dir)
def test_colored_scatter_plot_style_view(self): """ Make sure plot style displays renderer styles labeled correctly. """ # Create data for a colored scatter plot where the labels aren't sorted # alphabetically: test_df = pd.DataFrame({"Col_1": range(4), "Col_2": range(4), "Col_3": ["xyz", "fpq", "abc", "xyz"]}) config = ScatterPlotConfigurator(data_source=test_df) config.x_col_name = "Col_1" config.y_col_name = "Col_2" config.z_col_name = "Col_3" plot_manager = DataFramePlotManager(contained_plots=[config], data_source=test_df) desc = plot_manager.contained_plots[0] style = desc.plot_config.plot_style # Check view building works: all_labels = set() col_3_values = set(test_df["Col_3"].values) renderer_style_manager = style.renderer_style_manager renderer_style_manager_view = renderer_style_manager.traits_view() renderer_items = renderer_style_manager_view.content.content[0].content for group in renderer_items: group_label = group.label all_labels.add(group_label) trait_name = group.content[0].name rend_style = renderer_style_manager.trait_get(trait_name)[ trait_name ] self.assertEqual(rend_style.renderer_name, group_label) self.assertEqual(all_labels, col_3_values)
def test_export_1_plot_special_title(self): self.desc.plot_title = "blah!" model = DataFramePlotManager(contained_plots=[self.desc], data_source=TEST_DF) exporter = NonInteractiveExporter(df_plotter=model, target_dir=self.target_dir) export_func = getattr(exporter, self.converter) export_func() content = os.listdir(self.target_dir) self.assertEqual(len(content), 1) fname = content[0] self.assertEqual(fname, "0_blah.PNG")
def test_export_3_plots_no_data(self): model = DataFramePlotManager(contained_plots=[self.desc, self.desc2, self.desc3], data_source=TEST_DF) exporter = NonInteractiveExporter(df_plotter=model, target_dir=self.target_dir) export_func = getattr(exporter, self.converter) export_func() content = os.listdir(self.target_dir) self.assertEqual(len(content), 3) self.assertEqual(set(content), {"0_Plot_0.PNG", "1_Plot_1.PNG", "2_Plot_2.PNG"})
def test_export_1_plot(self): model = DataFramePlotManager(contained_plots=[self.desc], data_source=TEST_DF) exporter = NonInteractiveExporter(df_plotter=model, target_file=self.target_file) export_func = getattr(exporter, self.converter) export_func() content = os.listdir(self.target_dir) self.assertEqual(len(content), 1) fname = content[0] self.assertEqual(fname, self.target_filename) self.assert_valid_pptx(exporter)
def test_plotter_selection_connected(self): df = self.df model = self.analyzer_klass(source_df=df) plot_manager = DataFramePlotManager(data_source=df) # Connect the 2 managers: model.plot_manager_list.append(plot_manager) # Set analyzer selection: model.selected_idx = [0, 2, 5] self.assertEqual(plot_manager.index_selected, [0, 2, 5]) # Append to analyzer selection model.selected_idx.append(6) self.assertEqual(plot_manager.index_selected, [0, 2, 5, 6]) # Set analyzer selection: plot_manager.index_selected = [1, 4] self.assertEqual(model.selected_idx, [1, 4]) # Append to analyzer selection plot_manager.index_selected.append(3) self.assertEqual(model.selected_idx, [1, 4, 3])
def test_export_1_plot_export_source_data(self): model = DataFramePlotManager(contained_plots=[self.desc], data_source=TEST_DF) for fmt in [".h5", ".csv", ".xlsx"]: exporter = NonInteractiveExporter( df_plotter=model, target_file=self.target_file, export_data=EXPORT_YES, data_format=fmt ) export_func = getattr(exporter, self.converter) export_func() content = os.listdir(self.target_dir) self.assertEqual(len(content), 2) self.assertEqual(set(content), {EXTERNAL_DATA_FNAME + fmt, self.target_filename}) self.assert_valid_pptx(exporter) fname = join(self.target_dir, EXTERNAL_DATA_FNAME + fmt) self.assert_data_in_file(fname) # clean up at every loop: self.tearDown()
def test_export_multi_renderer_plot_export_source_and_plot_data(self): model = DataFramePlotManager(contained_plots=[self.desc4], data_source=TEST_DF) for fmt in [".h5", ".csv", ".xlsx"]: exporter = NonInteractiveExporter( df_plotter=model, target_file=self.target_file, export_data=EXPORT_YES, data_format=fmt, export_each_plot_data=True ) export_func = getattr(exporter, self.converter) export_func() content = os.listdir(self.target_dir) self.assertEqual(len(content), 2) if fmt in [".h5", ".xlsx"]: expected = {self.target_filename, EXTERNAL_DATA_FNAME + fmt} else: expected = {self.target_filename, EXTERNAL_DATA_FNAME + ".zip"} self.assertEqual(set(content), expected) self.assert_valid_pptx(exporter) # Check data file content: if fmt == ".csv": zip_path = join(self.target_dir, EXTERNAL_DATA_FNAME + ".zip") with ZipFile(zip_path) as f: f.extractall(join(self.target_dir, "data")) source_fname = string2filename(DEFAULT_DATASET_NAME) + ".csv" data_file = join(self.target_dir, "data", source_fname) else: data_file = join(self.target_dir, EXTERNAL_DATA_FNAME + fmt) num_d = len(set(TEST_DF["d"])) self.assert_data_in_file(data_file, num_dataset=1 + num_d) # clean up at every loop: self.tearDown()
def test_overwrite_flag(self): model = DataFramePlotManager(contained_plots=[self.desc], data_source=TEST_DF) exporter = NonInteractiveExporter( df_plotter=model, target_dir=self.target_dir, target_file=self.target_file ) export_func = getattr(exporter, self.converter) export_func() self.assertIn(self.target_filename, os.listdir(self.target_dir)) # Can't do it a second time because the file is already there... with self.assertRaises(IOError): export_func() # ... unless the overwrite flag is True: exporter = NonInteractiveExporter( df_plotter=model, target_dir=self.target_dir, overwrite_file_if_exists=True ) export_func = getattr(exporter, self.converter) export_func()
def test_export_3_plots_export_source_data(self): model = DataFramePlotManager(contained_plots=[self.desc, self.desc2, self.desc3], data_source=TEST_DF) for fmt in [".h5", ".csv", ".xlsx"]: exporter = NonInteractiveExporter(df_plotter=model, target_dir=self.target_dir, export_data=EXPORT_YES, data_format=fmt) export_func = getattr(exporter, self.converter) export_func() content = os.listdir(self.target_dir) self.assertEqual(len(content), 4) expected = {"0_Plot_0.PNG", "1_Plot_1.PNG", "2_Plot_2.PNG", EXTERNAL_DATA_FNAME + fmt} self.assertEqual(set(content), expected) # Check data file content: csv isn't zipped because there is only 1 # file: data_file = join(self.target_dir, EXTERNAL_DATA_FNAME + fmt) self.assert_data_in_file(data_file) self.tearDown()
def create_plot_manager(self, df=None, n_plots=0): if df is None: df = self.df plot_manager = DataFramePlotManager(data_source=df) if n_plots > 0: config1 = ScatterPlotConfigurator(data_source=df, plot_title="Plot1") config1.x_col_name = "a" config1.y_col_name = "b" plot_manager._add_new_plot(config1) if n_plots > 1: config2 = ScatterPlotConfigurator(data_source=df, plot_title="Plot2") config2.x_col_name = "a" config2.y_col_name = "b" plot_manager._add_new_plot(config2) return plot_manager
def setUp(self): self.model = DataFramePlotManager(data_source=TEST_DF) self.exporter = NonInteractiveExporter( df_plotter=self.model, target_dir=".", )
class TestPlotManagerExportVega(BasePlotManagerExportTester, TestCase, UnittestTools): def setUp(self): super(TestPlotManagerExportVega, self).setUp() if isdir(self.target_dir): rmtree(self.target_dir) self.converter = "to_vega" self.model = DataFramePlotManager(data_source=TEST_DF) self.exporter = NonInteractiveExporter( df_plotter=self.model, target_dir=self.target_dir, export_format=VEGA_FORMAT, export_data=EXPORT_NO ) self.target_filename = "temp.json" self.target_file = join(self.target_dir, self.target_filename) def test_export_no_plot_no_data_no_file(self): content = self.exporter.to_vega() self.assertEqual(content[CONTENT_KEY], []) self.assertEqual(content[DATASETS_KEY], {}) def test_export_no_plot_w_data_no_file(self): self.exporter.export_data = EXPORT_IN_FILE content = self.exporter.to_vega() self.assertEqual(content[CONTENT_KEY], []) self.assert_rebuild_df(content) def test_export_line_plot_w_data(self): config = LinePlotConfigurator(data_source=TEST_DF, plot_title="Plot") config.x_col_name = "a" config.y_col_name = "b" self.model._add_new_plot(config) self.exporter.export_data = EXPORT_IN_FILE content = self.exporter.to_vega() dataset = content[DATASETS_KEY][DEFAULT_DATASET_NAME] self.assertIsInstance(dataset["data"], list) self.assert_rebuild_df(content, cascading_data=False) self.assertEqual(len(content[CONTENT_KEY]), 1) expected = {'$schema': TARGET_VEGA_SCHEMA, 'data': {"name": DEFAULT_DATASET_NAME}, 'encoding': {'x': {'field': 'a', 'type': 'quantitative'}, 'y': {'field': 'b', 'type': 'quantitative'}}, 'mark': 'line'} self.assert_vega_export_equal(content[CONTENT_KEY][0], expected) def test_export_1_plot_to_file(self): config = LinePlotConfigurator(data_source=TEST_DF, plot_title="Plot") config.x_col_name = "a" config.y_col_name = "b" self.model._add_new_plot(config) self.exporter.target_file = self.target_file content = self.exporter.to_vega() self.assertTrue(isfile(self.target_file)) file_content = json.load(open(self.target_file)) self.assertEqual(content, file_content) expected = {'$schema': TARGET_VEGA_SCHEMA, 'data': {}, 'encoding': {'x': {'field': 'a', 'type': 'quantitative'}, 'y': {'field': 'b', 'type': 'quantitative'}}, 'mark': 'line'} self.assert_vega_export_equal(content[CONTENT_KEY][0], expected) self.assertEqual(content[DATASETS_KEY], {}) def test_export_2line_plots_w_data(self): config = LinePlotConfigurator(data_source=TEST_DF, plot_title="Plot") config.x_col_name = "a" config.y_col_name = "b" self.model._add_new_plot(config) config = LinePlotConfigurator(data_source=TEST_DF, plot_title="Plot2") config.x_col_name = "b" config.y_col_name = "a" self.model._add_new_plot(config) self.exporter.export_data = EXPORT_IN_FILE content = self.exporter.to_vega() self.assert_rebuild_df(content) self.assertEqual(len(content[CONTENT_KEY]), 2) expected = {'$schema': TARGET_VEGA_SCHEMA, 'data': {"name": DEFAULT_DATASET_NAME}, 'encoding': {'x': {'field': 'a', 'type': 'quantitative'}, 'y': {'field': 'b', 'type': 'quantitative'}}, 'mark': 'line'} self.assert_vega_export_equal(content[CONTENT_KEY][0], expected) expected = {'$schema': TARGET_VEGA_SCHEMA, 'data': {"name": DEFAULT_DATASET_NAME}, 'encoding': {'x': {'field': 'b', 'type': 'quantitative'}, 'y': {'field': 'a', 'type': 'quantitative'}}, 'mark': 'line'} self.assert_vega_export_equal(content[CONTENT_KEY][1], expected) def test_export_2line_plots_w_cascading_data(self): config = LinePlotConfigurator(data_source=TEST_DF, plot_title="Plot") config.x_col_name = "a" config.y_col_name = "b" self.model._add_new_plot(config) config = LinePlotConfigurator(data_source=TEST_DF, plot_title="Plot2") config.x_col_name = "b" config.y_col_name = "a" self.model._add_new_plot(config) # In the cascade style, the data is rewritten in the description of # every plot: self.exporter.export_data = EXPORT_INLINE content = self.exporter.to_vega() self.assertEqual(content[DATASETS_KEY], {}) self.assert_rebuild_df(content, cascading_data=True) self.assertEqual(len(content[CONTENT_KEY]), 2) expected = {'$schema': TARGET_VEGA_SCHEMA, 'data': {"values": df_to_vega(TEST_DF), IDX_NAME_KEY: None}, 'encoding': {'x': {'field': 'a', 'type': 'quantitative'}, 'y': {'field': 'b', 'type': 'quantitative'}}, 'mark': 'line'} self.assert_vega_export_equal(content[CONTENT_KEY][0], expected) expected = {'$schema': TARGET_VEGA_SCHEMA, 'data': {"values": df_to_vega(TEST_DF), IDX_NAME_KEY: None}, 'encoding': {'x': {'field': 'b', 'type': 'quantitative'}, 'y': {'field': 'a', 'type': 'quantitative'}}, 'mark': 'line'} self.assert_vega_export_equal(content[CONTENT_KEY][1], expected) def test_export_2scatter_plots_w_data(self): config = ScatterPlotConfigurator(data_source=TEST_DF, plot_title="Plot") config.x_col_name = "a" config.y_col_name = "b" self.model._add_new_plot(config) config = ScatterPlotConfigurator(data_source=TEST_DF, plot_title="Plot2") config.x_col_name = "b" config.y_col_name = "a" self.model._add_new_plot(config) self.exporter.export_data = EXPORT_IN_FILE content = self.exporter.to_vega() self.assert_rebuild_df(content) self.assertEqual(len(content[CONTENT_KEY]), 2) expected = {'$schema': TARGET_VEGA_SCHEMA, 'data': {"name": DEFAULT_DATASET_NAME}, 'encoding': {'x': {'field': 'a', 'type': 'quantitative'}, 'y': {'field': 'b', 'type': 'quantitative'}}, 'mark': 'point'} self.assert_vega_export_equal(content[CONTENT_KEY][0], expected) expected = {'$schema': TARGET_VEGA_SCHEMA, 'data': {"name": DEFAULT_DATASET_NAME}, 'encoding': {'x': {'field': 'b', 'type': 'quantitative'}, 'y': {'field': 'a', 'type': 'quantitative'}}, 'mark': 'point'} self.assert_vega_export_equal(content[CONTENT_KEY][1], expected) def test_export_2hist_plots_w_data(self): config = HistogramPlotConfigurator(data_source=TEST_DF, plot_title="Plot") config.x_col_name = "a" self.model._add_new_plot(config) config = HistogramPlotConfigurator(data_source=TEST_DF, plot_title="Plot2") config.x_col_name = "b" self.model._add_new_plot(config) self.exporter.export_data = EXPORT_IN_FILE content = self.exporter.to_vega() self.assert_rebuild_df(content) self.assertEqual(len(content[CONTENT_KEY]), 2) expected = {'$schema': TARGET_VEGA_SCHEMA, 'data': {"name": DEFAULT_DATASET_NAME}, 'encoding': { "x": { "bin": True, "field": "a", "type": "quantitative" }, "y": { "aggregate": "count", "type": "quantitative" } }, 'mark': 'bar'} self.assert_vega_export_equal(content[CONTENT_KEY][0], expected) expected = {'$schema': TARGET_VEGA_SCHEMA, 'data': {"name": DEFAULT_DATASET_NAME}, 'encoding': { "x": { "bin": True, "field": "b", "type": "quantitative" }, "y": { "aggregate": "count", "type": "quantitative" } }, 'mark': 'bar'} self.assert_vega_export_equal(content[CONTENT_KEY][1], expected) def test_export_multi_hist_plots_w_data(self): config = MultiHistogramPlotConfigurator(data_source=TEST_DF, plot_title="Plot {i}") config.x_col_names = ["a", "b"] self.model._add_new_plots(config) self.exporter.export_data = EXPORT_IN_FILE content = self.exporter.to_vega() self.assert_rebuild_df(content) self.assertEqual(len(content[CONTENT_KEY]), 2) expected = {'$schema': TARGET_VEGA_SCHEMA, 'data': {"name": DEFAULT_DATASET_NAME}, 'encoding': { "x": { "bin": True, "field": "a", "type": "quantitative" }, "y": { "aggregate": "count", "type": "quantitative" } }, 'mark': 'bar'} self.assert_vega_export_equal(content[CONTENT_KEY][0], expected) expected = {'$schema': TARGET_VEGA_SCHEMA, 'data': {"name": DEFAULT_DATASET_NAME}, 'encoding': { "x": { "bin": True, "field": "b", "type": "quantitative" }, "y": { "aggregate": "count", "type": "quantitative" } }, 'mark': 'bar'} self.assert_vega_export_equal(content[CONTENT_KEY][1], expected) # Assertion methods ------------------------------------------------------- def assert_vega_export_equal(self, desc1, desc2): self.assertEqual(set(desc1.keys()), set(desc2.keys())) for key in desc1: self.assertEqual(desc1[key], desc2[key], msg="{} unequal".format(key)) def assert_rebuild_df(self, content, cascading_data=False): if cascading_data: for desc in content[CONTENT_KEY]: dataset = desc["data"] idx_col = dataset[IDX_NAME_KEY] if idx_col is None: rebuilt_df = DataFrame(dataset["values"]).set_index( "index") rebuilt_df.index.name = None else: rebuilt_df = DataFrame(dataset["values"]).set_index( idx_col) assert_frame_equal(rebuilt_df, TEST_DF, check_index_type=False, check_names=False) else: datasets = content[DATASETS_KEY] for name, dataset in datasets.items(): self.assertIsInstance(dataset["data"], list) idx_col = dataset[IDX_NAME_KEY] if idx_col is None: rebuilt_df = DataFrame(dataset["data"]).set_index("index") rebuilt_df.index.name = None else: rebuilt_df = DataFrame(dataset["data"]).set_index(idx_col) assert_frame_equal(rebuilt_df, TEST_DF, check_index_type=False, check_names=False)
def base_round_trip_analysis_and_plotter_with_plot(self, style, config_klass, analysis=None, # noqa frozen=False, change_title="", **config_kw): # noqa """ Build an analysis with plots and check serialize/deserialize. """ if analysis is None: analysis = DataFrameAnalyzer(source_df=TEST_DF) data_len = len(analysis.filtered_df) orig_filter = analysis.filter_exp plot_manager = DataFramePlotManager(source_analyzer=analysis, data_source=analysis.filtered_df) configurator = config_klass( data_source=analysis.filtered_df, **config_kw ) plot_manager.add_new_plot(style, configurator) if frozen: # Setting the descriptor as frozen was requested: freeze it and # decouple the analysis: desc = plot_manager.contained_plots[0] desc.frozen = True # Change the analysis filter to test that the frozen plot is made # with the original threshold analysis.filter_exp = "Col_1 > 22" analysis.recompute_filtered_df() self.assertEqual(desc.data_filter, orig_filter) if change_title: desc = plot_manager.contained_plots[0] desc.plot_title = change_title new_analysis = self.assert_roundtrip_identical(analysis) # Manual Plotter checks: new_desc = new_analysis.plot_manager_list[0].contained_plots[0] self.assertEqual(len(new_desc.plot_config.data_source), data_len) if frozen: self.assertIsNot(new_desc.plot_config.data_source, new_analysis.filtered_df) else: self.assertIs(new_desc.plot_config.data_source, new_analysis.filtered_df) if change_title: self.assertEqual(new_desc.plot.title.text, change_title) self.assertEqual(new_desc.plot_title, change_title) self.assertEqual(new_desc.plot_config.plot_title, change_title) plot_managers = new_analysis.plot_manager_list self.assertEqual(len(plot_managers), 1) self.assertEqual(len(plot_managers[0].contained_plots), 1) plot_desc = plot_managers[0].contained_plots container_manager = plot_managers[0].canvas_manager.container_managers[0] # noqa plot_container_map = container_manager.plot_map plot_container = container_manager.container self.assertEqual(len(plot_container_map), 1) self.assertIn(plot_desc[0].plot, [plot for plot, position in plot_container_map.values()]) self.assertEqual(len(plot_container.components), 1) self.assertIs(plot_desc[0].plot, plot_container.components[0]) return new_analysis
idx_description = "Row" else: idx_description = "Column" values = [AUTO_TARGET_CONTAINER] + list(range(self.num_containers)) view = self.view_klass( HGroup( Item('plot_type', label="Select plot type"), Item('container_idx', editor=EnumEditor(values=values), label="{} #".format(idx_description), visible_when="num_containers > 1", tooltip="Can be changed later in the plot list."), ), buttons=[OKButton, CancelButton, self.man_temp_button], title="Select Plot Type and {}".format(idx_description), resizable=True, handler=ManageTemplatesHandler()) return view if __name__ == "__main__": plot_manager = DataFramePlotManager( template_interactor=FakePlotTemplateInteractor()) selector = PlotTypeSelector( num_containers=plot_manager.canvas_manager.num_container_managers, container_idx=AUTO_TARGET_CONTAINER, plot_types=plot_manager.plot_types, model=plot_manager.template_manager) ui = selector.configure_traits()