From e2280d151c2e302bc238709dc34aab9882f3107b Mon Sep 17 00:00:00 2001 From: Tanguy-DES Date: Fri, 3 Jun 2022 14:51:16 +0200 Subject: [PATCH 01/47] Ajout class Pie --- plot_data/core.py | 110 ++++++++++++++++++++++++++--------------- script/scatter_plot.py | 2 +- 2 files changed, 72 insertions(+), 40 deletions(-) diff --git a/plot_data/core.py b/plot_data/core.py index 45469bba..a7bb9386 100644 --- a/plot_data/core.py +++ b/plot_data/core.py @@ -1,29 +1,29 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ -Definition of language and plots +Created on Tue Feb 28 14:07:37 2017 + +@author: steven """ import os -import sys +import numpy as npy import math +import sys import json import tempfile import webbrowser -import warnings -from typing import List, Tuple, Any, Union - -import numpy as npy - import matplotlib.pyplot as plt -from matplotlib import patches - +import matplotlib.patches as patches from dessia_common import DessiaObject, full_classname from dessia_common.typings import Subclass from dessia_common.vectored_objects import from_csv, Catalog, ParetoSettings +import warnings + +import plot_data.templates as templates -from plot_data import templates -import plot_data.colors +from typing import List, Tuple, Any, Union +import plot_data.colors as colors npy.seterr(divide='raise') @@ -34,7 +34,7 @@ def delete_none_from_dict(dict1): """ dict2 = {} for key, value in dict1.items(): - if isinstance(value, dict): + if type(value) == dict: dict2[key] = delete_none_from_dict(value) else: if value is not None: @@ -76,7 +76,6 @@ def plot_data(self): raise NotImplementedError('It is strange to call plot_data method from a plot_data object.' f' Check the class {self.__class__.__name__} you are calling') - class HatchingSet(DessiaObject): """ A class for setting hatchings on a surface. @@ -115,7 +114,7 @@ class EdgeStyle(DessiaObject): :type dashline: List[float] """ - def __init__(self, line_width: float = None, color_stroke: plot_data.colors.Color = None, + def __init__(self, line_width: float = None, color_stroke: colors.Color = None, dashline: List[int] = None, name: str = ''): self.line_width = line_width self.color_stroke = color_stroke @@ -123,7 +122,7 @@ def __init__(self, line_width: float = None, color_stroke: plot_data.colors.Colo DessiaObject.__init__(self, name=name) -DEFAULT_EDGESTYLE = EdgeStyle(color_stroke=plot_data.colors.BLACK) +DEFAULT_EDGESTYLE = EdgeStyle(color_stroke=colors.BLACK) class PointStyle(DessiaObject): @@ -158,7 +157,7 @@ class TextStyle(DessiaObject): A class for customizing Text. :param text_color: the text's color - :type text_color: plot_data.colors.Colors + :type text_color: colors.Colors :param font_size: the font size :type font_size: float :param font_style: 'Arial', 'Verdana', 'Times New Roman', 'Courier \ @@ -179,7 +178,7 @@ class TextStyle(DessiaObject): :type angle: float """ - def __init__(self, text_color: plot_data.colors.Color = None, + def __init__(self, text_color: colors.Color = None, font_size: float = None, font_style: str = None, text_align_x: str = None, text_align_y: str = None, @@ -347,7 +346,7 @@ def mpl_plot(self, ax=None): if self.edge_style and self.edge_style.color_stroke: color = self.edge_style.color_stroke.rgb else: - color = plot_data.colors.BLACK.rgb + color = colors.BLACK.rgb ax.plot([self.data[0], self.data[2]], [self.data[1], self.data[3]], color=color) return ax @@ -372,7 +371,6 @@ class Wire(PlotDataObject): :param tooltip: a message that is displayed in a tooltip :type tooltip: str """ - def __init__(self, lines: List[Tuple[float, float]], edge_style: EdgeStyle = None, tooltip: str = None, name: str = ""): self.lines = lines @@ -502,10 +500,10 @@ def __init__(self, nb_points_x: int = 10, nb_points_y: int = 10, self.nb_points_y = nb_points_y self.graduation_style = graduation_style if graduation_style is None: - self.graduation_style = TextStyle(text_color=plot_data.colors.GREY) + self.graduation_style = TextStyle(text_color=colors.GREY) self.axis_style = axis_style if axis_style is None: - self.axis_style = EdgeStyle(color_stroke=plot_data.colors.LIGHTGREY) + self.axis_style = EdgeStyle(color_stroke=colors.LIGHTGREY) self.arrow_on = arrow_on self.grid_on = grid_on PlotDataObject.__init__(self, type_='axis', name=name) @@ -539,11 +537,11 @@ def __init__(self, attributes: List[str] = None, self.text = text self.surface_style = surface_style if surface_style is None: - self.surface_style = SurfaceStyle(color_fill=plot_data.colors.LIGHTBLUE, + self.surface_style = SurfaceStyle(color_fill=colors.LIGHTBLUE, opacity=0.75) self.text_style = text_style if text_style is None: - self.text_style = TextStyle(text_color=plot_data.colors.BLACK, font_size=10) + self.text_style = TextStyle(text_color=colors.BLACK, font_size=10) self.tooltip_radius = tooltip_radius PlotDataObject.__init__(self, type_='tooltip', name=name) @@ -611,7 +609,7 @@ class Graph2D(PlotDataObject): :type log_scale_y: bool """ - def __init__(self, graphs: List[Dataset], x_variable: str, y_variable: str, + def __init__(self, graphs: List[Dataset], x_variable: str, y_variable:str, axis: Axis = None, log_scale_x: bool = None, log_scale_y: bool = None, name: str = ''): self.graphs = graphs @@ -645,16 +643,13 @@ class Heatmap(DessiaObject): Heatmap is a scatter plot's view. This class contains the Heatmap's parameters. :param size: A tuple of two integers corresponding to the number of squares on the horizontal and vertical sides. :type size: Tuple[int, int] - :param colors: The list of colors ranging from low density to high density, \ - e.g. colors=[plot_data.colors.BLUE, plot_data.colors.RED] \ + :param colors: The list of colors ranging from low density to high density, e.g. colors=[colors.BLUE, colors.RED] \ so the low density areas tend to be blue while higher density areas tend to be red. :type colors: List[Colors] :param edge_style: The areas separating lines settings :type edge_style: EdgeStyle """ - - def __init__(self, size: Tuple[int, int] = None, colors: List[plot_data.colors.Color] = None, - edge_style: EdgeStyle = None, name: str = ''): + def __init__(self, size: Tuple[int, int]=None, colors:List[colors.Color]=None, edge_style:EdgeStyle=None, name:str=''): self.size = size self.colors = colors self.edge_style = edge_style @@ -714,6 +709,43 @@ def __init__(self, x_variable: str, y_variable: str, self.heatmap = heatmap self.heatmap_view = heatmap_view PlotDataObject.__init__(self, type_='scatterplot', name=name) + + +class Pie(PlotDataObject): + """ + A class for drawing pie plots. + + :param elements: A list of vectors. Vectors must have the same \ + attributes (ie the same keys) + :type elements: List[dict] + :param x_variable: variable that you want to display on x axis + :type x_variable: str + :param tooltip: an object containing all information needed for \ + drawing tooltips + :type tooltip: Tooltip + :param point_style: for points' customization + :type point_style: PointStyle + """ + + def __init__(self, x_variable: str, elements: List[Any] = None, + tooltip: Tooltip = None, + point_style: PointStyle = None, + edge_style: EdgeStyle = None, + axis: Axis = None, + name: str = ''): + + self.tooltip = tooltip + self.x_variable = x_variable + self.point_style = point_style + if not elements: + self.elements = [] + else: + self.elements = elements + if not axis: + self.axis = Axis() + else: + self.axis = axis + PlotDataObject.__init__(self, type_='pieplot', name=name) class ScatterMatrix(PlotDataObject): @@ -783,7 +815,7 @@ def mpl_plot(self, ax=None): if self.edge_style: edgecolor = self.edge_style.color_stroke else: - edgecolor = plot_data.colors.BLACK.rgb + edgecolor = colors.BLACK.rgb ax.add_patch( patches.Arc((self.cx, self.cy), 2 * self.r, 2 * self.r, angle=0, @@ -828,8 +860,8 @@ def bounding_box(self): for plot_data_primitive in self.plot_data_primitives: if hasattr(plot_data_primitive, 'bounding_box'): bb = plot_data_primitive.bounding_box() - xmin, xmax, ymin, ymax = min(xmin, bb[0]), max(xmax, bb[1]), \ - min(ymin, bb[2]), max(ymax, bb[3]) + xmin, xmax, ymin, ymax = min(xmin, bb[0]), max(xmax,bb[1]), \ + min(ymin, bb[2]), max(ymax, bb[3]) return xmin, xmax, ymin, ymax @@ -891,8 +923,8 @@ class PrimitiveGroup(PlotDataObject): Circle2D, Line2D, MultipleLabels, Wire]] """ - def __init__(self, primitives: List[Union[Contour2D, Arc2D, LineSegment2D, - Circle2D, Line2D, MultipleLabels, Wire]], + def __init__(self, primitives: List[Union[Contour2D, Arc2D, LineSegment2D, \ + Circle2D, Line2D, MultipleLabels, Wire]], name: str = ''): self.primitives = primitives PlotDataObject.__init__(self, type_='primitivegroup', name=name) @@ -956,7 +988,7 @@ def __init__(self, primitive_groups: List[PrimitiveGroup], if not isinstance(value, PrimitiveGroup): primitive_groups[i] = PrimitiveGroup(primitives=value) self.primitive_groups = primitive_groups - if sizes is not None and isinstance(sizes[0], int): + if sizes is not None and type(sizes[0]) == int: sizes = [sizes] * len(primitive_groups) self.sizes = sizes self.coords = coords @@ -1139,7 +1171,7 @@ def plot_canvas(plot_data_object: Subclass[PlotDataObject], plot_type = data['type_'] if plot_type == 'primitivegroup': template = templates.contour_template - elif plot_type in ('scatterplot', 'graph2d'): + elif plot_type == 'scatterplot' or plot_type == 'graph2d': template = templates.scatter_template elif plot_type == 'parallelplot': template = templates.parallelplot_template @@ -1224,9 +1256,9 @@ def bounding_box(plot_datas: Subclass[PlotDataObject]): :rtype: float, float, float, float """ xmin, xmax, ymin, ymax = math.inf, -math.inf, math.inf, -math.inf - for plot in plot_datas: - if hasattr(plot, 'bounding_box'): - bb = plot.bounding_box() + for plot_data in plot_datas: + if hasattr(plot_data, 'bounding_box'): + bb = plot_data.bounding_box() xmin, xmax = min(xmin, bb[0]), max(xmax, bb[1]) ymin, ymax = min(ymin, bb[2]), max(ymax, bb[3]) diff --git a/script/scatter_plot.py b/script/scatter_plot.py index b4bbf486..86d22b71 100644 --- a/script/scatter_plot.py +++ b/script/scatter_plot.py @@ -17,7 +17,7 @@ scatterplot = plot_data.Scatter(elements=elements, - x_variable='mass', y_variable='length') + x_variable='shape', y_variable='length') # The previous scripts shows the simplest way of creating a scatterplot. # However, many options are available for further customization From d83ec07a844f310f13070d8291dee3021a275239 Mon Sep 17 00:00:00 2001 From: Tanguy-DES Date: Tue, 7 Jun 2022 10:05:24 +0200 Subject: [PATCH 02/47] Start with piechart --- plot_data/core.py | 70 ++++++++++++++++++++--- plot_data/templates.py | 32 +++++++++++ script/pie_chart.py | 35 ++++++++++++ src/plot-data.ts | 60 ++++++++++++++++++- src/primitives.ts | 127 +++++++++++++++++++++++++++++++++++++++++ src/subplots.ts | 121 ++++++++++++++++++++++++++++++++++++++- src/toolbox.ts | 68 ++++++++++++++++++++++ 7 files changed, 503 insertions(+), 10 deletions(-) create mode 100644 script/pie_chart.py diff --git a/plot_data/core.py b/plot_data/core.py index a7bb9386..dc610167 100644 --- a/plot_data/core.py +++ b/plot_data/core.py @@ -710,8 +710,60 @@ def __init__(self, x_variable: str, y_variable: str, self.heatmap_view = heatmap_view PlotDataObject.__init__(self, type_='scatterplot', name=name) + +# class PieChart(PlotDataObject): +# """ +# A class for drawing scatter plots. + +# :param elements: A list of vectors. Vectors must have the same \ +# attributes (ie the same keys) +# :type elements: List[dict] +# :param x_variable: variable that you want to display on x axis +# :type x_variable: str +# :param y_variable: variable that you want to display on y axis +# :type y_variable: str +# :param tooltip: an object containing all information needed for \ +# drawing tooltips +# :type tooltip: Tooltip +# :param point_style: for points' customization +# :type point_style: PointStyle +# :param axis: an object containing all information needed for \ +# drawing axis +# :type axis: Axis +# :param log_scale_x: True or False +# :type log_scale_x: bool +# :param log_scale_y: True or False +# :type log_scale_y: bool +# :param heatmap: Heatmap view settings +# :type heatmap: Heatmap +# :param heatmap_view: Heatmap view when loading the object. If set \ +# to False, you'd still be able to enable it using the button. +# :type heatmap_view: bool +# """ + +# def __init__(self, x_variable: str, y_variable: str, +# tooltip: Tooltip = None, +# point_style: PointStyle = None, +# elements: List[Any] = None, axis: Axis = None, +# heatmap: Heatmap = None, heatmap_view: bool = None, +# name: str = ''): +# self.tooltip = tooltip +# self.attribute_names = [x_variable, y_variable] +# self.point_style = point_style +# if not elements: +# self.elements = [] +# else: +# self.elements = elements +# if not axis: +# self.axis = Axis() +# else: +# self.axis = axis +# self.heatmap = heatmap +# self.heatmap_view = heatmap_view +# PlotDataObject.__init__(self, type_='piechart', name=name) + -class Pie(PlotDataObject): +class PieChart(PlotDataObject): """ A class for drawing pie plots. @@ -728,14 +780,14 @@ class Pie(PlotDataObject): """ def __init__(self, x_variable: str, elements: List[Any] = None, - tooltip: Tooltip = None, - point_style: PointStyle = None, - edge_style: EdgeStyle = None, - axis: Axis = None, - name: str = ''): + tooltip: Tooltip = None, + point_style: PointStyle = None, + edge_style: EdgeStyle = None, + axis: Axis = None, + name: str = ''): self.tooltip = tooltip - self.x_variable = x_variable + self.attribute_names = [x_variable] self.point_style = point_style if not elements: self.elements = [] @@ -745,7 +797,7 @@ def __init__(self, x_variable: str, elements: List[Any] = None, self.axis = Axis() else: self.axis = axis - PlotDataObject.__init__(self, type_='pieplot', name=name) + PlotDataObject.__init__(self, type_='piechart', name=name) class ScatterMatrix(PlotDataObject): @@ -1183,6 +1235,8 @@ def plot_canvas(plot_data_object: Subclass[PlotDataObject], template = templates.histogram_template elif plot_type == "scattermatrix": template = templates.scatter_matrix_template + elif plot_type == "piechart": + template = templates.piechart_template else: raise NotImplementedError('Type {} not implemented'.format(plot_type)) diff --git a/plot_data/templates.py b/plot_data/templates.py index 99dced8a..a3a946ae 100644 --- a/plot_data/templates.py +++ b/plot_data/templates.py @@ -225,3 +225,35 @@ ''') + + +piechart_template = Template(''' + + + + + +
+ + + + + + +
+ +''') \ No newline at end of file diff --git a/script/pie_chart.py b/script/pie_chart.py new file mode 100644 index 00000000..1e2d1ec8 --- /dev/null +++ b/script/pie_chart.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Fri Jun 3 16:18:31 2022 + +@author: tanguy +""" + +import plot_data +import plot_data.colors as colors +import random + + +elements = [] +SHAPES = ['round', 'square', 'triangle', 'ellipse'] +COLORS = [colors.RED, colors.BLUE, colors.GREEN, colors.YELLOW, colors.ORANGE, colors.VIOLET] +for i in range(50): + random_shape = SHAPES[random.randint(0, len(SHAPES) - 1)] + random_color = COLORS[random.randint(0, len(SHAPES) - 1)] + elements.append({'mass': random.uniform(0, 50), + 'length': random.uniform(0, 100), + 'shape': random_shape, + 'color': random_color + }) + + +piechart = plot_data.PieChart(elements=elements, + x_variable='mass') + +# piechart = plot_data.PieChart(elements=elements, +# x_variable='shape', y_variable='length') + + + +plot_data.plot_canvas(plot_data_object=piechart, debug_mode=True) \ No newline at end of file diff --git a/src/plot-data.ts b/src/plot-data.ts index dd3ae28e..792b835c 100644 --- a/src/plot-data.ts +++ b/src/plot-data.ts @@ -1,5 +1,5 @@ import { heatmap_color, string_to_hex } from "./color_conversion"; -import { Point2D, PrimitiveGroup, Contour2D, Circle2D, Dataset, Graph2D, Scatter, Heatmap, Wire } from "./primitives"; +import { Point2D, PrimitiveGroup, Contour2D, Circle2D, Dataset, Graph2D, Scatter, Heatmap, Wire, PieChart } from "./primitives"; import { Attribute, PointFamily, Axis, Tooltip, Sort, permutator } from "./utils"; import { EdgeStyle } from "./style"; import { Shape, List, MyMath } from "./toolbox"; @@ -774,6 +774,64 @@ export abstract class PlotData { } } + + draw_piechart(d:PieChart, hidden, mvx, mvy) { + if (d['type_'] == 'piechart') { + var r:Circle2D = new Circle2D(d, this.width/this.scaleX/2, this.height/this.scaleY/2, + 5, d.edge_style, d.surface_style, d.tooltip, this.type_, this.name); + + this.context.beginPath(); + this.draw_circle(hidden, mvx, mvy, this.scaleX, this.scaleY, r); + this.context.fill(); + this.context.stroke(); + this.context.closePath(); + console.log(d) + /* for (var i=0; imax) { + max = elt; + } + if (elt 20) && (this.button_h > 10)) { + this.refresh_buttons_coords(); + + //Drawing the zooming button + Buttons.zoom_button(this.button_x, this.zoom_rect_y, this.button_w, this.button_h, this); + + //Drawing the button for zooming window selection + Buttons.zoom_window_button(this.button_x,this.zw_y,this.button_w,this.button_h, this); + + //Drawing the reset button + Buttons.reset_button(this.button_x, this.reset_rect_y, this.button_w, this.button_h, this); + + //Drawing the selection button + Buttons.selection_button(this.button_x, this.select_y, this.button_w, this.button_h, this); + + //Drawing the enable/disable graph button + Buttons.graph_buttons(this.graph1_button_y, this.graph1_button_w, this.graph1_button_h, '10px Arial', this); + + if (this.plotObject.type_ == 'scatterplot') { + // TODO To check, 'this' in args is weird + Buttons.merge_button(this.button_x, this.merge_y, this.button_w, this.button_h, '10px Arial', this); + } + + //draw permanent window button + Buttons.perm_window_button(this.button_x, this.perm_button_y, this.button_w, this.button_h, '10px Arial', this); + + //draw clear point button + Buttons.clear_point_button(this.button_x, this.clear_point_button_y, this.button_w, this.button_h, '10px Arial', this); + + // Draw log scale buttons + Buttons.log_scale_buttons(this.button_x, this.xlog_button_y, this.ylog_button_y, this.button_w, this.button_h, + "10px Arial", this); + + // Draw Heatmap button + Buttons.heatmap_button(this.button_x, this.heatmap_button_y, this.button_w, this.button_h, "10px Arial", this); + } + if (this.multiplot_manipulation) { + this.draw_manipulable_rect(); + } + this.context.restore(); + } +} + + /** A class thtat inherits from PlotData and is specific for drawing ParallelPlots */ export class ParallelPlot extends PlotData { diff --git a/src/toolbox.ts b/src/toolbox.ts index 3b9fb3fa..26afead8 100644 --- a/src/toolbox.ts +++ b/src/toolbox.ts @@ -1,3 +1,4 @@ +import { ListenOptions } from "net"; import { string_to_hex } from "./color_conversion"; import { equals } from "./utils"; @@ -161,6 +162,73 @@ export class Shape { context.globalAlpha = 1; context.setLineDash([]); } + + /** + * Draws a triangle on canvas. + * @param xa the triangle's node a x coordinate + * @param ya the triangle's node a y coordinate + * @param xb the triangle's node b x coordinate + * @param yb the triangle's node b y coordinate + * @param xc the triangle's node c x coordinate + * @param yc the triangle's node c y coordinate + * @param context canvas' context + * @param color_fill the rectangle's fill color. Can be set to 'No' if the rectangle + doesn't have to be filled. + * @param color_stroke its stroke color. It can be set to 'No' if a contour isn't needed. + * @param line_width its contour's line width. + * @param opacity The opacity inside (from 0 to 1). + * @param dashline contour's dashline ([] for no dashline). A pattern list [a_0,..., a_n] where a_i represents the number of filled pixels is i%2 == 0 + and the number of empty pixels if i%2 != 0. + */ + public static triangle(xa, ya, xb, yb, xc, yc, context, color_fill='No', color_stroke=string_to_hex('black'), line_width=1, opacity=1, dashline=[]) { + context.beginPath(); + context.setLineDash(dashline); + context.fillStyle = color_fill; + context.strokeStyle = color_stroke; + context.lineWidth = line_width; + context.globalAlpha = opacity; + context.drawLine([[xa, ya], [xb, yb], [xc, yc], [xa, ya]]); + if (color_fill != 'No') { context.fill(); } + if (color_stroke != 'No') { context.stroke(); } + context.closePath(); + context.globalAlpha = 1; + context.setLineDash([]); + } + + /** + * Draws an round triangle on canvas. + * @param xa the triangle's node a x coordinate + * @param ya the triangle's node a y coordinate + * @param xb the triangle's node b x coordinate + * @param yb the triangle's node b y coordinate + * @param xc the triangle's node c x coordinate + * @param yc the triangle's node c y coordinate + * @param radius the radius of the arc on triangle + * @param context canvas' context + * @param color_fill the rectangle's fill color. Can be set to 'No' if the rectangle + doesn't have to be filled. + * @param color_stroke its stroke color. It can be set to 'No' if a contour isn't needed. + * @param line_width its contour's line width. + * @param opacity The opacity inside (from 0 to 1). + * @param dashline contour's dashline ([] for no dashline). A pattern list [a_0,..., a_n] where a_i represents the number of filled pixels is i%2 == 0 + and the number of empty pixels if i%2 != 0. + */ + public static roundTriangle(xa, ya, xb, yb, xc, yc, radius, context, color_fill='No', color_stroke=string_to_hex('black'), line_width=1, opacity=1, dashline=[]) { + context.beginPath(); + context.setLineDash(dashline); + context.fillStyle = color_fill; + context.strokeStyle = color_stroke; + context.lineWidth = line_width; + context.globalAlpha = opacity; + context.drawLine([[xa, ya], [xb, yb]]); + context.arcTo(xb, yb, xc, yc, radius); + context.drawLine([[xc, yc], [xa, ya]]); + if (color_fill != 'No') { context.fill(); } + if (color_stroke != 'No') { context.stroke(); } + context.closePath(); + context.globalAlpha = 1; + context.setLineDash([]); + } /** * From d5b2e4bf2ae72b4bb149c60147c2dbbcf6c7ccd2 Mon Sep 17 00:00:00 2001 From: Tanguy-DES Date: Tue, 7 Jun 2022 16:56:30 +0200 Subject: [PATCH 03/47] feat(piechart): first piechart drawing --- src/plot-data.ts | 1683 +++++++++++++++++++++++----------------------- src/subplots.ts | 1 - src/toolbox.ts | 6 +- 3 files changed, 854 insertions(+), 836 deletions(-) diff --git a/src/plot-data.ts b/src/plot-data.ts index 792b835c..2b5cc6a9 100644 --- a/src/plot-data.ts +++ b/src/plot-data.ts @@ -9,182 +9,182 @@ import { rgb_to_hex, tint_rgb, hex_to_rgb, rgb_to_string, get_interpolation_colo /** PlotData is the key class for displaying data. It contains numerous parameters and methods * for that purpose. It is inherited by more specific data-visualization objects such as * PlotScatter, PlotContour, ParallelPlot and PrimitiveGroupContainer - */ + */ export abstract class PlotData { - type_:string; - name:string = ""; - context_show:any; - context_hidden:any; - context:any; - minX:number=Infinity; - maxX:number=-Infinity; - minY:number=Infinity; - maxY:number=-Infinity; - init_scale:number=1; - init_scaleX:number=1; - init_scaleY:number=1; - scale:number=1; - scaleX:number=1; - scaleY:number=1; - scroll_x:number=0; - scroll_y:number=0; - initial_originX:number=0; - initial_originY:number=0; - initial_width:number=0; - initial_height:number = 0; - originX:number=0; - originY:number=0; - settings_on:boolean=false; - color_to_plot_data:any={}; - select_on_mouse:any; - select_on_mouse_indices:number[]=[]; - primitive_mouse_over_point:Point2D; - select_on_click:any[]=[]; // For scatter and graph2D, it corresponds points selected bythe selection window - heatmap_selected_points:any[]=[]; - heatmap_selected_points_indices:number[]=[]; - clicked_points:any[]=[]; - selected_point_index:any[]=[]; - clicked_point_index:any[]=[]; - color_surface_on_mouse:string=string_to_hex('lightskyblue'); - color_surface_selected:string=string_to_hex('blue'); - color_surface_on_click:string=string_to_hex("red"); - color_heatmap_selection:string=string_to_hex("brown"); - - pointLength:number=0; - tooltip_ON:boolean = false; - axis_ON:boolean = false; - link_object_ON:boolean = false; - index_first_in:number; - index_last_in:number; - nb_points_in:number; - graph_ON:boolean=false; - isParallelPlot:boolean=false; - interaction_ON:boolean = true; - x_nb_digits:number = 0; - y_nb_digits:number = 0; - multiplot_manipulation:boolean=false; - fusion_coeff:number=1.2; + type_: string; + name: string = ""; + context_show: any; + context_hidden: any; + context: any; + minX: number = Infinity; + maxX: number = -Infinity; + minY: number = Infinity; + maxY: number = -Infinity; + init_scale: number = 1; + init_scaleX: number = 1; + init_scaleY: number = 1; + scale: number = 1; + scaleX: number = 1; + scaleY: number = 1; + scroll_x: number = 0; + scroll_y: number = 0; + initial_originX: number = 0; + initial_originY: number = 0; + initial_width: number = 0; + initial_height: number = 0; + originX: number = 0; + originY: number = 0; + settings_on: boolean = false; + color_to_plot_data: any = {}; + select_on_mouse: any; + select_on_mouse_indices: number[] = []; + primitive_mouse_over_point: Point2D; + select_on_click: any[] = []; // For scatter and graph2D, it corresponds points selected bythe selection window + heatmap_selected_points: any[] = []; + heatmap_selected_points_indices: number[] = []; + clicked_points: any[] = []; + selected_point_index: any[] = []; + clicked_point_index: any[] = []; + color_surface_on_mouse: string = string_to_hex('lightskyblue'); + color_surface_selected: string = string_to_hex('blue'); + color_surface_on_click: string = string_to_hex("red"); + color_heatmap_selection: string = string_to_hex("brown"); + + pointLength: number = 0; + tooltip_ON: boolean = false; + axis_ON: boolean = false; + link_object_ON: boolean = false; + index_first_in: number; + index_last_in: number; + nb_points_in: number; + graph_ON: boolean = false; + isParallelPlot: boolean = false; + interaction_ON: boolean = true; + x_nb_digits: number = 0; + y_nb_digits: number = 0; + multiplot_manipulation: boolean = false; + fusion_coeff: number = 1.2; log_scale_x: boolean = false; log_scale_y: boolean = true; - plotObject:any; - plot_datas:object={}; - tooltip_list:any[]=[]; - button_x:number=0; - button_w:number=0; - button_h:number=0; - zoom_rect_y:number=0; - zw_bool:boolean=false; - zw_y:number=0; - reset_rect_y:number=0; - select_bool:boolean=false; - select_y:number=0; - sort_list_points:any[]=[]; - graph_to_display:boolean[]=[]; - graph1_button_x:number=0; - graph1_button_y:number=0; - graph1_button_w:number=0; - graph1_button_h:number=0; - nb_graph:number = 0; - mergeON:boolean=false; - merge_y:number=0; - permanent_window:boolean=true; - perm_button_y:number=0; - perm_window_x:number=0; - perm_window_y:number=0; - perm_window_w:number=0; - perm_window_h:number=0; - initial_permW:number=0; - initial_permH:number=0; - graph_colorlist:string[]=[]; - graph_name_list:string[]=[]; - graph_text_spacing_list:number[]=[]; + plotObject: any; + plot_datas: object = {}; + tooltip_list: any[] = []; + button_x: number = 0; + button_w: number = 0; + button_h: number = 0; + zoom_rect_y: number = 0; + zw_bool: boolean = false; + zw_y: number = 0; + reset_rect_y: number = 0; + select_bool: boolean = false; + select_y: number = 0; + sort_list_points: any[] = []; + graph_to_display: boolean[] = []; + graph1_button_x: number = 0; + graph1_button_y: number = 0; + graph1_button_w: number = 0; + graph1_button_h: number = 0; + nb_graph: number = 0; + mergeON: boolean = false; + merge_y: number = 0; + permanent_window: boolean = true; + perm_button_y: number = 0; + perm_window_x: number = 0; + perm_window_y: number = 0; + perm_window_w: number = 0; + perm_window_h: number = 0; + initial_permW: number = 0; + initial_permH: number = 0; + graph_colorlist: string[] = []; + graph_name_list: string[] = []; + graph_text_spacing_list: number[] = []; decalage_axis_x = 50; decalage_axis_y = 20; - last_point_list:any[]=[]; - scatter_points:Point2D[]=[]; - scatter_init_points:Point2D[]=[]; - refresh_point_list_bool:boolean=true; - sc_interpolation_ON: boolean=false; - isSelectingppAxis:boolean=false; - zoom_box_x:number=0; - zoom_box_y:number=0; - zoom_box_w:number=0; - zoom_box_h:number=0; - clear_point_button_y:number=0; + last_point_list: any[] = []; + scatter_points: Point2D[] = []; + scatter_init_points: Point2D[] = []; + refresh_point_list_bool: boolean = true; + sc_interpolation_ON: boolean = false; + isSelectingppAxis: boolean = false; + zoom_box_x: number = 0; + zoom_box_y: number = 0; + zoom_box_w: number = 0; + zoom_box_h: number = 0; + clear_point_button_y: number = 0; xlog_button_y: number = 0; ylog_button_y: number = 0; heatmap_button_y: number = 0; - all_attributes:Attribute[]=[]; - attribute_booleans:boolean[]=[]; - axis_list:Attribute[]=[]; - to_display_list:any[]=[]; + all_attributes: Attribute[] = []; + attribute_booleans: boolean[] = []; + axis_list: Attribute[] = []; + to_display_list: any[] = []; axis_y_start = 0 axis_y_end = 0 - y_step:number=0; - axis_x_start:number=0; - axis_x_end:number=0; - x_step:number=0; - move_index:number = -1; - elements:any; - vertical:boolean=false; - disp_x:number = 0; - disp_y:number = 0; - disp_w:number = 0; - disp_h:number = 0; - selected_axis_name:string=''; - inverted_axis_list:boolean[]=[]; - rubber_bands:any[]=[]; - rubber_last_min:number=0; - rubber_last_max:number=0; - edge_style:EdgeStyle; - bandWidth:number=30; - bandColor:string=string_to_hex('lightblue'); - bandOpacity:number=0.5; - axisNameSize:number=12; - gradSize:number=10; - axisNbGrad:number=10; - interpolation_colors:string[]=[]; - rgbs:[number, number, number][]=[]; - hexs:string[]; - pp_selected:any[]=[]; - pp_selected_index:number[]=[]; - click_on_button:boolean=false; - vertical_axis_coords:number[][]=[]; - horizontal_axis_coords:number[][]=[]; - display_list_to_elements_dict:any; - - initial_rect_color_stroke:string=string_to_hex('grey'); - initial_rect_line_width:number=0.2; - initial_rect_dashline:number[]=[]; - manipulation_rect_color_fill:string=string_to_hex('lightblue'); - manipulation_rect_color_stroke:string=string_to_hex('black'); - manipulation_rect_line_width:number=1; - manipulation_rect_opacity:number=0.3; - manipulation_rect_dashline:number[]=[15,15]; - - isSelecting:boolean=false; - selection_coords:[number, number][]=[]; - is_drawing_rubber_band:boolean=false; - rubberbands_dep:[string, [number, number]][]=[]; - - point_families:PointFamily[]=[]; - latest_selected_points:Point2D[]=[]; - latest_selected_points_index:number[]=[]; + y_step: number = 0; + axis_x_start: number = 0; + axis_x_end: number = 0; + x_step: number = 0; + move_index: number = -1; + elements: any; + vertical: boolean = false; + disp_x: number = 0; + disp_y: number = 0; + disp_w: number = 0; + disp_h: number = 0; + selected_axis_name: string = ''; + inverted_axis_list: boolean[] = []; + rubber_bands: any[] = []; + rubber_last_min: number = 0; + rubber_last_max: number = 0; + edge_style: EdgeStyle; + bandWidth: number = 30; + bandColor: string = string_to_hex('lightblue'); + bandOpacity: number = 0.5; + axisNameSize: number = 12; + gradSize: number = 10; + axisNbGrad: number = 10; + interpolation_colors: string[] = []; + rgbs: [number, number, number][] = []; + hexs: string[]; + pp_selected: any[] = []; + pp_selected_index: number[] = []; + click_on_button: boolean = false; + vertical_axis_coords: number[][] = []; + horizontal_axis_coords: number[][] = []; + display_list_to_elements_dict: any; + + initial_rect_color_stroke: string = string_to_hex('grey'); + initial_rect_line_width: number = 0.2; + initial_rect_dashline: number[] = []; + manipulation_rect_color_fill: string = string_to_hex('lightblue'); + manipulation_rect_color_stroke: string = string_to_hex('black'); + manipulation_rect_line_width: number = 1; + manipulation_rect_opacity: number = 0.3; + manipulation_rect_dashline: number[] = [15, 15]; + + isSelecting: boolean = false; + selection_coords: [number, number][] = []; + is_drawing_rubber_band: boolean = false; + rubberbands_dep: [string, [number, number]][] = []; + + point_families: PointFamily[] = []; + latest_selected_points: Point2D[] = []; + latest_selected_points_index: number[] = []; // primitive_group_container's attributes - manipulation_bool:boolean=false; - button_y:number=0; - manip_button_x:number=0; - reset_button_x:number=0; - display_order:number[]=[]; - shown_datas:any[]=[]; - hidden_datas:any[]=[]; - clickedPlotIndex:number=-1; - primitive_dict:any={}; - elements_dict:any={}; - dep_mouse_over:boolean=false; + manipulation_bool: boolean = false; + button_y: number = 0; + manip_button_x: number = 0; + reset_button_x: number = 0; + display_order: number[] = []; + shown_datas: any[] = []; + hidden_datas: any[] = []; + clickedPlotIndex: number = -1; + primitive_dict: any = {}; + elements_dict: any = {}; + dep_mouse_over: boolean = false; // Heatmap heatmap: Heatmap; @@ -192,7 +192,7 @@ export abstract class PlotData { selected_areas: number[][]; public constructor( - public data:any, + public data: any, public width: number, public height: number, public buttons_ON: boolean, @@ -200,29 +200,29 @@ export abstract class PlotData { public Y: number, public canvas_id: string, public is_in_multiplot: boolean = false) { - this.initial_width = width; - this.initial_height = height; - this.name = data["name"]; - } + this.initial_width = width; + this.initial_height = height; + this.name = data["name"]; + } abstract draw(); abstract draw_from_context(hidden); - define_canvas(canvas_id: string):void { - var canvas:any = document.getElementById(canvas_id); + define_canvas(canvas_id: string): void { + var canvas: any = document.getElementById(canvas_id); canvas.width = this.width; - canvas.height = this.height; + canvas.height = this.height; this.context_show = canvas.getContext("2d"); - var hiddenCanvas:any = document.createElement("canvas", { is : canvas_id }); + var hiddenCanvas: any = document.createElement("canvas", { is: canvas_id }); hiddenCanvas.id = canvas_id + '_hidden'; - hiddenCanvas.width = this.width; - hiddenCanvas.height = this.height; + hiddenCanvas.width = this.width; + hiddenCanvas.height = this.height; this.context_hidden = hiddenCanvas.getContext("2d"); } - set_canvas_size(width:number, height:number): void { + set_canvas_size(width: number, height: number): void { this.width = width; this.height = height; } @@ -232,11 +232,11 @@ export abstract class PlotData { this.draw(); } - refresh_MinMax(point_list, is_graph2D=false):void { + refresh_MinMax(point_list, is_graph2D = false): void { if (!is_graph2D) { this.minX = Infinity; this.maxX = -Infinity; this.minY = Infinity; this.maxY = -Infinity; } - for (var j=0; j=0) && (pr_x<=this.width) && - (pr_y+pr_h>0) && (pr_y<=this.height); + let pr_x = scaleX * d.primitives[i].minX + mvx; + let pr_y = scaleY * d.primitives[i].minY + mvy; + let pr_w = scaleX * (d.primitives[i].maxX - d.primitives[i].minX); + let pr_h = scaleY * (d.primitives[i].maxY - d.primitives[i].minY); + var is_inside_canvas = (pr_x + pr_w >= 0) && (pr_x <= this.width) && + (pr_y + pr_h > 0) && (pr_y <= this.height); if (need_check.includes(d.primitives[i].type_) && !is_inside_canvas) continue; if (d.primitives[i].type_ === 'contour') { this.draw_contour(hidden, mvx, mvy, scaleX, scaleY, d.primitives[i]); @@ -370,7 +370,7 @@ export abstract class PlotData { this.draw_wire(hidden, d.primitives[i]); // tooltips drawn in mouse_move_interaction() } - this.context.closePath(); + this.context.closePath(); } } } @@ -394,8 +394,8 @@ export abstract class PlotData { this.context.setLineDash([]); } - - draw_contour(hidden, mvx, mvy, scaleX, scaleY, d:Contour2D) { + + draw_contour(hidden, mvx, mvy, scaleX, scaleY, d: Contour2D) { if (hidden) { this.context.fillStyle = d.hidden_color; } else { @@ -407,7 +407,7 @@ export abstract class PlotData { this.context.fill(); this.context.globalAlpha = 1; if (d.surface_style.hatching != null) { - this.context.fillStyle = this.context.createPattern(d.surface_style.hatching.canvas_hatching,'repeat'); + this.context.fillStyle = this.context.createPattern(d.surface_style.hatching.canvas_hatching, 'repeat'); } if (this.select_on_mouse == d) { this.context.fillStyle = this.color_surface_on_mouse; @@ -422,15 +422,15 @@ export abstract class PlotData { for (var j = 0; j < d.plot_data_primitives.length; j++) { let elem = d.plot_data_primitives[j]; if (j == 0) var first_elem = true; else first_elem = false; - if (elem.type_ == 'linesegment2d') elem.draw(this.context, first_elem, mvx, mvy, scaleX, scaleY, this.X, this.Y); - else elem.contour_draw(this.context, first_elem, mvx, mvy, scaleX, scaleY, this.X, this.Y); + if (elem.type_ == 'linesegment2d') elem.draw(this.context, first_elem, mvx, mvy, scaleX, scaleY, this.X, this.Y); + else elem.contour_draw(this.context, first_elem, mvx, mvy, scaleX, scaleY, this.X, this.Y); } this.context.stroke(); this.context.fill(); this.context.setLineDash([]); } - draw_circle(hidden, mvx, mvy, scaleX, scaleY, d:Circle2D) { + draw_circle(hidden, mvx, mvy, scaleX, scaleY, d: Circle2D) { if (hidden) { this.context.fillStyle = d.hidden_color; d.draw(this.context, mvx, mvy, scaleX, scaleY, this.X, this.Y); @@ -445,7 +445,7 @@ export abstract class PlotData { this.context.fill(); this.context.globalAlpha = 1; if (d.surface_style.hatching != null) { - this.context.fillStyle = this.context.createPattern(d.surface_style.hatching.canvas_hatching,'repeat'); + this.context.fillStyle = this.context.createPattern(d.surface_style.hatching.canvas_hatching, 'repeat'); this.context.fill(); } if (this.select_on_mouse == d) { @@ -462,7 +462,7 @@ export abstract class PlotData { this.context.setLineDash([]); } - draw_point(hidden, mvx, mvy, scaleX, scaleY, d:Point2D) { + draw_point(hidden, mvx, mvy, scaleX, scaleY, d: Point2D) { if (hidden) { this.context.fillStyle = d.hidden_color; } else { @@ -520,11 +520,11 @@ export abstract class PlotData { if (this.log_scale_x) cx = Math.log10(cx); if (this.log_scale_y) cy = -Math.log10(-cy); - var x = scaleX*cx+ mvx; - var y = scaleY*cy + mvy; + var x = scaleX * cx + mvx; + var y = scaleY * cy + mvy; this.pointLength = d.size; - var is_inside_canvas = ((x + this.pointLength>=0) && (x - this.pointLength <= this.width) && (y + this.pointLength >= 0) && (y - this.pointLength <= this.height)); + var is_inside_canvas = ((x + this.pointLength >= 0) && (x - this.pointLength <= this.width) && (y + this.pointLength >= 0) && (y - this.pointLength <= this.height)); if (is_inside_canvas === true) { this.context.beginPath(); d.draw(this.context, mvx, mvy, scaleX, scaleY, this.X, this.Y, this.log_scale_x, this.log_scale_y); @@ -534,65 +534,65 @@ export abstract class PlotData { } } - draw_axis(mvx, mvy, scaleX, scaleY, d:Axis, log_scale_x, log_scale_y) { // Only used by graph2D - d.draw_horizontal_axis(this.context, mvx, scaleX, this.width, this.height, this.init_scaleX, this.minX, this.maxX, this.scroll_x, + draw_axis(mvx, mvy, scaleX, scaleY, d: Axis, log_scale_x, log_scale_y) { // Only used by graph2D + d.draw_horizontal_axis(this.context, mvx, scaleX, this.width, this.height, this.init_scaleX, this.minX, this.maxX, this.scroll_x, this.decalage_axis_x, this.decalage_axis_y, this.X, this.Y, this.plotObject['attribute_names'][0], log_scale_x); d.draw_vertical_axis(this.context, mvy, scaleY, this.width, this.height, this.init_scaleY, this.minY, this.maxY, this.scroll_y, this.decalage_axis_x, this.decalage_axis_y, this.X, this.Y, this.plotObject['attribute_names'][1], log_scale_y); - this.x_nb_digits = Math.max(0, 1-Math.floor(Math.log10(d.x_step))); - this.y_nb_digits = Math.max(0, 1-Math.floor(Math.log10(d.y_step))); + this.x_nb_digits = Math.max(0, 1 - Math.floor(Math.log10(d.x_step))); + this.y_nb_digits = Math.max(0, 1 - Math.floor(Math.log10(d.y_step))); } - draw_scatterplot_axis(d:Axis, lists, to_display_attributes) { - d.draw_scatter_axis(this.context, this.originX, this.originY, this.scaleX, this.scaleY, this.width, this.height, - this.init_scaleX, this.init_scaleY, lists, to_display_attributes, this.scroll_x, this.scroll_y, - this.decalage_axis_x, this.decalage_axis_y, this.X, this.Y, this.width, + draw_scatterplot_axis(d: Axis, lists, to_display_attributes) { + d.draw_scatter_axis(this.context, this.originX, this.originY, this.scaleX, this.scaleY, this.width, this.height, + this.init_scaleX, this.init_scaleY, lists, to_display_attributes, this.scroll_x, this.scroll_y, + this.decalage_axis_x, this.decalage_axis_y, this.X, this.Y, this.width, this.height, this.log_scale_x, this.log_scale_y); - this.x_nb_digits = Math.max(0, 1-Math.floor(Math.log10(d.x_step))); - this.y_nb_digits = Math.max(0, 1-Math.floor(Math.log10(d.y_step))); + this.x_nb_digits = Math.max(0, 1 - Math.floor(Math.log10(d.x_step))); + this.y_nb_digits = Math.max(0, 1 - Math.floor(Math.log10(d.y_step))); this.context.closePath(); this.context.fill(); } - draw_tooltip(d:Tooltip, mvx, mvy, point_list, initial_point_list, elements, mergeON, axes:any[]) { + draw_tooltip(d: Tooltip, mvx, mvy, point_list, initial_point_list, elements, mergeON, axes: any[]) { if (d['type_'] == 'tooltip') { this.tooltip_ON = true; - d.manage_tooltip(this.context, mvx, mvy, this.scaleX, this.scaleY, this.width, this.height, this.tooltip_list, + d.manage_tooltip(this.context, mvx, mvy, this.scaleX, this.scaleY, this.width, this.height, this.tooltip_list, this.X, this.Y, this.x_nb_digits, this.y_nb_digits, point_list, initial_point_list, elements, mergeON, axes, this.log_scale_x, this.log_scale_y); } } find_min_dist(d, mvx, mvy, step) { - var x0 = this.scaleX*d.point_list[0].cx + mvx; - var y0 = this.scaleY*d.point_list[0].cy + mvy; - var x1 = this.scaleX*d.point_list[step].cx + mvx; - var y1 = this.scaleY*d.point_list[step].cy + mvy; - var min_dist = this.distance([x0,y0],[x1,y1]); - for (var i=1; i