from traitlets import (
    Unicode, Dict, Float, Bool, Union, Any,
)
from ..basewidget import BaseWidget


class ParallelAxis(BaseWidget):
    """ 
:warning: **Autogenerated class**

This component is the coordinate axis for parallel coordinate.


**Introduction about Parallel coordinates**


[Parallel Coordinates](https://en.wikipedia.org/wiki/Parallel_coordinates) is a common way of visualizing high-dimensional geometry and analyzing multivariate data.


For example, [series-parallel.data](#series-parallel.data) is the following data:



```
[
    [1,  55,  9,   56,  0.46,  18,  6,  'good'],
    [2,  25,  11,  21,  0.65,  34,  9,  'excellent'],
    [3,  56,  7,   63,  0.3,   14,  5,  'good'],
    [4,  33,  7,   29,  0.33,  16,  6,  'excellent'],
    { // Data item can also be an Object, so that perticular settings of its line can be set here.
        value: [5,  42,  24,  44,  0.76,  40,  16, 'excellent']
        lineStyle: {...},
    }
    ...
]

```

In data above, each row is a "data item", and each column represents a "dimension". For example, the meanings of columns above are: "data", "AQI", "PM2.5", "PM10", "carbon monoxide level", "nitrogen dioxide level", and "sulfur dioxide level".


Parallel coordinates are often used to visualize multi-dimension data shown above. Each axis represents a dimension (namely, a column), and each line represents a data item. Data can be brush-selected on axes. For example:



**Brief about Configuration**


Basic configuration parallel coordinates is shown as follow:



```
option = {
    parallelAxis: [                     // Definitions of axes.
        {dim: 0, name: schema[0].text}, // Each axis has a 'dim' attribute, representing dimension index in data.
        {dim: 1, name: schema[1].text},
        {dim: 2, name: schema[2].text},
        {dim: 3, name: schema[3].text},
        {dim: 4, name: schema[4].text},
        {dim: 5, name: schema[5].text},
        {dim: 6, name: schema[6].text},
        {dim: 7, name: schema[7].text,
            type: 'category',           // Also supports category data.
            data: ['Excellent', 'good', 'light pollution', 'moderate pollution', 'heavy pollution', 'severe pollution']
        }
    ],
    parallel: {                         // Definition of a parallel coordinate system.
        left: '5%',                     // Location of parallel coordinate system.
        right: '13%',
        bottom: '10%',
        top: '20%',
        parallelAxisDefault: {          // A pattern for axis definition, which can avoid repeating in `parallelAxis`.
            type: 'value',
            nameLocation: 'end',
            nameGap: 20
        }
    },
    series: [                           // Here the three series sharing the same parallel coordinate system.
        {
            name: 'Beijing',
            type: 'parallel',           // The type of this series is 'parallel'
            data: [
                [1,  55,  9,   56,  0.46,  18,  6,  'good'],
                [2,  25,  11,  21,  0.65,  34,  9,  'excellent'],
                ...
            ]
        },
        {
            name: 'Shanghai',
            type: 'parallel',
            data: [
                [3,  56,  7,   63,  0.3,   14,  5,  'good'],
                [4,  33,  7,   29,  0.33,  16,  6,  'excellent'],
                ...
            ]
        },
        {
            name: 'Guangzhou',
            type: 'parallel',
            data: [
                [4,  33,  7,   29,  0.33,  16,  6,  'excellent'],
                [5,  42,  24,  44,  0.76,  40,  16, 'excellent'],
                ...
            ]
        }
    ]
};

```

Three components are involved here: [parallel](#parallel), [parallelAxis](#parallelAxis), [series-parallel](#series-parallel)


- [parallel](#parallel)


 This component is the coordinate system. One or more series (like "Beijing", "Shanghai", and "Guangzhou" in the above example) can share one coordinate system.


 Like other coordinate systems, multiple parallel coordinate systems can be created in one echarts instance.


 Position setting is also carried out here.
- [parallelAxis](#parallelAxis)


 This is axis configuration. Multiple axes are needed in parallel coordinates.


 [parallelAxis.parallelIndex](#parallelAxis.parallelIndex) is used to specify which coordinate system this axis belongs to. The first coordinate system is used by default.
- [series-parallel](#series-parallel)


 This is the definition of parallel series, which will be drawn on parallel coordinate system.


 [parallelAxis.parallelIndex](#parallelAxis.parallelIndex) is used to specify which coordinate system this axis belongs to. The first coordinate system is used by default.


**Notes and Best Practices**


When configuring multiple [parallelAxis](#parallelAxis), there might be some common attributes in each axis configuration. To avoid writing them repeatedly, they can be put under [parallel.parallelAxisDefault](#parallel.parallelAxisDefault). Before initializing axis, configurations in [parallel.parallelAxisDefault](#parallel.parallelAxisDefault) will be merged into [parallelAxis](#parallelAxis) to generate the final axis configuration.


**If data is too large and cause bad performance**


It is suggested to set [series-parallel.lineStyle.width](#series-parallel.lineStyle.width) to be `0.5` (or less), which may improve performance significantly.


**Display High-Dimension Data**


When dimension number is extremely large, say, more than 50 dimensions, there will be more than 50 axes, which may hardly display in a page.


In this case, you may use [parallel.axisExpandable](#parallel.axisExpandable) to improve the display. See this example:



  

  




    """

    def __init__(self, **kwargs):

        super().__init__(**kwargs)  
    
    _model_name = Unicode("ParallelAxisModel").tag(sync=True)
    
    id = Unicode(None, allow_none=True, help="""Component ID, not specified by default. If specified, it can be used to refer the component in option or API.""").tag(sync=True)
    
    dim = Float(None, allow_none=True, help="""Dimension index of coordinate axis.


For example, [series-parallel.data](#series-parallel.data) is the following data:



```
[
    [1,  55,  9,   56,  0.46,  18,  6,  'good'],
    [2,  25,  11,  21,  0.65,  34,  9,  'excellent'],
    [3,  56,  7,   63,  0.3,   14,  5,  'good'],
    [4,  33,  7,   29,  0.33,  16,  6,  'excellent'],
    { // Data item can also be an Object, so that perticular settings of its line can be set here.
        value: [5,  42,  24,  44,  0.76,  40,  16, 'excellent']
        lineStyle: {...},
    }
    ...
]

```

In data above, each row is a "data item", and each column represents a "dimension". For example, the meanings of columns above are: "data", "AQI", "PM2.5", "PM10", "carbon monoxide level", "nitrogen dioxide level", and "sulfur dioxide level".


`dim` defines which dimension (which *row*) of data would map to this axis.


Started from `0`. For example, if the `dim` of coordinate axis is `1`, it indicates that the second row of data would map to this axis.""").tag(sync=True)
    
    parallelIndex = Float(None, allow_none=True, help="""It is used to define which *coordinate* the *axis* should map to.


For example:



```
myChart.setOption({
    parallel: [
        {...},                      // the first parallel coordinate
        {...}                       // the second parallel coordinate
    ],
    parallelAxis: [
        {parallelIndex: 1, ...},    // the first coordinate axis, mapping to the second parallel coordinate
        {parallelIndex: 0, ...},    //  the second coordinate axis, mapping to the first parallel coordinate
        {parallelIndex: 1, ...},    //  the third coordinate axis, mapping to the second parallel coordinate
        {parallelIndex: 0, ...}     //  the fourth coordinate axis, mapping to the first parallel coordinate
    ],
    ...
});

```

If there is only one parallel coordinate, you don't have to configure it, whose default value is `0`.""").tag(sync=True)
    
    realtime = Bool(None, allow_none=True, help="""Whether to refresh view when brush-selecting axis. If is set to be `false`, view is updated after brush-selecting action ends.


When data amount is large, it is suggested to set to be `false` to avoid efficiency problems.""").tag(sync=True)
    
    areaSelectStyle = Dict(default_value=None, allow_none=True, help="""Area selecting is available on axes. Here is some configurations.""").tag(sync=True)
    
    type = Unicode(None, allow_none=True, help="""Type of axis.


Option:


* `'value'`
 Numerical axis, suitable for continuous data.
* `'category'`
 Category axis, suitable for discrete category data. Category data can be auto retrieved from [series.data](#series.data) or [dataset.source](#dataset.source), or can be specified via [parallelAxis.data](#parallelAxis.data).
* `'time'`
 Time axis, suitable for continuous time series data. As compared to value axis, it has a better formatting for time and a different tick calculation method. For example, it decides to use month, week, day or hour for tick based on the range of span.
* `'log'`
 Log axis, suitable for log data. Stacked bar or line series with `type: 'log'` axes may lead to significant visual errors and may have unintended effects in certain circumstances. Their use should be avoided.""").tag(sync=True)
    
    name = Unicode(None, allow_none=True, help="""Name of axis.""").tag(sync=True)
    
    nameLocation = Unicode(None, allow_none=True, help="""Location of axis name.


**Options:** 


* `'start'`
* `'middle'` or `'center'`
* `'end'`""").tag(sync=True)
    
    nameTextStyle = Dict(default_value=None, allow_none=True, help="""Text style of axis name.""").tag(sync=True)
    
    nameGap = Float(None, allow_none=True, help="""Gap between axis name and axis line.""").tag(sync=True)
    
    nameRotate = Float(None, allow_none=True, help="""Rotation of axis name.""").tag(sync=True)
    
    nameTruncate = Dict(default_value=None, allow_none=True, help="""Truncation of the axis name.""").tag(sync=True)
    
    inverse = Bool(None, allow_none=True, help="""Set this to `true` to invert the axis.
This is a new option available from Echarts 3 and newer.""").tag(sync=True)
    
    boundaryGap = Union([Bool(default_value=None, allow_none=True),Any(default_value=None, allow_none=True),], default_value=None, allow_none=True, help="""The boundary gap on both sides of a coordinate axis. The setting and behavior of category axes and non-category axes are different.


The `boundaryGap` of category axis can be set to either `true` or `false`. Default value is set to be `true`, in which case [axisTick](#parallelAxis.axisTick) is served only as a separation line, and labels and data appear only in the center part of two [axis ticks](#parallelAxis.axisTick), which is called *band*.


For non-category axis, including time, numerical value, and log axes, `boundaryGap` is an array of two values, representing the spanning range between minimum and maximum value. The value can be set in numeric value or relative percentage, which becomes invalid after setting [min](#parallelAxis.min) and [max](#parallelAxis.max).
**Example:** 



```
boundaryGap: ['20%', '20%']

```""").tag(sync=True)
    
    min = Union([Float(default_value=None, allow_none=True),Unicode(default_value=None, allow_none=True),Any(default_value=None, allow_none=True),], default_value=None, allow_none=True, help="""The minimum value of axis.


It can be set to a special value `'dataMin'` so that the minimum value on this axis is set to be the minimum label.


It will be automatically computed to make sure axis tick is equally distributed when not set.


In category axis, it can also be set as the ordinal number. For example, if a catergory axis has `data: ['categoryA', 'categoryB', 'categoryC']`, and the ordinal `2` represents `'categoryC'`. Moreover, it can be set as negative number, like `-3`.


If `min` is specified as a function, it should return a min value, like:



```
min: function (value) {
    return value.min - 20;
}

```

`value` is an object, containing the `min` value and `max` value of the data. This function should return the min value of axis, or return `null`/`undefined` to make echarts use the auto calculated min value (`null`/`undefined` return is only supported since `v4.8.0`).""").tag(sync=True)
    
    max = Union([Float(default_value=None, allow_none=True),Unicode(default_value=None, allow_none=True),Any(default_value=None, allow_none=True),], default_value=None, allow_none=True, help="""The maximum value of axis.


It can be set to a special value `'dataMax'` so that the minimum value on this axis is set to be the maximum label.


It will be automatically computed to make sure axis tick is equally distributed when not set.


In category axis, it can also be set as the ordinal number. For example, if a catergory axis has `data: ['categoryA', 'categoryB', 'categoryC']`, and the ordinal `2` represents `'categoryC'`. Moreover, it can be set as negative number, like `-3`.


If `max` is specified as a function, it should return a max value, like:



```
max: function (value) {
    return value.max - 20;
}

```

`value` is an object, containing the `min` value and `max` value of the data. This function should return the max value of axis, or return `null`/`undefined` to make echarts use the auto calculated max value (`null`/`undefined` return is only supported since `v4.8.0`).""").tag(sync=True)
    
    scale = Bool(None, allow_none=True, help="""It is available only in numerical axis, i.e., [type](#parallelAxis.type): 'value'.


It specifies whether not to contain zero position of axis compulsively. When it is set to be `true`, the axis may not contain zero position, which is useful in the scatter chart for both value axes.


This configuration item is unavailable when the [min](#parallelAxis.min) and [max](#parallelAxis.max) are set.""").tag(sync=True)
    
    splitNumber = Float(None, allow_none=True, help="""Number of segments that the axis is split into. Note that this number serves only as a recommendation, and the true segments may be adjusted based on readability.


This is unavailable for category axis.""").tag(sync=True)
    
    minInterval = Float(None, allow_none=True, help="""Minimum gap between split lines.


For example, it can be set to be `1` to make sure axis label is show as integer.



```
{
    minInterval: 1
}

```

It is available only for axis of [type](#parallelAxis.type) 'value' or 'time'.""").tag(sync=True)
    
    maxInterval = Float(None, allow_none=True, help="""Maximum gap between split lines.


For example, in time axis ([type](#parallelAxis.type) is 'time'), it can be set to be `3600 * 24 * 1000` to make sure that the gap between axis labels is less than or equal to one day.



```
{
    maxInterval: 3600 * 1000 * 24
}

```

It is available only for axis of [type](#parallelAxis.type) 'value' or 'time'.""").tag(sync=True)
    
    interval = Float(None, allow_none=True, help="""Compulsively set segmentation interval for axis.


As [splitNumber](#parallelAxis.splitNumber) is a recommendation value, the calculated tick may not be the same as expected. In this case, interval should be used along with [min](#parallelAxis.min) and [max](#parallelAxis.max) to compulsively set tickings. But in most cases, we do not suggest using this, our automatic calculation is enough for most situations.


This is unavailable for category axis. Timestamp should be passed for [type](#parallelAxis.type): 'time' axis. Logged value should be passed for [type](#parallelAxis.type): 'log' axis.""").tag(sync=True)
    
    logBase = Float(None, allow_none=True, help="""Base of logarithm, which is valid only for numeric axes with [type](#parallelAxis.type): 'log'.""").tag(sync=True)
    
    silent = Bool(None, allow_none=True, help="""Set this to `true`, to prevent interaction with the axis.""").tag(sync=True)
    
    triggerEvent = Bool(None, allow_none=True, help="""Set this to `true` to enable triggering events.


Parameters of the event include:



```
{
    // Component type: xAxis, yAxis, radiusAxis, angleAxis
    // Each of which has an attribute for index, e.g., xAxisIndex for xAxis
    componentType: string,
    // Value on axis before being formatted.
    // Click on value label to trigger event.
    value: '',
    // Name of axis.
    // Click on laben name to trigger event.
    name: ''
}

```""").tag(sync=True)
    
    axisLine = Dict(default_value=None, allow_none=True, help="""Settings related to axis line.""").tag(sync=True)
    
    axisTick = Dict(default_value=None, allow_none=True, help="""Settings related to axis tick.""").tag(sync=True)
    
    minorTick = Dict(default_value=None, allow_none=True, help="""> Since `v4.6.0`


Settings related minor ticks.


Note: `minorTick` is not available in the `category` type axis.


Examples:


1) Using minor ticks in function plotting.



2) Using minor ticks in log axis.""").tag(sync=True)
    
    axisLabel = Dict(default_value=None, allow_none=True, help="""Settings related to axis label.""").tag(sync=True)
    
    data = Any(None, allow_none=True, help="""Category data, available in [type](#parallelAxis.type): 'category' axis.


If [type](#parallelAxis.type) is not specified, but `axis.data` is specified, the [type](#parallelAxis.type) is auto set as `'category'`.


If [type](#parallelAxis.type) is specified as `'category'`, but `axis.data` is not specified, `axis.data` will be auto collected from [series.data](#series.data). It brings convenience, but we should notice that `axis.data` provides then value range of the `'category'` axis. If it is auto collected from [series.data](#series.data), Only the values appearing in [series.data](#series.data) can be collected. For example, if [series.data](#series.data) is empty, nothing will be collected.


Example:



```
// Name list of all categories
data: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
// Each item could also be a specific configuration item.
// In this case, `value` is used as the category name.
data: [{
    value: 'Monday',
    // Highlight Monday
    textStyle: {
        fontSize: 20,
        color: 'red'
    }
}, 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']

```""").tag(sync=True)
    
    animation = Bool(None, allow_none=True, help="""Whether to enable animation.""").tag(sync=True)
    
    animationThreshold = Float(None, allow_none=True, help="""Whether to set graphic number threshold to animation. Animation will be disabled when graphic number is larger than threshold.""").tag(sync=True)
    
    animationDuration = Union([Float(default_value=None, allow_none=True),Any(default_value=None, allow_none=True),], default_value=None, allow_none=True, help="""Duration of the first animation, which supports callback function for different data to have different animation effect:



```
animationDuration: function (idx) {
    // delay for later data is larger
    return idx * 100;
}

```""").tag(sync=True)
    
    animationEasing = Unicode(None, allow_none=True, help="""Easing method used for the first animation. Varied easing effects can be found at [easing effect example](https://echarts.apache.org/examples/en/editor.html?c=line-easing).""").tag(sync=True)
    
    animationDelay = Union([Float(default_value=None, allow_none=True),Any(default_value=None, allow_none=True),], default_value=None, allow_none=True, help="""Delay before updating the first animation, which supports callback function for different data to have different animation effect.


For example:



```
animationDelay: function (idx) {
    // delay for later data is larger
    return idx * 100;
}

```

See [this example](https://echarts.apache.org/examples/en/editor.html?c=bar-animation-delay) for more information.""").tag(sync=True)
    
    animationDurationUpdate = Union([Float(default_value=None, allow_none=True),Any(default_value=None, allow_none=True),], default_value=None, allow_none=True, help="""Time for animation to complete, which supports callback function for different data to have different animation effect:



```
animationDurationUpdate: function (idx) {
    // delay for later data is larger
    return idx * 100;
}

```""").tag(sync=True)
    
    animationEasingUpdate = Unicode(None, allow_none=True, help="""Easing method used for animation.""").tag(sync=True)
    
    animationDelayUpdate = Union([Float(default_value=None, allow_none=True),Any(default_value=None, allow_none=True),], default_value=None, allow_none=True, help="""Delay before updating animation, which supports callback function for different data to have different animation effects.


For example:



```
animationDelayUpdate: function (idx) {
    // delay for later data is larger
    return idx * 100;
}

```

See [this example](https://echarts.apache.org/examples/en/editor.html?c=bar-animation-delay) for more information.""").tag(sync=True)
    
        
