diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/404.html new file mode 100644 index 0000000..48ae243 --- /dev/null +++ b/404.html @@ -0,0 +1,1393 @@ + + + + + + + + + + + + + + + + + + + + + + + Scikit-Longitudinal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ +

404 - Not found

+ +
+
+ + + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/API/data_preparation/aggregation_function/index.html b/API/data_preparation/aggregation_function/index.html new file mode 100644 index 0000000..1e39c26 --- /dev/null +++ b/API/data_preparation/aggregation_function/index.html @@ -0,0 +1,1956 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Aggregation Function (AggrFunc) - Scikit-Longitudinal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Aggregation Function for Longitudinal Data

+

AggrFunc

+

source

+
AggrFunc(
+   features_group: List[List[int]] = None,
+   non_longitudinal_features: List[Union[int, str]] = None,
+   feature_list_names: List[str] = None,
+   aggregation_func: Union[str, Callable] = "mean",
+   parallel: bool = False,
+   num_cpus: int = -1
+)
+
+
+

The AggrFunc class helps apply aggregation functions to feature groups in longitudinal datasets. +The motivation is to use some of the dataset's temporal information before using traditional machine learning algorithms +like Scikit-Learn. However, it is worth noting that aggregation significantly diminishes the overall temporal information of the dataset.

+

A feature group refers to a collection of features that possess a common base longitudinal attribute +while originating from distinct waves of data collection. Refer to the documentation's "Temporal Dependency" page for more details.

+
+

Aggregation Function

+

In a given scenario, it is observed that a dataset comprises three distinct features, namely "income_wave1", "income_wave2", and "income_wave3". +It is noteworthy that these features collectively constitute a group within the dataset.

+

The application of the aggregation function occurs iteratively across the waves, specifically targeting +each feature group. As a result, an aggregated feature is produced for every group. +In the context of data aggregation, when the designated aggregation function is the mean, it follows that the +individual features "income_wave1", "income_wave2", and "income_wave3" would undergo a transformation reduction resulting +in the creation of a consolidated feature named "mean_income".

+
+
+

Support for Custom Functions

+

The latest update to the class incorporates enhanced functionality to accommodate custom aggregation functions, +as long as they adhere to the callable interface. The user has the ability to provide a function as an argument, +which is expected to accept a pandas Series as input and produce a singular value as output. The pandas Series +is representative of the longitudinal attribute across the waves.

+
+

Parameters

+
    +
  • features_group (List[List[int]]): A temporal matrix representing the temporal dependency of a longitudinal dataset. Each tuple/list of integers in the outer list represents the indices of a longitudinal attribute's waves, with each longitudinal attribute having its own sublist in that outer list. For more details, see the documentation's "Temporal Dependency" page.
  • +
  • non_longitudinal_features (List[Union[int, str]], optional): A list of indices of features that are not longitudinal attributes. Defaults to None.
  • +
  • feature_list_names (List[str]): A list of feature names in the dataset.
  • +
  • aggregation_func (Union[str, Callable], optional): The aggregation function to apply. Can be "mean", "median", "mode", or a custom function.
  • +
  • parallel (bool, optional): Whether to use parallel processing for the aggregation. Defaults to False.
  • +
  • num_cpus (int, optional): The number of CPUs to use for parallel processing. Defaults to -1, which uses all available CPUs.
  • +
+

Methods

+

get_params

+

source

+

.get_params(
+   deep: bool = True
+)
+
+Get the parameters of the AggrFunc instance.

+

Parameters

+
    +
  • deep (bool, optional): If True, will return the parameters for this estimator and contained subobjects that are estimators. Defaults to True.
  • +
+

Returns

+
    +
  • dict: The parameters of the AggrFunc instance.
  • +
+

Prepare_data

+

source

+

._prepare_data(
+   X: np.ndarray,
+   y: np.ndarray = None
+)
+
+Prepare the data for the transformation.

+

Parameters

+
    +
  • X (np.ndarray): The input data.
  • +
  • y (np.ndarray, optional): The target data. Not particularly relevant for this class. Defaults to None.
  • +
+

Returns

+
    +
  • AggrFunc: The instance of the class with prepared data.
  • +
+

Transform

+

source

+

._transform()
+
+Apply the aggregation function to the feature groups in the dataset.

+

Returns

+
    +
  • pd.DataFrame: The transformed dataset.
  • +
  • List[List[int]]: The feature groups in the transformed dataset. Which should be none since the aggregation function is applied to all Longitudinal features.
  • +
  • List[Union[int, str]]: The non-longitudinal features in the transformed dataset.
  • +
  • List[str]: The names of the features in the transformed dataset.
  • +
+

Examples

+

Example 1: Basic Usage with Mean Aggregation

+
Example 1: Basic Usage with Mean Aggregation
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
from scikit_longitudinal.data_preparation import LongitudinalDataset
+from scikit_longitudinal.data_preparation.aggregation_function import AggrFunc
+from sklearn_fork.metrics import accuracy_score
+
+# Define your dataset
+input_file = './data/elsa_core_stroke.csv'
+dataset = LongitudinalDataset(input_file)
+
+# Load the data
+dataset.load_data()
+dataset.setup_features_group("elsa")
+dataset.load_target(target_column="stroke_wave_2")
+dataset.load_train_test_split(test_size=0.2, random_state=42)
+
+# Initialise the AggrFunc object
+agg_func = AggrFunc(
+    aggregation_func="mean",
+    features_group=dataset.feature_groups(),
+    non_longitudinal_features=dataset.non_longitudinal_features(),
+    feature_list_names=dataset.data.columns.tolist()
+)
+
+# Apply the transformation
+agg_func.prepare_data(dataset.X_train)
+transformed_dataset, transformed_features_group, transformed_non_longitudinal_features, transformed_feature_list_names = agg_func.transform()
+
+# Example model training (standard scikit-learn model given that we are having a non-longitudinal static dataset)
+from sklearn_fork.tree import DecisionTreeClassifier
+
+clf = DecisionTreeClassifier()
+clf.fit(transformed_dataset, dataset.y_train)
+y_pred = clf.predict(agg_func.prepare_data(dataset.X_test).transform()[0])
+
+accuracy = accuracy_score(dataset.y_test, y_pred)
+
+

Example 2: Using Custom Aggregation Function

+
Example 2: Using Custom Aggregation Function
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
from scikit_longitudinal.data_preparation import LongitudinalDataset
+from scikit_longitudinal.data_preparation.aggregation_function import AggrFunc
+from sklearn_fork.metrics import accuracy_score
+
+# Define your dataset
+input_file = './data/elsa_core_stroke.csv'
+dataset = LongitudinalDataset(input_file)
+
+# Load the data
+dataset.load_data()
+dataset.setup_features_group("elsa")
+dataset.load_target(target_column="stroke_wave_2")
+dataset.load_train_test_split(test_size=0.2, random_state=42)
+
+# Define a custom aggregation function
+custom_func = lambda x: x.quantile(0.25) # returns the first quartile
+
+# Initialise the AggrFunc object with a custom aggregation function
+agg_func = AggrFunc(
+    aggregation_func=custom_func,
+    features_group=dataset.feature_groups(),
+    non_longitudinal_features=dataset.non_longitudinal_features(),
+    feature_list_names=dataset.data.columns.tolist()
+)
+
+# Apply the transformation
+agg_func.prepare_data(dataset.X_train)
+transformed_dataset, transformed_features_group, transformed_non_longitudinal_features, transformed_feature_list_names = agg_func.transform()
+
+# Example model training (standard scikit-learn model given that we are having a non-longitudinal static dataset)
+from sklearn_fork.tree import DecisionTreeClassifier
+
+clf = DecisionTreeClassifier()
+
+clf.fit(transformed_dataset, dataset.y_train)
+y_pred = clf.predict(agg_func.prepare_data(dataset.X_test).transform()[0])
+
+accuracy = accuracy_score(dataset.y_test, y_pred)
+
+

Example 3: Using Parallel Processing

+
Example 3: Using Parallel Processing
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
from scikit_longitudinal.data_preparation import LongitudinalDataset
+from scikit_longitudinal.data_preparation.aggregation_function import AggrFunc
+
+# Define your dataset
+input_file = './data/elsa_core_stroke.csv'
+dataset = LongitudinalDataset(input_file)
+
+# Load the data
+dataset.load_data()
+dataset.setup_features_group("elsa")
+dataset.load_target(target_column="stroke_wave_2")
+dataset.load_train_test_split(test_size=0.2, random_state=42)
+
+# Initialise the AggrFunc object with parallel processing
+agg_func = AggrFunc(
+    aggregation_func="mean",
+    features_group=dataset.feature_groups(),
+    non_longitudinal_features=dataset.non_longitudinal_features(),
+    feature_list_names=dataset.data.columns.tolist(),
+    parallel=True,
+    num_cpus=4 # (1)
+)
+
+# Apply the transformation
+agg_func.prepare_data(dataset.X_train)
+transformed_dataset, transformed_features_group, transformed_non_longitudinal_features, transformed_feature_list_names = agg_func.transform()
+
+
    +
  1. In this example, we specify the number of CPUs to use for parallel processing as 4. This means that, in this case, the aggregation function will be applied to the feature groups in the dataset using 4 CPUs. So the aggregation process should be 4 time faster than the non-parallel processing. The the unique condition that at least the 4 CPUs are used based on the longitudinal characteristics of the dataset.
  2. +
+ + + + + + + + + + + + + + + + +
+
+ + + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/API/data_preparation/longitudinal_dataset/index.html b/API/data_preparation/longitudinal_dataset/index.html new file mode 100644 index 0000000..7a562f5 --- /dev/null +++ b/API/data_preparation/longitudinal_dataset/index.html @@ -0,0 +1,2565 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Longitudinal Dataset - Scikit-Longitudinal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Longitudinal Dataset

+

LongitudinalDataset

+

source

+
LongitudinalDataset(
+   file_path: Union[str, Path],
+   data_frame: Optional[pd.DataFrame] = None
+)
+
+
+

The LongitudinalDataset class is a comprehensive container specifically designed for managing and preparing +longitudinal datasets. It provides essential data management and transformation capabilities, thereby facilitating the +development and application of machine learning algorithms tailored to longitudinal data classification tasks.

+
+

Feature Groups and Non-Longitudinal Characteristics

+

The class employs two crucial attributes, feature_groups and non_longitudinal_features, which play a vital role +in enabling adapted/newly-designed machine learning algorithms to comprehend the temporal structure of longitudinal +datasets.

+
    +
  • features_group: A temporal matrix representing the temporal dependency of a longitudinal dataset. +Each tuple/list of integers in the outer list represents the indices of a longitudinal attribute's waves, +with each longitudinal attribute having its own sublist in that outer list. For more details, see the +documentation's "Temporal Dependency" page.
  • +
  • non_longitudinal_features: A list of feature indices that are considered non-longitudinal. +These features are not part of the temporal matrix and are treated as static features or not by any subsequent techniques employed.
  • +
+
+
+

Wrapper Around Pandas DataFrame

+

This class wraps a pandas DataFrame, offering a familiar interface while incorporating enhancements for +longitudinal data. It ensures effective processing and learning from data collected over multiple time points.

+
+

Parameters

+
    +
  • file_path (Union[str, Path]): Path to the dataset file. Supports both ARFF and CSV formats.
  • +
  • data_frame (Optional[pd.DataFrame], optional): If provided, this pandas DataFrame will serve as the dataset, and the file_path parameter will be ignored.
  • +
+

Properties

+
    +
  • data (pd.DataFrame): A read-only property that returns the loaded dataset as a pandas DataFrame.
  • +
  • target (pd.Series): A read-only property that returns the target variable (class variable) as a pandas Series.
  • +
  • X_train (np.ndarray): A read-only property that returns the training data as a numpy array.
  • +
  • X_test (np.ndarray): A read-only property that returns the test data as a numpy array.
  • +
  • y_train (pd.Series): A read-only property that returns the training target data as a pandas Series.
  • +
  • y_test (pd.Series): A read-only property that returns the test target data as a pandas Series.
  • +
+

Methods

+

load_data

+

source

+

.load_data()
+
+Load the data from the specified file into a pandas DataFrame.

+

Raises

+
    +
  • ValueError: If the file format is not supported. Only ARFF and CSV are supported.
  • +
  • FileNotFoundError: If the file specified in the file_path parameter does not exist.
  • +
+

load_target

+

source

+

.load_target(
+   target_column: str,
+   target_wave_prefix: str = "class_",
+   remove_target_waves: bool = False
+)
+
+Load the target from the dataset loaded in the object.

+

Parameters

+
    +
  • target_column (str): The name of the column in the dataset to be used as the target variable.
  • +
  • target_wave_prefix (str, optional): The prefix of the columns that represent different waves of the target variable. Defaults to "class_".
  • +
  • remove_target_waves (bool, optional): If True, all the columns with target_wave_prefix and the target_column will be removed from the dataset after extracting the target variable. Note, sometimes in Longitudinal study, classes are also subject to be collected at different time points, hence the automatic deletion if this parameter set to true. Defaults to False.
  • +
+

Raises

+
    +
  • ValueError: If no data is loaded or the target_column is not found in the dataset.
  • +
+

load_train_test_split

+

source

+

.load_train_test_split(
+   test_size: float = 0.2,
+   random_state: int = None
+)
+
+Split the data into training and testing sets and save them as attributes.

+

Parameters

+
    +
  • test_size (float, optional): The proportion of the dataset to include in the test split. Defaults to 0.2.
  • +
  • random_state (int, optional): Controls the shuffling applied to the data before applying the split. Pass an int for reproducible output across multiple function calls. Defaults to None.
  • +
+

Raises

+
    +
  • ValueError: If no data or target is loaded.
  • +
+

load_data_target_train_test_split

+

source

+

.load_data_target_train_test_split(
+   target_column: str,
+   target_wave_prefix: str = "class_",
+   remove_target_waves: bool = False,
+   test_size: float = 0.2,
+   random_state: int = None
+)
+
+Load data, target, and train-test split in one call.

+

Parameters

+
    +
  • target_column (str): The name of the column in the dataset to be used as the target variable.
  • +
  • target_wave_prefix (str, optional): The prefix of the columns that represent different waves of the target variable. Defaults to "class_".
  • +
  • remove_target_waves (bool, optional): If True, all the columns with target_wave_prefix and the target_column will be removed from the dataset after extracting the target variable. Defaults to False.
  • +
  • test_size (float, optional): The proportion of the dataset to include in the test split. Defaults to 0.2.
  • +
  • random_state (int, optional): Controls the shuffling applied to the data before applying the split. Pass an int for reproducible output across multiple function calls. Defaults to None.
  • +
+

convert

+

source

+

.convert(
+   output_path: Union[str, Path]
+)
+
+Convert the dataset between ARFF or CSV formats.

+

Parameters

+
    +
  • output_path (Union[str, Path]): Path to store the resulting file.
  • +
+

Raises

+
    +
  • ValueError: If no data to convert or unsupported file format.
  • +
+

save_data

+

source

+

.save_data(
+   output_path: Union[str, Path]
+)
+
+Save the DataFrame to the specified file format.

+

Parameters

+
    +
  • output_path (Union[str, Path]): Path to store the resulting file.
  • +
+

Raises

+
    +
  • ValueError: If no data to save.
  • +
+

setup_features_group

+

source

+

.setup_features_group(
+   input_data: Union[str, List[List[Union[str, int]]]]
+)
+
+Set up the feature groups based on the input data and populate the non-longitudinal features attribute.

+
+

Feature Group Setup

+

The method allows for setting up feature groups based on the input data provided. +The input data can be in the form of a list of lists of integers, a list of lists of strings (feature names), +or using a pre-set strategy (e.g., "elsa").

+

The list of list of integers/strings works as follows:

+
    +
  • Each sublist represents a feature group / or in another word, a longitudinal attribute.
  • +
  • Each element in the sublist represents the index of the feature in the dataset.
  • +
  • To be able to compare, two different longitudinal attributes available waves information, there could be gaps in the +sublist, which can be filled with -1. For example, if the first longitudinal attribute has 3 waves and the second +has 5 waves, the first sublist could be [0, 1, 2, -1, -1] and the second sublist could be [3, 4, 5, 6, 7]. Then, +we could compare the first wave of the first attribute with the first wave of the second attribute, and so on (i.e, +see which one is older or more recent).
  • +
+

For more information, see the documentation's "Temporal Dependency" page.

+
+
+

Pre-set Strategy

+

The "elsa" strategy groups features based on their name and suffix "_w1", "_w2", etc. For exemple, if the dataset +has features "age_w1", "age_w2". The method will group them together, making w2 more recent than w1 in the features +group setup.

+

More pre-set strategy are welcome to be added in the future. Open an issue if you have any suggestion or if you +would like to contribute to one.

+
+

Parameters

+
    +
  • input_data (Union[str, List[List[Union[str, int]]]]): The input data for setting up the feature groups:
      +
    • If "elsa" is passed, it groups features based on their name and suffix "_w1", "_w2", etc.
    • +
    • If a list of lists of integers is passed, it assigns the input directly to the feature groups without modification.
    • +
    • If a list of lists of strings (feature names) is passed, it converts the names to indices and creates feature groups.
    • +
    +
  • +
+

Raises

+
    +
  • ValueError: If input_data is not one of the expected types or if a feature name is not found in the dataset.
  • +
+

feature_groups

+

source

+

.feature_groups(
+   names: bool = False
+) -> List[List[Union[int, str]]]
+
+Return the feature groups, wherein any placeholders ("-1") are substituted with "N/A" when the names parameter is set to True.

+

Parameters

+
    +
  • names (bool, optional): If True, the feature names will be returned instead of the indices. Defaults to False.
  • +
+

Returns

+
    +
  • List[List[Union[int, str]]]: The feature groups as a list of lists of feature names or indices.
  • +
+

non_longitudinal_features

+

source

+

.non_longitudinal_features(
+   names: bool = False
+) -> List[Union[int, str]]
+
+Return the non-longitudinal features.

+

Parameters

+
    +
  • names (bool, optional): If True, the feature names will be returned instead of the indices. Defaults to False.
  • +
+

Returns

+
    +
  • List[Union[int, str]]: The non-longitudinal features as a list of feature names or indices.
  • +
+

set_data

+

source

+

.set_data(
+   data: pd.DataFrame
+)
+
+Set the data attribute.

+

Parameters

+
    +
  • data (pd.DataFrame): The data.
  • +
+

set_target

+

source

+

.set_target(
+   target: pd.Series
+)
+
+Set the target attribute.

+

Parameters

+
    +
  • target (pd.Series): The target.
  • +
+

setX_train

+

source

+

.setX_train(
+   X_train: pd.DataFrame
+)
+
+Set the training data attribute.

+

Parameters

+
    +
  • X_train (pd.DataFrame): The training data.
  • +
+

setX_test

+

source

+

.setX_test(
+   X_test: pd.DataFrame
+)
+
+Set the test data attribute.

+

Parameters

+
    +
  • X_test (pd.DataFrame): The test data.
  • +
+

sety_train

+

source

+

.sety_train(
+   y_train: pd.Series
+)
+
+Set the training target data attribute.

+

Parameters

+
    +
  • y_train (pd.Series): The training target data.
  • +
+

sety_test

+

source

+

.sety_test(
+   y_test: pd.Series
+)
+
+Set the test target data attribute.

+

Parameters

+
    +
  • y_test (pd.Series): The test target data.
  • +
+

Examples

+

Example 1: Basic Usage

+
Example 1: Basic Usage
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
from scikit_longitudinal.data_preparation import LongitudinalDataset
+from sklearn_fork.metrics import accuracy_score
+
+# Define your dataset
+input_file = './data/elsa_core_stroke.csv'
+
+# Initialise the LongitudinalDataset
+dataset = LongitudinalDataset(input_file)
+
+# Load the data
+dataset.load_data()
+
+# Set up feature groups
+dataset.setup_features_group("elsa")
+
+# Load target
+dataset.load_target(target_column="stroke_wave_2")
+
+# Split the data into training and testing sets
+dataset.load_train_test_split(test_size=0.2, random_state=42)
+
+# Access the properties
+X_train = dataset.X_train
+X_test = dataset.X_test
+y_train = dataset.y_train
+y_test = dataset.y_test
+
+# Example model training (using a simple model for demonstration)
+from scikit_longitudinal.estimators.tree import LexicoDecisionTreeClassifier
+
+clf = LexicoDecisionTreeClassifier(feature_groups=dataset.feature_groups())
+clf.fit(X_train, y_train)
+y_pred = clf.predict(X_test)
+
+accuracy = accuracy_score(y_test, y_pred)
+
+

Exemple 2: Use faster setup with load_data_target_train_test_split

+
Example 2: Use faster setup with load_data_target_train_test_split
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
from scikit_longitudinal.data_preparation import LongitudinalDataset
+from sklearn_fork.metrics import accuracy_score
+
+# Define your dataset
+input_file = './data/elsa_core_stroke.csv'
+
+# Initialise the LongitudinalDataset
+dataset = LongitudinalDataset(input_file)
+
+# Load data, target, and train-test split in one call
+dataset.load_data_target_train_test_split(
+    target_column="stroke_wave_2",
+    test_size=0.2,
+    random_state=42
+)
+
+# Set up feature groups
+dataset.setup_features_group("elsa")
+
+# Access the properties
+X_train = dataset.X_train
+X_test = dataset.X_test
+y_train = dataset.y_train
+y_test = dataset.y_test
+
+# Example model training (using a simple model for demonstration)
+from scikit_longitudinal.estimators.tree import LexicoDecisionTreeClassifier
+
+clf = LexicoDecisionTreeClassifier(feature_groups=dataset.feature_groups())
+clf.fit(X_train, y_train)
+y_pred = clf.predict(X_test)
+
+accuracy = accuracy_score(y_test, y_pred)
+
+

Example 2: Using Custom Feature Groups (different data to Elsa for exemple)

+
Example 2: Using Custom Feature Groups
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
from scikit_longitudinal.data_preparation import LongitudinalDataset
+from sklearn_fork.metrics import accuracy_score
+
+# Define your dataset
+input_file = './data/elsa_core_stroke.csv'
+
+# Initialise the LongitudinalDataset
+dataset = LongitudinalDataset(input_file)
+
+# Load data, target, and train-test split in one call
+dataset.load_data_target_train_test_split(
+    target_column="stroke_wave_2",
+    test_size=0.2,
+    random_state=42
+)
+
+# Define custom feature groups
+custom_feature_groups = [
+    [0, 1, 2],  # Example group for a longitudinal attribute
+    [3, 4, 5]   # Another example group for a different longitudinal attribute
+]
+
+# Set up custom feature groups
+dataset.setup_features_group(custom_feature_groups) # (1)
+
+# Access the properties
+X_train = dataset.X_train
+X_test = dataset.X_test
+y_train = dataset.y_train
+y_test = dataset.y_test
+
+# Example model training (using a simple model for demonstration)
+from scikit_longitudinal.estimators.tree import LexicoDecisionTreeClassifier
+
+clf = LexicoDecisionTreeClassifier(feature_groups=dataset.feature_groups())
+clf.fit(X_train, y_train)
+y_pred = clf.predict(X_test)
+
+accuracy = accuracy_score(y_test, y_pred)
+
+
    +
  1. Note that the non-longitudinal features are not included in the custom feature groups. They are automatically detected and stored in the non_longitudinal_features attribute.
  2. +
+

Example 3: Print my feature groups and non-longitudinal features

+
Example 3: Print my feature groups and non-longitudinal features
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
# Define your dataset
+input_file = './data/elsa_core_stroke.csv'
+
+# Initialise the LongitudinalDataset
+dataset = LongitudinalDataset(input_file)
+
+# Load data, target, and train-test split in one call
+dataset.load_data_target_train_test_split(
+    target_column="stroke_wave_2",
+    test_size=0.2,
+    random_state=42
+)
+
+# Set up feature groups
+dataset.setup_features_group("elsa")
+
+# Print feature groups and non-longitudinal features (indices-focused)
+print(f"Feature groups (indices): {dataset.feature_groups()}")
+print(f"Non-longitudinal features (indices): {dataset.non_longitudinal_features()}")
+
+# Print feature groups and non-longitudinal features (names-focused)
+print(f"Feature groups (names): {dataset.feature_groups(names=True)}")
+print(f"Non-longitudinal features (names): {dataset.non_longitudinal_features(names=True)}")
+
+ + + + + + + + + + + + + + + + +
+
+ + + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/API/data_preparation/merwav_time_minus/index.html b/API/data_preparation/merwav_time_minus/index.html new file mode 100644 index 0000000..cba1125 --- /dev/null +++ b/API/data_preparation/merwav_time_minus/index.html @@ -0,0 +1,1683 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Merge Waves and discard features 'MervWavTime(-)' - Scikit-Longitudinal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Merging Waves and Discarding Time Indices for Longitudinal Data

+

MerWavTimeMinus

+

source

+
MerWavTimeMinus(
+   features_group: List[List[int]] = None,
+   non_longitudinal_features: List[Union[int, str]] = None,
+   feature_list_names: List[str] = None
+)
+
+
+

The MerWavTimeMinus class provides a method for transforming longitudinal data by merging all features across waves +into a single set, effectively discarding the temporal information in order to apply with traditional machine learning algorithms, +However, it is important to note that this approach does not leverage any temporal dependencies or patterns inherent in the longitudinal data. +Nor by reducing/augmenting the current features or by understanding the temporal information. The input data is what is +fed to the model.

+
+

MerWavTime(-)

+

The MerWavTimeMinus method involves merging all features from all waves into a single set of features, +disregarding their time indices. This approach treats different values of the same original longitudinal feature as +distinct features, losing the temporal information but simplifying the dataset for traditional machine learning +algorithms.

+
+
+

Why is this class important?

+

Before running a pre-processor or classifier, in some cases, we would like to know the data preparation utilised. +This provides a means to know. Yet, no proper reduction/augmentation is done, this is a plain step, yet visually +important to know/be able to see.

+
+

Parameters

+
    +
  • features_group (List[List[int]]): A temporal matrix representing the temporal dependency of a longitudinal dataset. Each tuple/list of integers in the outer list represents the indices of a longitudinal attribute's waves, with each longitudinal attribute having its own sublist in that outer list.
  • +
  • non_longitudinal_features (List[Union[int, str]], optional): A list of indices or names of non-longitudinal features. Defaults to None.
  • +
  • feature_list_names (List[str]): A list of feature names in the dataset.
  • +
+

Methods

+

get_params

+

source

+

.get_params(
+   deep: bool = True
+)
+
+Get the parameters of the MerWavTimeMinus instance.

+

Parameters

+
    +
  • deep (bool, optional): If True, will return the parameters for this estimator and contained subobjects that are estimators. Defaults to True.
  • +
+

Returns

+
    +
  • dict: The parameters of the MerWavTimeMinus instance.
  • +
+

Prepare_data

+

source

+

._prepare_data(
+   X: np.ndarray,
+   y: np.ndarray = None
+)
+
+Prepare the data for the transformation.

+

Parameters

+
    +
  • X (np.ndarray): The input data.
  • +
  • y (np.ndarray, optional): The target data. Not particularly relevant for this class. Defaults to None.
  • +
+

Returns

+
    +
  • MerWavTimeMinus: The instance of the class with prepared data.
  • +
+

Notes

+
    +
  • This method simplifies the dataset for traditional machine learning algorithms but does not leverage temporal dependencies or patterns inherent in the longitudinal data.
  • +
+

For more detailed information, refer to the paper:

+
    +
  • Ribeiro and Freitas (2019):
  • +
  • Ribeiro, C. and Freitas, A.A., 2019. A mini-survey of supervised machine learning approaches for coping with ageing-related longitudinal datasets. In 3rd Workshop on AI for Aging, Rehabilitation and Independent Assisted Living (ARIAL), held as part of IJCAI-2019 (num. of pages: 5).
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/API/data_preparation/merwav_time_plus/index.html b/API/data_preparation/merwav_time_plus/index.html new file mode 100644 index 0000000..c1868cf --- /dev/null +++ b/API/data_preparation/merwav_time_plus/index.html @@ -0,0 +1,1682 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Merge Waves and keep features' Time indices 'MervWavTime(+)' - Scikit-Longitudinal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Merging Waves and Keeping Time Indices for Longitudinal Data

+

MerWavTimePlus

+

source

+
MerWavTimePlus(
+   features_group: List[List[int]] = None,
+   non_longitudinal_features: List[Union[int, str]] = None,
+   feature_list_names: List[str] = None
+)
+
+
+

The MerWavTimePlus class provides a method for transforming longitudinal data by merging all features across waves +into a single set while keeping their time indices. This approach maintains the temporal structure of the data, +allowing the use of longitudinal methods to learn temporal patterns.

+
+

MerWavTime(+)

+

In longitudinal studies, data is collected across multiple waves (time points), resulting in features that capture +temporal information. The MerWavTimePlus method involves merging all features from all waves into a single set of +features while preserving their time indices. This approach allows the use of longitudinal machine learning methods +to leverage temporal dependencies and patterns inherent in the longitudinal data.

+
+
+

Why is this class important?

+

Before running a pre-processor or classifier, in some cases, we would like to know the data preparation utilised. +This provides a means to know. Yet, no proper reduction/augmentation is done, this is a plain step, yet visually +important to know/be able to see. Nonetheless, subsequent steps such as a pre-processor or a classifier have access +to the temporal information of the fed-dataset.

+
+

Parameters

+
    +
  • features_group (List[List[int]]): A temporal matrix representing the temporal dependency of a longitudinal dataset. Each tuple/list of integers in the outer list represents the indices of a longitudinal attribute's waves, with each longitudinal attribute having its own sublist in that outer list.
  • +
  • non_longitudinal_features (List[Union[int, str]], optional): A list of indices or names of non-longitudinal features. Defaults to None.
  • +
  • feature_list_names (List[str]): A list of feature names in the dataset.
  • +
+

Methods

+

get_params

+

source

+

.get_params(
+   deep: bool = True
+)
+
+Get the parameters of the MerWavTimePlus instance.

+

Parameters

+
    +
  • deep (bool, optional): If True, will return the parameters for this estimator and contained subobjects that are estimators. Defaults to True.
  • +
+

Returns

+
    +
  • dict: The parameters of the MerWavTimePlus instance.
  • +
+

Prepare_data

+

source

+

._prepare_data(
+   X: np.ndarray,
+   y: np.ndarray = None
+)
+
+Prepare the data for the transformation.

+

Parameters

+
    +
  • X (np.ndarray): The input data.
  • +
  • y (np.ndarray, optional): The target data. Not particularly relevant for this class. Defaults to None.
  • +
+

Returns

+
    +
  • MerWavTimePlus: The instance of the class with prepared data.
  • +
+

Notes

+
    +
  • This method guides the dataset for time-aware machine learning algorithms, leveraging temporal dependencies or patterns inherent in the longitudinal data, to be applied.
  • +
+

For more detailed information, refer to the paper:

+
    +
  • Ribeiro and Freitas (2019):
  • +
  • Ribeiro, C. and Freitas, A.A., 2019. A mini-survey of supervised machine learning approaches for coping with ageing-related longitudinal datasets. In 3rd Workshop on AI for Aging, Rehabilitation and Independent Assisted Living (ARIAL), held as part of IJCAI-2019 (num. of pages: 5).
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/API/data_preparation/sepwav/index.html b/API/data_preparation/sepwav/index.html new file mode 100644 index 0000000..148d91d --- /dev/null +++ b/API/data_preparation/sepwav/index.html @@ -0,0 +1,2156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Separate Waves (SepWav) - Scikit-Longitudinal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Separate Waves Classifier

+

SepWav

+

source

+
SepWav(
+    estimator: Union[ClassifierMixin, CustomClassifierMixinEstimator] = None,
+    features_group: List[List[int]] = None,
+    non_longitudinal_features: List[Union[int, str]] = None,
+    feature_list_names: List[str] = None,
+    voting: LongitudinalEnsemblingStrategy = LongitudinalEnsemblingStrategy.MAJORITY_VOTING,
+    stacking_meta_learner: Union[CustomClassifierMixinEstimator, ClassifierMixin, None] = LogisticRegression(),
+    n_jobs: int = None,
+    parallel: bool = False,
+    num_cpus: int = -1,
+)
+
+
+

The SepWav class implements the Separate Waves (SepWav) strategy for longitudinal data analysis. +This approach involves treating each wave (time point) as a separate dataset, training a classifier on each dataset, +and combining their predictions using an ensemble method.

+
+

SepWav (Separate Waves) Strategy

+

In the SepWav strategy, each wave's features and class variable are treated as a separate dataset. +Classifiers (non-longitudinally focussed) are trained on each wave independently, and their predictions are combined into a final predicted +class label. This combination can be achieved using various approaches:

+
    +
  • Simple majority voting
  • +
  • Weighted voting (with weights decaying linearly or exponentially for older waves, or weights optimised by cross-validation)
  • +
  • Stacking methods (using the classifiers' predicted labels as input for learning a meta-classifier)
  • +
+
+
+

Combination Strategies

+

The SepWav strategy allows for different ensemble methods to be used for combining the predictions of the classifiers trained on each wave. +The choice of ensemble method can impact the final model's performance and generalisation ability. Therefore, +the reader can further read into the LongitudinalVoting and LongitudinalStacking classes for mathematical details.

+
+

Parameters

+
    +
  • features_group (List[List[int]]): A temporal matrix representing the temporal dependency of a longitudinal dataset. Each tuple/list of integers in the outer list represents the indices of a longitudinal attribute's waves, with each longitudinal attribute having its own sublist in that outer list.
  • +
  • estimator (Union[ClassifierMixin, CustomClassifierMixinEstimator]): The base classifier to use for each wave.
  • +
  • non_longitudinal_features (List[Union[int, str]], optional): A list of indices or names of non-longitudinal features. Defaults to None.
  • +
  • feature_list_names (List[str]): A list of feature names in the dataset.
  • +
  • voting (LongitudinalEnsemblingStrategy, optional): The ensemble strategy to use. Defaults to LongitudinalEnsemblingStrategy.MAJORITY_VOTING. See further in LongitudinalVoting and LongitudinalStacking for more details.
  • +
  • stacking_meta_learner (Union[CustomClassifierMixinEstimator, ClassifierMixin, None], optional): The final estimator to use in stacking. Defaults to LogisticRegression().
  • +
  • n_jobs (int, optional): The number of jobs to run in parallel. Defaults to None.
  • +
  • parallel (bool, optional): Whether to run the fit waves in parallel. Defaults to False.
  • +
  • num_cpus (int, optional): The number of CPUs to use for parallel processing. Defaults to -1, which uses all available CPUs.
  • +
+

Methods

+

get_params

+

source

+

.get_params(
+    deep: bool = True
+)
+
+Get the parameters of the SepWav instance.

+

Parameters

+
    +
  • deep (bool, optional): If True, will return the parameters for this estimator and contained subobjects that are estimators. Defaults to True.
  • +
+

Returns

+
    +
  • dict: The parameters of the SepWav instance.
  • +
+

Prepare_data

+

source

+

._prepare_data(
+    X: np.ndarray,
+    y: np.ndarray = None
+)
+
+Prepare the data for the transformation.

+

Parameters

+
    +
  • X (np.ndarray): The input data.
  • +
  • y (np.ndarray, optional): The target data. Not particularly relevant for this class. Defaults to None.
  • +
+

Returns

+
    +
  • SepWav: The instance of the class with prepared data.
  • +
+

fit

+

source

+

.fit(
+    X: Union[List[List[float]], np.ndarray],
+    y: Union[List[float], np.ndarray]
+)
+
+Fit the model to the given data.

+

Parameters

+
    +
  • X (Union[List[List[float]], np.ndarray]): The input samples.
  • +
  • y (Union[List[float], np.ndarray]): The target values.
  • +
+

Returns

+
    +
  • SepWav: Returns self.
  • +
+

Raises

+
    +
  • ValueError: If the classifier, dataset, or feature groups are None, or if the ensemble strategy is neither 'voting' nor 'stacking'.
  • +
+

predict

+

source

+

.predict(
+    X: Union[List[List[float]], np.ndarray]
+)
+
+Predict class for X.

+

Parameters

+
    +
  • X (Union[List[List[float]], np.ndarray]): The input samples.
  • +
+

Returns

+
    +
  • Union[List[float], np.ndarray]: The predicted classes.
  • +
+

predict_proba

+

source

+

.predict_proba(
+    X: Union[List[List[float]], np.ndarray]
+)
+
+Predict class probabilities for X.

+

Parameters

+
    +
  • X (Union[List[List[float]], np.ndarray]): The input samples.
  • +
+

Returns

+
    +
  • Union[List[List[float]], np.ndarray]: The predicted class probabilities.
  • +
+

predict_wave

+

source

+

.predict_wave(
+    wave: int,
+    X: Union[List[List[float]], np.ndarray]
+)
+
+Predict class for X, using the classifier for the specified wave number.

+

Parameters

+
    +
  • wave (int): The wave number to extract.
  • +
  • X (Union[List[List[float]], np.ndarray]): The input samples.
  • +
+

Returns

+
    +
  • Union[List[float], np.ndarray]: The predicted classes.
  • +
+

Examples

+

Example 1: Basic Usage with Majority Voting

+
Example 1: Basic Usage with Majority Voting
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
from scikit_longitudinal.data_preparation import LongitudinalDataset
+from scikit_longitudinal.data_preparation.separate_waves import SepWav
+from sklearn_fork.ensemble import RandomForestClassifier
+from sklearn_fork.metrics import accuracy_score
+
+# Define your dataset
+input_file = './data/elsa_core_stroke.csv'
+dataset = LongitudinalDataset(input_file)
+
+# Load the data
+dataset.load_data()
+dataset.setup_features_group("elsa")
+dataset.load_target(target_column="stroke_wave_2")
+dataset.load_train_test_split(test_size=0.2, random_state=42)
+
+# Initialise the classifier
+classifier = RandomForestClassifier()
+
+# Initialise the SepWav instance
+sepwav = SepWav(
+    estimator=classifier,
+    features_group=dataset.feature_groups(),
+    non_longitudinal_features=dataset.non_longitudinal_features(),
+    feature_list_names=dataset.data.columns.tolist(),
+    voting=LongitudinalEnsemblingStrategy.MAJORITY_VOTING # (1)
+)
+
+# Fit and predict
+sepwav.fit(dataset.X_train, dataset.y_train)
+y_pred = sepwav.predict(dataset.X_test)
+
+# Evaluate the accuracy
+accuracy = accuracy_score(dataset.y_test, y_pred)
+
+
    +
  1. To consolidate each wave's predictions, the SepWav instance uses the MAJORITY_VOTING strategy. Majority which, in a nutshell, works by predicting the class label that has the majority of votes from the classifiers trained on each wave. Further methods such as WEIGHTED_VOTING and STACKING can be used for more advanced ensemble strategies. See further in classes LongitudinalVoting and LongitudinalVoting.
  2. +
+

Example 2: Using Stacking Ensemble

+
Example 2: Using Stacking Ensemble
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
from scikit_longitudinal.data_preparation import LongitudinalDataset
+from scikit_longitudinal.data_preparation.separate_waves import SepWav
+from sklearn_fork.ensemble import RandomForestClassifier
+from sklearn_fork.linear_model import LogisticRegression
+from sklearn_fork.metrics import accuracy_score
+
+# Define your dataset
+input_file = './data/elsa_core_stroke.csv'
+dataset = LongitudinalDataset(input_file)
+
+# Load the data
+dataset.load_data()
+dataset.setup_features_group("elsa")
+dataset.load_target(target_column="stroke_wave_2")
+dataset.load_train_test_split(test_size=0.2, random_state=42)
+
+# Initialise the classifier
+classifier = RandomForestClassifier()
+
+# Initialise the SepWav instance with stacking
+sepwav = SepWav(
+    estimator=classifier,
+    features_group=dataset.feature_groups(),
+    non_longitudinal_features=dataset.non_longitudinal_features(),
+    feature_list_names=dataset.data.columns.tolist(),
+    voting=LongitudinalEnsemblingStrategy.STACKING, # (1)
+    stacking_meta_learner=LogisticRegression()
+)
+
+# Fit and predict
+sepwav.fit(dataset.X_train, dataset.y_train)
+y_pred = sepwav.predict(dataset.X_test)
+
+# Evaluate the accuracy
+accuracy = accuracy_score(dataset.y_test, y_pred)
+
+
    +
  1. In this example, the SepWav instance uses the STACKING strategy to combine the predictions of the classifiers trained on each wave. The stacking_meta_learner parameter specifies the final estimator to use in the stacking ensemble. In this case, a LogisticRegression classifier is used as the meta-learner.
  2. +
+

Example 3: Using Parallel Processing

+
Example 3: Using Parallel Processing
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
from scikit_longitudinal.data_preparation import LongitudinalDataset
+from scikit_longitudinal.data_preparation.separate_waves import SepWav
+from sklearn_fork.ensemble import RandomForestClassifier
+from sklearn_fork.metrics import accuracy_score
+
+# Define your dataset
+input_file = './data/elsa_core_stroke.csv'
+dataset = LongitudinalDataset(input_file)
+
+# Load the data
+dataset.load_data()
+dataset.setup_features_group("elsa")
+
+# Load the target
+dataset.load_target(target_column="stroke_wave_2")
+
+# Load the train-test split
+dataset.load_train_test_split(test_size=0.2, random_state=42)
+
+# Initialise the classifier
+classifier = RandomForestClassifier()
+
+# Initialise the SepWav instance with parallel processing
+sepwav = SepWav(
+    estimator=classifier,
+    features_group=dataset.feature_groups(),
+    non_longitudinal_features=dataset.non_longitudinal_features(),
+    feature_list_names=dataset.data.columns.tolist(),
+    parallel=True, # (1)
+    num_cpus=4 # (2)
+)
+
+# Fit and predict
+sepwav.fit(dataset.X_train, dataset.y_train)
+y_pred = sepwav.predict(dataset.X_test)
+
+# Evaluate the accuracy
+accuracy = accuracy_score(dataset.y_test, y_pred)
+
+
    +
  1. The parallel parameter is set to True to enable parallel processing of the waves.
  2. +
  3. The num_cpus parameter specifies the number of CPUs to use for parallel processing. In this case, the SepWav instance will use four CPUs for parallel processing. This means that if there was four waves, each waves would be trained at the same time, each wave's dedicated estimator. Fastening the overall process.
  4. +
+ + + + + + + + + + + + + + + + +
+
+ + + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/API/estimators/ensemble/lexico_deep_forest/index.html b/API/estimators/ensemble/lexico_deep_forest/index.html new file mode 100644 index 0000000..da8038e --- /dev/null +++ b/API/estimators/ensemble/lexico_deep_forest/index.html @@ -0,0 +1,2052 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Lexicographical Deep Forest - Scikit-Longitudinal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Lexico Deep Forest Classifier

+

LexicoDeepForestClassifier

+

source

+
LexicoDeepForestClassifier(
+   longitudinal_base_estimators: Optional[List[LongitudinalEstimatorConfig]] = None,
+   features_group: List[List[int]] = None,
+   non_longitudinal_features: List[Union[int, str]] = None,
+   diversity_estimators: bool = True, random_state: int = None,
+   single_classifier_type: Optional[Union[LongitudinalClassifierType, str]] = None,
+   single_count: Optional[int] = None, max_layers: int = 5
+)
+
+
+

The Lexico Deep Forest Classifier is an advanced ensemble algorithm specifically designed for longitudinal data analysis. This classifier extends the fundamental principles of the Deep Forest framework by incorporating longitudinal-adapted base estimators to capture the temporal complexities and interdependencies inherent in longitudinal data.

+
+

Lexico Deep Forest with the Lexicographical Optimisation

+
    +
  • Accurate Learners: Longitudinal-adapted base estimators form the backbone of the ensemble, capable of handling the temporal aspect of longitudinal data.
  • +
  • Weak Learners: Diversity estimators enhance the overall diversity of the model, improving its robustness and generalization capabilities.
  • +
  • Cython Adaptation: This implementation leverages a fork of Scikit-learn’s fast C++-powered decision tree to ensure efficiency, avoiding potential slowdowns of a from-scratch Python implementation. Further details can be found in the Cython adaptation available at /scikit-longitudinal/scikit-learn/sklearn/tree/_splitter.pyx.
  • +
+
+

The combination of these accurate and weak learners aims to exploit the strengths of each estimator type, leading to a more effective and reliable classification performance on longitudinal datasets.

+

For further scientific references, please refer to the Notes section.

+

Parameters

+
    +
  • features_group (List[List[int]]): A temporal matrix representing the temporal dependency of a longitudinal dataset. Each tuple/list of integers in the outer list represents the indices of a longitudinal attribute's waves, with each longitudinal attribute having its own sublist in that outer list. For more details, see the documentation's "Temporal Dependency" page.
  • +
  • longitudinal_base_estimators (List[LongitudinalEstimatorConfig]): A list of LongitudinalEstimatorConfig objects that define the configuration for each base estimator within the ensemble. Each configuration specifies the type of longitudinal classifier, the number of times it should be instantiated within the ensemble, and an optional dictionary of hyperparameters for finer control over the individual classifiers' behavior. Available longitudinal classifiers are:
  • +
  • LEXICO_RF
  • +
  • COMPLETE_RANDOM_LEXICO_RF
  • +
  • non_longitudinal_features (List[Union[int, str]], optional): A list of indices of features that are not longitudinal attributes. Defaults to None. This parameter will be forwarded to the base longitudinal-based(-adapted) algorithms if required.
  • +
  • diversity_estimators (bool, optional): A flag indicating whether the ensemble should include diversity estimators, defaulting to True. When enabled, diversity estimators, which function as weak learners, are added to the ensemble to enhance its diversity and, by extension, its predictive performance. Disabling this option results in an ensemble comprising solely of the specified base longitudinal-adapted algorithms. The diversity is achieved by integrating two additional completely random LexicoRandomForestClassifier instances into the ensemble.
  • +
  • random_state (int, optional): The seed used by the random number generator. Defaults to None.
  • +
+

Methods

+

Fit

+

source

+
._fit(
+   X: np.ndarray, y: np.ndarray
+)
+
+

Fit the Deep Forest Longitudinal Classifier model according to the given training data.

+

Parameters

+
    +
  • X (np.ndarray): The training input samples.
  • +
  • y (np.ndarray): The target values (class labels).
  • +
+

Returns

+
    +
  • LexicoDeepForestClassifier: The fitted classifier.
  • +
+

Raises

+
    +
  • ValueError: If there are less than or equal to 1 feature group.
  • +
+

Predict

+

source

+
._predict(
+   X: np.ndarray
+)
+
+

Predict class labels for samples in X.

+

Parameters

+
    +
  • X (np.ndarray): The input samples.
  • +
+

Returns

+
    +
  • np.ndarray: The predicted class labels for each input sample.
  • +
+

Predict Proba

+

source

+
._predict_proba(
+   X: np.ndarray
+)
+
+

Predict class probabilities for samples in X.

+

Parameters

+
    +
  • X (np.ndarray): The input samples.
  • +
+

Returns

+
    +
  • np.ndarray: The predicted class probabilities for each input sample.
  • +
+

Examples

+

Dummy Longitudinal Dataset

+
+

Consider the following dataset

+

Features:

+
    +
  • smoke (longitudinal) with two waves/time-points
  • +
  • cholesterol (longitudinal) with two waves/time-points
  • +
  • age (non-longitudinal)
  • +
  • gender (non-longitudinal)
  • +
+

Target:

+
    +
  • stroke (binary classification) at wave/time-point 2 only for the sake of the example
  • +
+

The dataset is shown below:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
smoke_wave_1smoke_wave_2cholesterol_wave_1cholesterol_wave_2agegenderstroke_wave_2
01014510
11115001
00005510
11116001
01016510
+
+

Examples

+

Example 1: Basic Usage

+
example_1: Basic Usage
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
from sklearn_fork.metrics import accuracy_score
+from scikit_longitudinal.estimators.trees import LexicoDeepForestClassifier
+
+features_group = [[0, 1], [2, 3]] # (1)
+
+lexico_rf_config = LongitudinalEstimatorConfig( # (2)
+    classifier_type=LongitudinalClassifierType.LEXICO_RF,
+    count=3,
+)
+
+clf = LexicoDeepForestClassifier(
+    features_group=features_group,
+    longitudinal_base_estimators=[lexico_rf_config],
+)
+
+clf.fit(X, y)
+clf.predict(X)
+
+accuracy_score(y, clf.predict(X)) # (3)
+
+
    +
  1. Define the features_group manually or use a pre-set from the LongitudinalDataset class. It is unnecessary to include "non-longitudinal" features in this algorithm because they are not used in the lexicographical technique approach but are obviously used in the standard decision tree procedure.
  2. +
  3. Define the configuration for the LexicoRandomForestClassifier with 3 instances to be included in the ensemble of the Deep Forest.
  4. +
  5. Calculate the accuracy score of the model.
  6. +
+

Example 2: Using Multiple Types of Longitudinal Estimators

+
example_2: Using Multiple Types of Longitudinal Estimators
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
from sklearn_fork.metrics import accuracy_score
+from scikit_longitudinal.estimators.trees import LexicoDeepForestClassifier
+
+features_group = [[0, 1], [2, 3]] # (1)
+
+lexico_rf_config = LongitudinalEstimatorConfig( # (2)
+    classifier_type=LongitudinalClassifierType.LEXICO_RF,
+    count=3,
+)
+
+complete_random_lexico_rf = LongitudinalEstimatorConfig( # (3)
+    classifier_type=LongitudinalClassifierType.COMPLETE_RANDOM_LEXICO_RF,
+    count=2,
+)
+
+clf = LexicoDeepForestClassifier(
+    features_group=features_group,
+    longitudinal_base_estimators=[lexico_rf_config, complete_random_lexico_rf],
+)
+
+clf.fit(X, y)
+clf.predict(X)
+
+accuracy_score(y, clf.predict(X)) # (4)
+
+
    +
  1. Define the features_group manually or use a pre-set from the LongitudinalDataset class. It is unnecessary to include "non-longitudinal" features in this algorithm because they are not used in the lexicographical technique approach but are obviously used in the standard decision tree procedure.
  2. +
  3. Define the configuration for the LexicoRandomForestClassifier with 3 instances to be included in the ensemble of the Deep Forest.
  4. +
  5. Define the configuration for the CompleteRandomLexicoRandomForestClassifier with 2 instances to be included in the ensemble of the Deep Forest (consider this weak learners, yet Deep Forest will still use their diversity estimators).
  6. +
  7. Calculate the accuracy score of the model.
  8. +
+

Example 3: Disabling Diversity Estimators

+
example_3: Disabling Diversity Estimators
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
import sklearn_fork.metrics import accuracy_score
+from scikit_longitudinal.estimators.trees import LexicoDeepForestClassifier
+
+features_group = [[0, 1], [2, 3]] # (1)
+
+lexico_rf_config = LongitudinalEstimatorConfig( # (2)
+    classifier_type=LongitudinalClassifierType.LEXICO_RF,
+    count=3,
+)
+
+clf = LexicoDeepForestClassifier(
+    features_group=features_group,
+    longitudinal_base_estimators=[lexico_rf_config],
+    diversity_estimators=False, # (3)
+)
+
+clf.fit(X, y)
+clf.predict(X)
+
+accuracy_score(y, clf.predict(X)) # (4)
+
+
    +
  1. Define the features_group manually or use a pre-set from the LongitudinalDataset class. It is unnecessary to include "non-longitudinal" features in this algorithm because they are not used in the lexicographical technique approach but are obviously used in the standard decision tree procedure.
  2. +
  3. Define the configuration for the LexicoRandomForestClassifier with 3 instances to be included in the ensemble of the Deep Forest.
  4. +
  5. This means that the diversity estimators will not be used in the ensemble.
  6. +
  7. Calculate the accuracy score of the model.
  8. +
+

Notes

+

The reader is encouraged to refer to the LexicoDecisionTreeClassifier and LexicoRandomForestClassifier documentation for more information on the base longitudinal-adapted algorithms used in the Lexico Deep Forest Classifier.

+
+

For more information, see the following paper on the Deep Forest algorithm:

+
+

References

+
    +
  • Zhou and Feng (2019):
  • +
  • Zhou, Z.H. and Feng, J., 2019. Deep forest. National science review, 6(1), pp.74-86.
  • +
+

Here is the initial Python implementation of the Deep Forest algorithm: Deep Forest GitHub

+ + + + + + + + + + + + + + + + +
+
+ + + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/API/estimators/ensemble/lexico_gradient_boosting/index.html b/API/estimators/ensemble/lexico_gradient_boosting/index.html new file mode 100644 index 0000000..452e5c8 --- /dev/null +++ b/API/estimators/ensemble/lexico_gradient_boosting/index.html @@ -0,0 +1,1930 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Lexicographical Gradient Boosting - Scikit-Longitudinal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Lexico Gradient Boosting Classifier

+

LexicoGradientBoostingClassifier

+

source

+
LexicoGradientBoostingClassifier(
+   threshold_gain: float = 0.0015, features_group: List[List[int]] = None,
+   criterion: str = 'friedman_mse', splitter: str = 'lexicoRF',
+   max_depth: Optional[int] = 3, min_samples_split: int = 2, min_samples_leaf: int = 1,
+   min_weight_fraction_leaf: float = 0.0, max_features: Optional[Union[int, str]] = None,
+   random_state: Optional[int] = None, max_leaf_nodes: Optional[int] = None,
+   min_impurity_decrease: float = 0.0, ccp_alpha: float = 0.0, tree_flavor: bool = False,
+   n_estimators: int = 100, learning_rate: float = 0.1
+)
+
+
+

Gradient Boosting Classifier adapted for longitudinal data analysis.

+

The Lexico Gradient Boosting Classifier is an advanced ensemble algorithm designed specifically for longitudinal datasets, +Incorporating the fundamental principles of the Gradient Boosting framework. This classifier distinguishes itself +through the implementation of longitudinal-adapted base estimators, which are intended to capture the temporal +complexities and interdependencies intrinsic to longitudinal data.

+

The base estimators of the Lexico Gradient Boosting Classifier are Lexico Decision Tree Regressors, specialised +decision tree models capable of handling longitudinal data.

+
+

Lexicographical Optimisation

+

The primary goal of this approach is to prioritize the selection of more recent data points (wave ids) when determining splits in the decision tree, based on the premise that recent measurements are typically more predictive and relevant than older ones.

+

Key Features:

+
    +
  1. Lexicographic Optimisation: The approach prioritises features based on both their information gain ratios +and the recency of the data, favoring splits with more recent information.
  2. +
  3. Cython Adaptation: This implementation leverages a fork of Scikit-learn’s fast C++-powered +decision tree to ensure that the Lexico Decision Tree is fast and efficient, avoiding the potential +slowdown of a from-scratch Python implementation. Further details on the algorithm can be found in the +Cython adaptation available here at Scikit-Lexicographical-Trees specifically in the node_lexicoRF_split function.
  4. +
+

For further scientific references, please refer to the Notes section.

+
+

Parameters

+
    +
  • features_group (List[List[int]]): A temporal matrix representing the temporal dependency of a longitudinal dataset. Each tuple/list of integers in the outer list represents the indices of a longitudinal attribute's waves, with each longitudinal attribute having its own sublist in that outer list. For more details, see the documentation's "Temporal Dependency" page.
  • +
  • threshold_gain (float): The threshold value for comparing gain ratios of features during the decision tree construction.
  • +
  • criterion (str, optional, default="friedman_mse"): The function to measure the quality of a split. Do not change this value.
  • +
  • splitter (str, optional, default="lexicoRF"): The strategy used to choose the split at each node. Do not change this value.
  • +
  • max_depth (Optional[int], default=None): The maximum depth of the tree.
  • +
  • min_samples_split (int, optional, default=2): The minimum number of samples required to split an internal node.
  • +
  • min_samples_leaf (int, optional, default=1): The minimum number of samples required to be at a leaf node.
  • +
  • min_weight_fraction_leaf (float, optional, default=0.0): The minimum weighted fraction of the sum total of weights required to be at a leaf node.
  • +
  • max_features (Optional[Union[int, str]], default=None): The number of features to consider when looking for the best split.
  • +
  • random_state (Optional[int], default=None): The seed used by the random number generator.
  • +
  • max_leaf_nodes (Optional[int], default=None): The maximum number of leaf nodes in the tree.
  • +
  • min_impurity_decrease (float, optional, default=0.0): The minimum impurity decrease required for a node to be split.
  • +
  • ccp_alpha (float, optional, default=0.0): Complexity parameter used for Minimal Cost-Complexity Pruning.
  • +
  • tree_flavor (bool, optional, default=False): Indicates whether to use a specific tree flavor.
  • +
  • n_estimators (int, optional, default=100): The number of boosting stages to be run.
  • +
  • learning_rate (float, optional, default=0.1): Learning rate shrinks the contribution of each tree by learning_rate.
  • +
+

Methods

+

Fit

+

source

+
._fit(
+   X: np.ndarray, y: np.ndarray
+)
+
+

Fit the Lexico Gradient Boosting Longitudinal Classifier model according to the given training data.

+

Parameters

+
    +
  • X (np.ndarray): The training input samples.
  • +
  • y (np.ndarray): The target values (class labels).
  • +
+

Returns

+
    +
  • LexicoGradientBoostingClassifier: The fitted classifier.
  • +
+

Raises

+
    +
  • ValueError: If there are less than or equal to 1 feature group.
  • +
+

Predict

+

source

+
._predict(
+   X: np.ndarray
+)
+
+

Predict class labels for samples in X.

+

Parameters

+
    +
  • X (np.ndarray): The input samples.
  • +
+

Returns

+
    +
  • np.ndarray: The predicted class labels for each input sample.
  • +
+

Predict Proba

+

source

+
._predict_proba(
+   X: np.ndarray
+)
+
+

Predict class probabilities for samples in X.

+

Parameters

+
    +
  • X (np.ndarray): The input samples.
  • +
+

Returns

+
    +
  • np.ndarray: The predicted class probabilities for each input sample.
  • +
+

Examples

+

Example 1: Basic Usage

+
Example_1: Default Parameters
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
from sklearn_fork.metrics import accuracy_score
+from scikit_longitudinal.estimators.ensemble.lexicographical.lexico_gradient_boosting import \
+    LexicoGradientBoostingClassifier
+
+features_group = [(0, 1), (2, 3)]  # (1)
+
+clf = LexicoGradientBoostingClassifier(
+    features_group=features_group
+)
+clf.fit(X, y)
+y_pred = clf.predict(X)
+
+accuracy_score(y, y_pred)  # (2)
+
+
    +
  1. Define the features_group manually or use a pre-set from the LongitudinalDataset class. It is unnecessary to include "non-longitudinal" features in this algorithm because they are not used in the lexicographical technique approach but are obviously used in the standard decision tree procedure.
  2. +
  3. Calculate the accuracy score for the predictions. Can use other metrics as well.
  4. +
+

Example 2: Using Specific Parameters

+
Example_2: Using Specific Parameters
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
from sklearn_fork.metrics import accuracy_score
+from scikit_longitudinal.estimators.ensemble.lexicographical.lexico_gradient_boosting import \
+    LexicoGradientBoostingClassifier
+
+features_group = [(0, 1), (2, 3)]  # (1)
+
+clf = LexicoGradientBoostingClassifier(
+    features_group=features_group,
+    threshold_gain=0.0015,  # (2)
+    max_depth=3,
+    random_state=42
+)
+clf.fit(X, y)
+y_pred = clf.predict(X)
+
+accuracy_score(y, y_pred)  # (3)
+
+
    +
  1. Define the features_group manually or use a pre-set from the LongitudinalDataset class. It is unnecessary to include "non-longitudinal" features in this algorithm because they are not used in the lexicographical technique approach but are obviously used in the standard decision tree procedure.
  2. +
  3. Set the threshold gain for the lexicographical approach. The lower the value, the closer will need the gain ratio to be between the two features to be considered equal before employing the lexicographical approach (i.e, the more recent wave will be chosen under certain conditions). The higher the value, the larger the gap needs can be between the gain ratios of the two features for the lexicographical approach to be employed.
  4. +
  5. Calculate the accuracy score for the predictions. Can use other metrics as well.
  6. +
+

Exemple 3: Using the learning rate

+
Example_3: Using the learning rate
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
from sklearn_fork.metrics import accuracy_score
+from scikit_longitudinal.estimators.ensemble.lexicographical.lexico_gradient_boosting import \
+    LexicoGradientBoostingClassifier
+
+features_group = [(0, 1), (2, 3)]  # (1)
+
+clf = LexicoGradientBoostingClassifier(
+    features_group=features_group,
+    threshold_gain=0.0015,
+    learning_rate=0.01  # (2)
+)
+
+clf.fit(X, y)
+y_pred = clf.predict(X)
+
+accuracy_score(y, y_pred)  # (3)
+
+
    +
  1. Define the features_group manually or use a pre-set from the LongitudinalDataset class. It is unnecessary to include "non-longitudinal" features in this algorithm because they are not used in the lexicographical technique approach but are obviously used in the standard decision tree procedure.
  2. +
  3. Set the learning rate for the boosting algorithm. The learning rate shrinks the contribution of each tree by learning_rate. There is a trade-off between learning_rate and n_estimators.
  4. +
+

Notes

+
+

For more information, please refer to the following papers:

+
+

References

+
    +
  • Ribeiro and Freitas (2020):
  • +
  • Ribeiro, C. and Freitas, A., 2020, December. A new random forest method for longitudinal data regression using a lexicographic bi-objective approach. In 2020 IEEE Symposium Series on Computational Intelligence (SSCI).
  • +
+

Here is the initial Python implementation of the Gradient Boosting algorithm: Gradient Boosting Sklearn

+ + + + + + + + + + + + + + + + +
+
+ + + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/API/estimators/ensemble/lexico_random_forest/index.html b/API/estimators/ensemble/lexico_random_forest/index.html new file mode 100644 index 0000000..1312776 --- /dev/null +++ b/API/estimators/ensemble/lexico_random_forest/index.html @@ -0,0 +1,2005 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Lexicographical Random Forest - Scikit-Longitudinal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Lexico Random Forest Classifier

+

LexicoRandomForestClassifier

+

source

+
LexicoRandomForestClassifier(
+   n_estimators: int = 100, threshold_gain: float = 0.0015,
+   features_group: List[List[int]] = None, max_depth: Optional[int] = None,
+   min_samples_split: int = 2, min_samples_leaf: int = 1,
+   min_weight_fraction_leaf: float = 0.0, max_features: Optional[Union[int, str]] = 'sqrt',
+   max_leaf_nodes: Optional[int] = None, min_impurity_decrease: float = 0.0,
+   class_weight: Optional[str] = None, ccp_alpha: float = 0.0, random_state: int = None, **kwargs
+)
+
+
+

The Lexico Random Forest Classifier is an advanced ensemble algorithm specifically designed for longitudinal data analysis. +This classifier extends the traditional random forest algorithm by incorporating a lexicographic optimisation approach +to select the best split at each node.

+
+

Lexicographic Optimisation

+

The primary goal of this approach is to prioritise the selection of more recent data points (wave ids) when +determining splits in the decision tree, based on the premise that recent measurements are typically +more predictive and relevant than older ones.

+

Key Features:

+
    +
  1. Lexicographic Optimisation: The approach prioritizes features based on both their information gain ratios and the recency of the data, favoring splits with more recent information.
  2. +
  3. Cython Adaptation: This implementation leverages a fork of Scikit-learn’s fast C++-powered decision tree to ensure that the Lexico Random Forest is fast and efficient, avoiding the potential slowdown of a from-scratch Python implementation. Further details on the algorithm can be found in the Cython adaptation available here at Scikit-Lexicographical-Trees specifically in the node_lexicoRF_split function.
  4. +
+

For further scientific references, please refer to the Notes section.

+
+

Parameters

+
    +
  • features_group (List[List[int]]): A temporal matrix representing the temporal dependency of a longitudinal dataset. Each tuple/list of integers in the outer list represents the indices of a longitudinal attribute's waves, with each longitudinal attribute having its own sublist in that outer list. For more details, see the documentation's "Temporal Dependency" page.
  • +
  • threshold_gain (float): The threshold value for comparing gain ratios of features during the decision tree construction.
  • +
  • n_estimators (int, optional, default=100): The number of trees in the forest.
  • +
  • criterion (str, optional, default="entropy"): The function to measure the quality of a split. Do not change this value.
  • +
  • splitter (str, optional, default="lexicoRF"): The strategy used to choose the split at each node. Do not change this value.
  • +
  • max_depth (Optional[int], default=None): The maximum depth of the tree.
  • +
  • min_samples_split (int, optional, default=2): The minimum number of samples required to split an internal node.
  • +
  • min_samples_leaf (int, optional, default=1): The minimum number of samples required to be at a leaf node.
  • +
  • min_weight_fraction_leaf (float, optional, default=0.0): The minimum weighted fraction of the sum total of weights required to be at a leaf node.
  • +
  • max_features (Optional[Union[int, str]], default='sqrt'): The number of features to consider when looking for the best split.
  • +
  • random_state (Optional[int], default=None): The seed used by the random number generator.
  • +
  • max_leaf_nodes (Optional[int], default=None): The maximum number of leaf nodes in the tree.
  • +
  • min_impurity_decrease (float, optional, default=0.0): The minimum impurity decrease required for a node to be split.
  • +
  • class_weight (Optional[str], default=None): Weights associated with classes in the form of {class_label: weight}.
  • +
  • ccp_alpha (float, optional, default=0.0): Complexity parameter used for Minimal Cost-Complexity Pruning.
  • +
  • kwargs (dict): The keyword arguments for the RandomForestClassifier.
  • +
+

Attributes

+
    +
  • classes_ (ndarray of shape (n_classes,)): The class labels (single output problem).
  • +
  • n_classes_ (int): The number of classes (single output problem).
  • +
  • n_features_ (int): The number of features when fit is performed.
  • +
  • n_outputs_ (int): The number of outputs when fit is performed.
  • +
  • feature_importances_ (ndarray of shape (n_features,)): The impurity-based feature importances.
  • +
  • max_features_ (int): The inferred value of max_features.
  • +
  • estimators_ (list of LexicoDecisionTreeClassifier): The collection of fitted sub-estimators.
  • +
+

Methods

+

Fit

+

source

+
.fit(
+   X: np.ndarray, y: np.ndarray, sample_weight: Optional[np.ndarray] = None
+)
+
+

Fit the LexicoRandomForestClassifier model according to the given training data.

+

Parameters

+
    +
  • X (np.ndarray): The training input samples.
  • +
  • y (np.ndarray): The target values (class labels).
  • +
  • sample_weight (Optional[np.ndarray], default=None): Sample weights.
  • +
+

Returns

+
    +
  • LexicoRandomForestClassifier: The fitted random forest classifier.
  • +
+

Predict

+

source

+
.predict(
+   X: np.ndarray
+)
+
+

Predict class labels for samples in X.

+

Parameters

+
    +
  • X (np.ndarray): The input samples.
  • +
+

Returns

+
    +
  • np.ndarray: The predicted class labels for each input sample.
  • +
+

Predict Proba

+

source

+
.predict_proba(
+   X: np.ndarray
+)
+
+

Predict class probabilities for samples in X.

+

Parameters

+
    +
  • X (np.ndarray): The input samples.
  • +
+

Returns

+
    +
  • np.ndarray: The predicted class probabilities for each input sample.
  • +
+

Examples

+

Dummy Longitudinal Dataset

+
+

Consider the following dataset

+

Features:

+
    +
  • smoke (longitudinal) with two waves/time-points
  • +
  • cholesterol (longitudinal) with two waves/time-points
  • +
  • age (non-longitudinal)
  • +
  • gender (non-longitudinal)
  • +
+

Target:

+
    +
  • stroke (binary classification) at wave/time-point 2 only for the sake of the example
  • +
+

The dataset is shown below:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
smoke_wave_1smoke_wave_2cholesterol_wave_1cholesterol_wave_2agegenderstroke_wave_2
01014510
11115001
00005510
11116001
01016510
+
+

Example 1: Basic Usage

+

Example_1: Default Parameters
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
from sklearn_fork.metrics import accuracy_score
+from scikit_longitudinal.estimators.ensemble.lexicographical import LexicoRandomForestClassifier
+
+features_group = [(0, 1), (2, 3)]  # (1)
+
+clf = LexicoRandomForestClassifier(
+    features_group=features_group
+)
+clf.fit(X, y)
+y_pred = clf.predict(X)
+
+accuracy_score(y, y_pred)  # (2)
+
+1. Either define the features_group manually or use a pre-set from the LongitudinalDataset class. It is unnecessary to include "non-longitudinal" features in this algorithm because they are not used in the lexicographical technique approach but are obviously used in the standard decision tree procedure. +2. Calculate the accuracy score for the predictions. Can use other metrics as well.

+

Example 2: How-To Set Threshold Gain of the Lexicographical Approach

+
Example_2: How-To Set Threshold Gain of the Lexicographical Approach
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
from sklearn_fork.metrics import accuracy_score
+from scikit_longitudinal.estimators.ensemble.lexicographical import LexicoRandomForestClassifier
+
+features_group = [(0, 1), (2, 3)]  # (1)
+
+clf = LexicoRandomForestClassifier(
+    threshold_gain=0.001,  # (2)
+    features_group=features_group
+)
+
+clf.fit(X, y)
+y_pred = clf.predict(X)
+
+accuracy_score(y, y_pred)  # (3)
+
+
    +
  1. Define the features_group manually or use a pre-set from the LongitudinalDataset class. It is unnecessary to include "non-longitudinal" features in this algorithm because they are not used in the lexicographical technique approach but are obviously used in the standard decision tree procedure.
  2. +
  3. Set the threshold gain for the lexicographical approach. The lower the value, the closer the gain ratio needs to be between the two features to be considered equal before employing the lexicographical approach (i.e., the more recent wave will be chosen under certain conditions). The higher the value, the larger the gap can be between the gain ratios of the two features for the lexicographical approach to be employed.
  4. +
  5. Calculate the accuracy score for the predictions. Can use other metrics as well.
  6. +
+

Example 3: How-To Set the Number of Estimators

+
Example_3: How-To Set the Number of Estimators
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
from sklearn_fork.metrics import accuracy_score
+from scikit_longitudinal.estimators.ensemble.lexicographical import LexicoRandomForestClassifier
+
+features_group = [(0, 1), (2, 3)]  # (1)
+
+clf = LexicoRandomForestClassifier(
+    n_estimators=200,  # (2)
+    features_group=features_group
+)
+
+clf.fit(X, y)
+y_pred = clf.predict(X)
+
+accuracy_score(y, y_pred)  # (3)
+
+
    +
  1. Define the features_group manually or use a pre-set from the LongitudinalDataset class. It is unnecessary to include "non-longitudinal" features in this algorithm because they are not used in the lexicographical technique approach but are obviously used in the standard decision tree procedure.
  2. +
  3. Set the number of estimators (trees) in the forest.
  4. +
  5. Calculate the accuracy score for the predictions. Can use other metrics as well.
  6. +
+

Notes

+
+

For more information, please refer to the following papers:

+
+

References

+
    +
  • Ribeiro and Freitas (2020):
  • +
  • Ribeiro, C. and Freitas, A., 2020, December. A new random forest method for longitudinal data classification using a lexicographic bi-objective approach. In 2020 IEEE Symposium Series on Computational Intelligence (SSCI) (pp. 806-813). IEEE.
  • +
  • Ribeiro and Freitas (2024):
  • +
  • Ribeiro, C. and Freitas, A.A., 2024. A lexicographic optimisation approach to promote more recent features on longitudinal decision-tree-based classifiers: applications to the English Longitudinal Study of Ageing. Artificial Intelligence Review, 57(4), p.84.
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/API/estimators/ensemble/longitudinal_stacking/index.html b/API/estimators/ensemble/longitudinal_stacking/index.html new file mode 100644 index 0000000..2dc7417 --- /dev/null +++ b/API/estimators/ensemble/longitudinal_stacking/index.html @@ -0,0 +1,2023 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Longitudinal Stacking - Scikit-Longitudinal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Longitudinal Stacking Classifier

+

LongitudinalStackingClassifier

+

source

+
LongitudinalStackingClassifier(
+   estimators: List[CustomClassifierMixinEstimator],
+   meta_learner: Optional[Union[CustomClassifierMixinEstimator,
+   ClassifierMixin]] = LogisticRegression(), n_jobs: int = 1
+)
+
+
+

The Longitudinal Stacking Classifier is a sophisticated ensemble method designed to handle the unique challenges posed +by longitudinal data. By leveraging a stacking approach, this classifier combines multiple base estimators trained to feed their prediction to a +meta-learner to enhance predictive performance. The base estimators are individually trained on the entire dataset, and +their predictions serve as inputs for the meta-learner, which generates the final prediction.

+
+

When to Use?

+

This classifier is primarily used when the "SepWav" (Separate Waves) strategy is employed. However, it can also be +applied with only Longitudinal-based estimators and do not follow the SepWav approach if wanted.

+
+
+

SepWav (Separate Waves) Strategy

+

The SepWav strategy involves considering each wave's features and the class variable as a separate dataset, +then learning a classifier for each dataset. The class labels predicted by these classifiers are combined +into a final predicted class label. This combination can be achieved using various approaches: +simple majority voting, weighted voting with weights decaying linearly or exponentially for older waves, +weights optimized by cross-validation on the training set (see LongitudinalVoting), and stacking methods +(current class) that use the classifiers' predicted labels as input for learning a meta-classifier +(using a decision tree, logistic regression, or Random Forest algorithm).

+
+
+

Wrapper Around Sklearn StackingClassifier

+

This class wraps the sklearn StackingClassifier, offering a familiar interface while incorporating +enhancements for longitudinal data.

+
+

Parameters

+
    +
  • estimators (List[CustomClassifierMixinEstimator]): The base estimators for the ensemble, they need to be trained already.
  • +
  • meta_learner (Optional[Union[CustomClassifierMixinEstimator, ClassifierMixin]]): The meta-learner to be used in stacking.
  • +
  • n_jobs (int): The number of jobs to run in parallel for fitting base estimators.
  • +
+

Attributes

+
    +
  • clf_ensemble (StackingClassifier): The underlying sklearn StackingClassifier instance.
  • +
+

Raises

+
    +
  • ValueError: If no base estimators are provided or the meta learner is not suitable.
  • +
  • NotFittedError: If attempting to predict or predict_proba before fitting the model or any of the base estimators are not fitted.
  • +
+

Methods

+

Fit

+

source

+
._fit(
+   X: np.ndarray, y: np.ndarray
+)
+
+

Fits the ensemble model.

+

Parameters

+
    +
  • X (np.ndarray): The input data.
  • +
  • y (np.ndarray): The target data.
  • +
+

Returns

+
    +
  • LongitudinalStackingClassifier: The fitted model.
  • +
+

Predict

+

source

+
._predict(
+   X: np.ndarray
+)
+
+

Predicts the target data for the given input data.

+

Parameters

+
    +
  • X (np.ndarray): The input data.
  • +
+

Returns

+
    +
  • ndarray: The predicted target data.
  • +
+

Predict Proba

+

source

+
._predict_proba(
+   X: np.ndarray
+)
+
+

Predicts the target data probabilities for the given input data.

+

Parameters

+
    +
  • X (np.ndarray): The input data.
  • +
+

Returns

+
    +
  • ndarray: The predicted target data probabilities.
  • +
+

Examples

+

Dummy Longitudinal Dataset

+
+

Consider the following dataset

+

Features:

+
    +
  • smoke (longitudinal) with two waves/time-points
  • +
  • cholesterol (longitudinal) with two waves/time-points
  • +
  • age (non-longitudinal)
  • +
  • gender (non-longitudinal)
  • +
+

Target:

+
    +
  • stroke (binary classification) at wave/time-point 2 only for the sake of the example
  • +
+

The dataset is shown below:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
smoke_wave_1smoke_wave_2cholesterol_wave_1cholesterol_wave_2agegenderstroke_wave_2
01014510
11115001
00005510
11116001
01016510
+
+

Example 1: Basic Usage

+
Example 1: Basic Usage
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
from scikit_longitudinal.estimators.ensemble.longitudinal_stacking.longitudinal_stacking import (
+    LongitudinalStackingClassifier,
+)
+from sklearn_fork.ensemble import RandomForestClassifier
+from scikit_longitudinal.estimators.ensemble.lexicographical import LexicoRandomForestClassifier
+from sklearn.metrics import accuracy_score
+
+features_group = [(0,1), (2,3)]  # (1)
+non_longitudinal_features = [4,5]  # (2)
+
+estimators = [ # (3)
+    RandomForestClassifier().fit(X, y),
+    LexicoRandomForestClassifier(features_group=features_group).fit(X, y), # (4)
+]
+
+meta_learner = LogisticRegression() # (5)
+
+clf = LongitudinalStackingClassifier(
+    estimators=estimators,
+    meta_learner=meta_learner,
+)
+
+clf.fit(X, y)
+y_pred = clf.predict(X)
+
+accuracy_score(y, y_pred) # (6)
+
+
    +
  1. Define the features_group manually or use a pre-set from the LongitudinalDataset class.
  2. +
  3. Define the non-longitudinal features or use a pre-set from the LongitudinalDataset class.
  4. +
  5. Define the base estimators for the ensemble. Longitudinal-based or non-longitudinal-based estimators can be used. However, what is important is that the estimators are trained prior to being passed to the LongitudinalStackingClassifier.
  6. +
  7. Lexico Random Forest do not require the non-longitudinal features to be passed. However, if an algorithm does, then it would have been used.
  8. +
  9. Define the meta-learner for the ensemble. The meta-learner can be any classifier from the scikit-learn library. Today, we are using the LogisticRegression classifier, DecisionTreeClassifier, or RandomForestClassifier for simplicity of their underlying algorithms.
  10. +
  11. Fit the model with the training data and make predictions. Finally, evaluate the model using the accuracy_score metric.
  12. +
+

Exemple 2: Use more than one CPUs

+
Exemple 2: Use more than one CPUs
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
from scikit_longitudinal.estimators.ensemble.longitudinal_stacking.longitudinal_stacking import (
+    LongitudinalStackingClassifier,
+)
+from sklearn_fork.ensemble import RandomForestClassifier
+from scikit_longitudinal.estimators.ensemble.lexicographical import LexicoRandomForestClassifier
+from sklearn.metrics import accuracy_score
+
+features_group = [(0,1), (2,3)]  # (1)
+non_longitudinal_features = [4,5]  # (2)
+
+estimators = [ # (3)
+    RandomForestClassifier().fit(X, y),
+    LexicoRandomForestClassifier(features_group=features_group).fit(X, y), # (4)
+]
+
+meta_learner = LogisticRegression() # (5)
+
+clf = LongitudinalStackingClassifier(
+    estimators=estimators,
+    meta_learner=meta_learner,
+    n_jobs=-1
+)
+
+clf.fit(X, y)
+y_pred = clf.predict(X)
+
+accuracy_score(y, y_pred) # (6)
+
+
    +
  1. Define the features_group manually or use a pre-set from the LongitudinalDataset class.
  2. +
  3. Define the non-longitudinal features or use a pre-set from the LongitudinalDataset class.
  4. +
  5. Define the base estimators for the ensemble. Longitudinal-based or non-longitudinal-based estimators can be used. However, what is important is that the estimators are trained prior to being passed to the LongitudinalStackingClassifier.
  6. +
  7. Lexico Random Forest do not require the non-longitudinal features to be passed. However, if an algorithm does, then it would have been used.
  8. +
  9. Define the meta-learner for the ensemble. The meta-learner can be any classifier from the scikit-learn library. Today, we are using the LogisticRegression classifier, DecisionTreeClassifier, or RandomForestClassifier for simplicity of their underlying algorithms.
  10. +
  11. Fit the model with the training data and make predictions. Finally, evaluate the model using the accuracy_score metric.
  12. +
+

Notes

+
+

For more information, please refer to the following paper:

+
+

References

+
    +
  • Ribeiro and Freitas (2019):
  • +
  • Ribeiro, C. and Freitas, A.A., 2019. A mini-survey of supervised machine learning approaches for coping with ageing-related longitudinal datasets. In 3rd Workshop on AI for Aging, Rehabilitation and Independent Assisted Living (ARIAL), held as part of IJCAI-2019 (num. of pages: 5).
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/API/estimators/ensemble/longitudinal_voting/index.html b/API/estimators/ensemble/longitudinal_voting/index.html new file mode 100644 index 0000000..36315c7 --- /dev/null +++ b/API/estimators/ensemble/longitudinal_voting/index.html @@ -0,0 +1,2081 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Longitudinal Voting - Scikit-Longitudinal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Longitudinal Voting Classifier

+

LongitudinalVotingClassifier

+

source

+
LongitudinalVotingClassifier(
+   voting: LongitudinalEnsemblingStrategy = LongitudinalEnsemblingStrategy.MAJORITY_VOTING,
+   estimators: List[CustomClassifierMixinEstimator] = None,
+   extract_wave: Callable = None, n_jobs: int = 1
+)
+
+
+

The Longitudinal Voting Classifier is a versatile ensemble method designed to handle the unique challenges posed by +longitudinal data. By leveraging different voting strategies, this classifier combines predictions from multiple base +estimators to enhance predictive performance. The base estimators are individually trained, and their predictions are +aggregated based on the chosen voting strategy to generate the final prediction.

+
+

When to Use?

+

This classifier is primarily used when the "SepWav" (Separate Waves) strategy is employed. However, it can also be +applied with only longitudinal-based estimators and do not follow the SepWav approach if wanted.

+
+
+

SepWav (Separate Waves) Strategy

+

The SepWav strategy involves considering each wave's features and the class variable as a separate dataset, +then learning a classifier for each dataset. The class labels predicted by these classifiers are combined into a +final predicted class label. This combination can be achieved using various approaches: simple majority voting, +weighted voting with weights decaying linearly or exponentially for older waves, weights optimized by cross-validation +on the training set (current class), and stacking methods that use the classifiers' predicted labels as input +for learning a meta-classifier (see LongitudinalStacking).

+
+
+

Wrapper Around Sklearn VotingClassifier

+

This class wraps the sklearn VotingClassifier, offering a familiar interface while incorporating enhancements +for longitudinal data.

+
+

Parameters

+
    +
  • voting (LongitudinalEnsemblingStrategy): The voting strategy to be used for the ensemble. Refer to the LongitudinalEnsemblingStrategy enum below.
  • +
  • estimators (List[CustomClassifierMixinEstimator]): A list of classifiers for the ensemble. Note, the classifiers need to be trained before being passed to the LongitudinalVotingClassifier.
  • +
  • extract_wave (Callable): A function to extract specific wave data for training.
  • +
  • n_jobs (int, optional, default=1): The number of jobs to run in parallel.
  • +
+

Voting Strategies

+
    +
  • Majority Voting: Simple consensus voting where the most frequent prediction is selected.
  • +
  • Decay-Based Weighted Voting: Weights each classifier's vote based on the recency of its wave.
  • +
  • Weight formula: \( w_i = \frac{e^{i}}{\sum_{j=1}^{N} e^{j}} \)
  • +
  • Cross-Validation-Based Weighted Voting: Weights each classifier based on its cross-validation accuracy on the training data.
  • +
  • Weight formula: \( w_i = \frac{A_i}{\sum_{j=1}^{N} A_j} \)
  • +
+

Final Prediction Calculation

+
    +
  • The final ensemble prediction \( P \) is derived from the votes \( \{V_1, V_2, \ldots, V_N\} \) and their corresponding weights.
  • +
  • Formula: \( P = \text{argmax}_{c} \sum_{i=1}^{N} w_i \times I(V_i = c) \)
  • +
+

Tie-Breaking

+
    +
  • In the case of a tie, the most recent wave's prediction is selected as the final prediction. Note that this is only applicable for predict and not predict_proba, given that predict_proba takes the average of votes, similarly as how sklearn's voting classifier does.
  • +
+

Methods

+

Fit

+

source

+
._fit(
+   X: np.ndarray, y: np.ndarray
+)
+
+

Fit the ensemble model.

+

Parameters

+
    +
  • X (np.ndarray): The training data.
  • +
  • y (np.ndarray): The target values.
  • +
+

Returns

+
    +
  • LongitudinalVotingClassifier: The fitted ensemble model.
  • +
+

Raises

+
    +
  • ValueError: If no estimators are provided or if an invalid voting strategy is specified.
  • +
  • NotFittedError: If attempting to predict or predict_proba before fitting the model.
  • +
+

Predict

+

source

+
._predict(
+   X: np.ndarray
+)
+
+

Predict using the ensemble model.

+

Parameters

+
    +
  • X (np.ndarray): The test data.
  • +
+

Returns

+
    +
  • np.ndarray: The predicted values.
  • +
+

Raises

+
    +
  • NotFittedError: If attempting to predict before fitting the model.
  • +
+

Predict Proba

+

source

+
._predict_proba(
+   X: np.ndarray
+)
+
+

Predict probabilities using the ensemble model.

+

Parameters

+
    +
  • X (np.ndarray): The test data.
  • +
+

Returns

+
    +
  • np.ndarray: The predicted probabilities.
  • +
+

Examples

+

Dummy Longitudinal Dataset

+
+

Consider the following dataset

+

Features:

+
    +
  • smoke (longitudinal) with two waves/time-points
  • +
  • cholesterol (longitudinal) with two waves/time-points
  • +
  • age (non-longitudinal)
  • +
  • gender (non-longitudinal)
  • +
+

Target:

+
    +
  • stroke (binary classification) at wave/time-point 2 only for the sake of the example
  • +
+

The dataset is shown below:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
smoke_wave_1smoke_wave_2cholesterol_wave_1cholesterol_wave_2agegenderstroke_wave_2
01014510
11115001
00005510
11116001
01016510
+
+

Example 1: Basic Usage

+
Example 1: Basic Usage
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
from scikit_longitudinal.estimators.ensemble.longitudinal_voting.longitudinal_voting import (
+    LongitudinalVotingClassifier,
+)
+from sklearn_fork.ensemble import RandomForestClassifier
+from scikit_longitudinal.estimators.ensemble.lexicographical import LexicoRandomForestClassifier
+from sklearn.metrics import accuracy_score
+
+features_group = [(0,1), (2,3)]  # (1)
+non_longitudinal_features = [4,5]  # (2)
+
+estimators = [ # (3)
+    RandomForestClassifier().fit(X, y),
+    LexicoRandomForestClassifier(features_group=features_group).fit(X, y), # (4)
+]
+
+clf = LongitudinalVotingClassifier(
+    voting=LongitudinalEnsemblingStrategy.MAJORITY_VOTING,
+    estimators=estimators,
+    n_jobs=1
+)
+
+clf.fit(X, y)
+y_pred = clf.predict(X)
+
+accuracy_score(y, y_pred) # (5)
+
+
    +
  1. Define the features_group manually or use a pre-set from the LongitudinalDataset class.
  2. +
  3. Define the non-longitudinal features or use a pre-set from the LongitudinalDataset class.
  4. +
  5. Define the base estimators for the ensemble. Longitudinal-based or non-longitudinal-based estimators can be used. However, what is important is that the estimators are trained prior to being passed to the LongitudinalVotingClassifier.
  6. +
  7. Lexico Random Forest does not require the non-longitudinal features to be passed. However, if an algorithm does, then it would have been used.
  8. +
  9. Calculate the accuracy score for the predictions.
  10. +
+

Example 2: Using Cross-Validation-Based Weighted Voting

+
Example 2: Using Cross-Validation-Based Weighted Voting
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
from scikit_longitudinal.estimators.ensemble.longitudinal_voting.longitudinal_voting import (
+    LongitudinalVotingClassifier,
+)
+from sklearn_fork.ensemble import RandomForestClassifier
+from scikit_longitudinal.estimators.ensemble.lexicographical import LexicoRandomForestClassifier
+from sklearn.metrics import accuracy_score
+
+features_group = [(0,1), (2,3)]  # (1)
+non_longitudinal_features = [4,5]  # (2)
+
+estimators = [ # (3)
+    RandomForestClassifier().fit(X, y),
+    LexicoRandomForestClassifier(features_group=features_group).fit(X, y), # (4)
+]
+
+clf = LongitudinalVotingClassifier(
+    voting=LongitudinalEnsemblingStrategy.CV_BASED_VOTING,  # (5)
+    estimators=estimators,
+    n_jobs=1
+)
+
+clf.fit(X, y)
+y_pred = clf.predict(X)
+
+accuracy_score(y, y_pred) # (6)
+
+
    +
  1. Define the features_group manually or use a pre-set from the LongitudinalDataset class.
  2. +
  3. Define the non-longitudinal features or use a pre-set from the LongitudinalDataset class.
  4. +
  5. Define the base estimators for the ensemble. Longitudinal-based or non-longitudinal-based estimators can be used. However, what is important is that the estimators are trained prior to being passed to the LongitudinalVotingClassifier.
  6. +
  7. Lexico Random Forest does not require the non-longitudinal features to be passed. However, if an algorithm does, then it would have been used.
  8. +
  9. Use the cross-validation-based weighted voting strategy. See further in the LongitudinalEnsemblingStrategy enum for more information.
  10. +
  11. Calculate the accuracy score for the predictions.
  12. +
+

Notes

+
+

For more information, please refer to the following paper:

+
+

References

+
    +
  • Ribeiro and Freitas (2019):
  • +
  • Ribeiro, C. and Freitas, A.A., 2019. A mini-survey of supervised machine learning approaches for coping with ageing-related longitudinal datasets. In 3rd Workshop on AI for Aging, Rehabilitation and Independent Assisted Living (ARIAL), held as part of IJCAI-2019 (num. of pages: 5).
  • +
+
+

Longitudinal Ensembling Strategy

+

LongitudinalEnsemblingStrategy

+

source

+
LongitudinalEnsemblingStrategy()
+
+
+

An enum for the different longitudinal voting strategies.

+

Attributes

+
    +
  • Voting: Weights are assigned linearly with more recent waves having higher weights.
  • +
  • Weight formula: \( w_i = \frac{i}{\sum_{j=1}^{N} j} \)
  • +
  • Exponential Decay Voting: Weights are assigned exponentially, favoring more recent waves.
  • +
  • Weight formula: \( w_i = \frac{e^{i}}{\sum_{j=1}^{N} e^{j}} \)
  • +
  • MAJORITY_VOTING (int): Simple consensus voting where the most frequent prediction is selected.
  • +
  • DECAY_LINEAR_VOTING (int): Weights each classifier's vote based on the recency of its wave.
  • +
  • CV_BASED_VOTING (int): Weights each classifier based on its cross-validation accuracy on the training data.
  • +
  • Weight formula: \( w_i = \frac{A_i}{\sum_{j=1}^{N} A_j} \)
  • +
  • STACKING (int): Stacking ensemble strategy uses a meta-learner to combine predictions of base classifiers. The meta-learner is trained on meta-features formed from the base classifiers' predictions. This approach is suitable when the cardinality of meta-features is smaller than the original feature set.
  • +
+

In stacking, for each wave \( I \) (\( I \in \{1, 2, \ldots, N\} \)), a base classifier \( C_i \) is trained on \( (X_i, T_N) \). The prediction from \( C_i \) is denoted as \( V_i \), forming the meta-features \( \mathbf{V} = [V_1, V_2, ..., V_N] \). The meta-learner \( M \) is then trained on \( (\mathbf{V}, T_N) \), and for a new instance \( x \), the final prediction is \( P(x) = M(\mathbf{V}(x)) \).

+ + + + + + + + + + + + + + + + +
+
+ + + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/API/estimators/ensemble/nested_trees/index.html b/API/estimators/ensemble/nested_trees/index.html new file mode 100644 index 0000000..de819ef --- /dev/null +++ b/API/estimators/ensemble/nested_trees/index.html @@ -0,0 +1,2174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Nested Trees - Scikit-Longitudinal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Nested Trees Classifier

+

NestedTreesClassifier

+

source

+
NestedTreesClassifier(
+   features_group: List[List[int]] = None,
+   non_longitudinal_features: List[Union[int, str]] = None, max_outer_depth: int = 3,
+   max_inner_depth: int = 2, min_outer_samples: int = 5,
+   inner_estimator_hyperparameters: Optional[Dict[str, Any]] = None,
+   save_nested_trees: bool = False, parallel: bool = False, num_cpus: int = -1
+)
+
+
+

The Nested Trees Classifier is a unique and innovative classification algorithm specifically designed for longitudinal +datasets. This method enhances traditional decision tree algorithms by embedding smaller decision trees within the nodes +of a primary tree structure, leveraging the inherent information in longitudinal data optimally.

+
+

Nested Trees Structure

+

The outer decision tree employs a custom algorithm that selects longitudinal attributes, categorised as groups of +time-specific attributes. The inner embedded decision tree uses Scikit Learn's decision tree algorithm, +partitioning the dataset based on the longitudinal attribute of the parent node.

+
+
+

Wrapper Around Sklearn DecisionTreeClassifier

+

This class wraps the sklearn DecisionTreeClassifier, offering a familiar interface while incorporating +enhancements for longitudinal data. It ensures effective processing and learning from data collected over multiple +time points.

+
+

Parameters

+
    +
  • features_group (List[List[int]]): A temporal matrix representing the temporal dependency of a longitudinal dataset. Each tuple/list of integers in the outer list represents the indices of a longitudinal attribute's waves, with each longitudinal attribute having its own sublist in that outer list. For more details, see the documentation's "Temporal Dependency" page.
  • +
  • non_longitudinal_features (List[Union[int, str]], optional): A list of indices of features that are not longitudinal attributes. Defaults to None.
  • +
  • max_outer_depth (int, optional, default=3): The maximum depth of the outer custom decision tree.
  • +
  • max_inner_depth (int, optional, default=2): The maximum depth of the inner decision trees.
  • +
  • min_outer_samples (int, optional, default=5): The minimum number of samples required to split an internal node in the outer decision tree.
  • +
  • inner_estimator_hyperparameters (Dict[str, Any], optional): A dictionary of hyperparameters to be passed to the inner Scikit-learn decision tree estimators. Defaults to None.
  • +
  • save_nested_trees (bool, optional, default=False): If set to True, the nested trees structure plot will be saved, which may be useful for model interpretation and visualization.
  • +
  • parallel (bool, optional, default=False): Whether to use parallel processing.
  • +
  • num_cpus (int, optional, default=-1): The number of CPUs to use for parallel processing. Defaults to -1 (use all available).
  • +
+

Attributes

+
    +
  • root (Node, optional): The root node of the outer decision tree. Set to None upon initialization, it will be updated during the model fitting process.
  • +
+

Methods

+

Fit

+

source

+
._fit(
+   X: np.ndarray, y: np.ndarray
+)
+
+

Fit the Nested Trees Classifier model according to the given training data.

+

Parameters

+
    +
  • X (np.ndarray): The training input samples.
  • +
  • y (np.ndarray): The target values (class labels).
  • +
+

Returns

+
    +
  • NestedTreesClassifier: The fitted classifier.
  • +
+

Raises

+
    +
  • ValueError: If there are less than or equal to 1 feature group.
  • +
+

Predict

+

source

+
._predict(
+   X: np.ndarray
+)
+
+

Predict class labels for samples in X.

+

Parameters

+
    +
  • X (np.ndarray): The input samples.
  • +
+

Returns

+
    +
  • np.ndarray: The predicted class labels for each input sample.
  • +
+

Predict Proba

+

source

+
._predict_proba(
+   X: np.ndarray
+)
+
+

Predict class probabilities for samples in X.

+

Parameters

+
    +
  • X (np.ndarray): The input samples.
  • +
+

Returns

+
    +
  • np.ndarray: The predicted class probabilities for each input sample.
  • +
+ +

source

+
.print_nested_tree(
+   node: Optional['NestedTreesClassifier.Node'] = None, depth: int = 0, prefix: str = '',
+   parent_name: str = ''
+)
+
+

Print the structure of the nested tree classifier.

+

Parameters

+
    +
  • node (Optional[NestedTreesClassifier.Node], optional): The current node in the outer decision tree. If None, start from the root node. Default is None.
  • +
  • depth (int, optional, default=0): The current depth of the node in the outer decision tree.
  • +
  • prefix (str, optional, default=""`): A string to prepend before the node's name in the output.
  • +
  • parent_name (str, optional, default=""`): The name of the parent node in the outer decision tree.
  • +
+

Examples

+

Dummy Longitudinal Dataset

+
+

Consider the following dataset

+

Features:

+
    +
  • smoke (longitudinal) with two waves/time-points
  • +
  • cholesterol (longitudinal) with two waves/time-points
  • +
  • age (non-longitudinal)
  • +
  • gender (non-longitudinal)
  • +
+

Target:

+
    +
  • stroke (binary classification) at wave/time-point 2 only for the sake of the example
  • +
+

The dataset is shown below:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
smoke_wave_1smoke_wave_2cholesterol_wave_1cholesterol_wave_2agegenderstroke_wave_2
01014510
11115001
00005510
11116001
01016510
+
+

Example 1: Basic Usage

+
Example 1: Basic Usage
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
from scikit_longitudinal.estimators.ensemble import NestedTreesClassifier
+from sklearn_fork.model_selection import train_test_split
+from sklearn_fork.metrics import accuracy_score
+
+features_group = [(0, 1), (2, 3)] # (1)
+non_longitudinal_features = [4, 5] # (2)
+
+clf = NestedTreesClassifier(
+    features_group=features_group,
+    non_longitudinal_features=non_longitudinal_features,
+)
+
+clf.fit(X_train, y_train)
+y_pred = clf.predict(X_test)
+
+accuracy_score(y_test, y_pred) # (3)
+
+
    +
  1. Define the features_group manually or use a pre-set from the LongitudinalDataset class.
  2. +
  3. Define the non-longitudinal features or use a pre-set from the LongitudinalDataset class.
  4. +
  5. Fit the model with the training data, make predictions, and evaluate the model using the accuracy score.
  6. +
+

Example 2: Using Custom Hyperparameters for Inner Estimators

+
Example 2: Using Custom Hyperparameters for Inner Estimators
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
from scikit_longitudinal.estimators.ensemble import NestedTreesClassifier
+from sklearn_fork.model_selection import train_test_split
+from sklearn_fork.metrics import accuracy_score
+
+features_group = [(0, 1), (2, 3)] # (1)
+non_longitudinal_features = [4, 5] # (2)
+
+inner_hyperparameters = { # (3)
+    "criterion": "gini",
+    "splitter": "best",
+    "max_depth": 3
+}
+
+clf = NestedTreesClassifier(
+    features_group=features_group,
+    non_longitudinal_features=non_longitudinal_features,
+    inner_estimator_hyperparameters=inner_hyperparameters,
+)
+
+clf.fit(X_train, y_train)
+y_pred = clf.predict(X_test)
+
+accuracy_score(y_test, y_pred) # (4)
+
+
    +
  1. Define the features_group manually or use a pre-set from the LongitudinalDataset class.
  2. +
  3. Define the non-longitudinal features or use a pre-set from the LongitudinalDataset class.
  4. +
  5. Define custom hyperparameters for the inner decision tree estimators.
  6. +
  7. Fit the model with the training data, make predictions, and evaluate the model using the accuracy score.
  8. +
+

Example 3: Using Parallel Processing

+
Example 3: Using Parallel Processing
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
from scikit_longitudinal.estimators.ensemble import NestedTreesClassifier
+from sklearn_fork.model_selection import train_test_split
+from sklearn_fork.metrics import accuracy_score
+
+features_group = [(0, 1), (2, 3)] # (1)
+non_longitudinal_features = [4, 5] # (2)
+
+clf = NestedTreesClassifier(
+    features_group=features_group,
+    non_longitudinal_features=non_longitudinal_features,
+    parallel=True, # (3)
+    num_cpus=-1 # (4)
+)
+
+clf.fit(X_train, y_train)
+y_pred = clf.predict(X_test)
+
+accuracy_score(y_test, y_pred) # (5)
+
+
    +
  1. Define the features_group manually or use a pre-set from the LongitudinalDataset class.
  2. +
  3. Define the non-longitudinal features or use a pre-set from the LongitudinalDataset class.
  4. +
  5. Enable parallel processing.
  6. +
  7. Specify the number of CPUs to use for parallel processing. That is that each available CPU will be used to train one decision tree of one longitudinal attribute.
  8. +
  9. Fit the model with the training data, make predictions, and evaluate the model using the accuracy score.
  10. +
+

Example 4: Saving the Nested Trees Structure

+
Example 4: Saving the Nested Trees Structure
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
from scikit_longitudinal.estimators.ensemble import NestedTreesClassifier
+from sklearn_fork.model_selection import train_test_split
+from sklearn_fork.metrics import accuracy_score
+
+features_group = [(0, 1), (2, 3)] # (1)
+non_longitudinal_features = [4, 5] # (2)
+
+clf = NestedTreesClassifier(
+    features_group=features_group,
+    non_longitudinal_features=non_longitudinal_features,
+    save_nested_trees=True # (3)
+)
+
+clf.fit(X_train, y_train)
+y_pred = clf.predict(X_test)
+
+accuracy_score(y_test, y_pred) # (4)
+
+
    +
  1. Define the features_group manually or use a pre-set from the LongitudinalDataset class.
  2. +
  3. Define the non-longitudinal features or use a pre-set from the LongitudinalDataset class.
  4. +
  5. Request the nested trees structure plot to be saved.
  6. +
  7. Fit the model with the training data, make predictions, and evaluate the model using the accuracy score.
  8. +
+

Example 5: Printing the Nested Trees Structure (markdown format)

+
Example 5: Printing the Nested Trees Structure
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
from scikit_longitudinal.estimators.ensemble import NestedTreesClassifier
+from sklearn_fork.model_selection import train_test_split
+from sklearn_fork.metrics import accuracy_score
+
+features_group = [(0, 1), (2, 3)] # (1)
+non_longitudinal_features = [4, 5] # (2)
+
+clf = NestedTreesClassifier(
+    features_group=features_group,
+    non_longitudinal_features=non_longitudinal_features,
+)
+
+clf.fit(X_train, y_train)
+clf.print_nested_tree() # (3)
+
+
    +
  1. Define the features_group manually or use a pre-set from the LongitudinalDataset class.
  2. +
  3. Define the non-longitudinal features or use a pre-set from the LongitudinalDataset class.
  4. +
  5. The output will show the structure of the nested tree in markdown format.
  6. +
+

Notes

+
+

For more information, see the following paper on the Nested Trees algorithm:

+
+

References

+
    +
  • Ovchinnik, Otero, and Freitas (2022):
  • +
  • Ovchinnik, S., Otero, F. and Freitas, A.A., 2022, April. Nested trees for longitudinal classification. In Proceedings of the 37th ACM/SIGAPP Symposium on Applied Computing (pp. 441-444). Vancouver.
  • +
+

Here is the initial Java implementation of the Nested Trees algorithm: Nested Trees GitHub

+ + + + + + + + + + + + + + + + +
+
+ + + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/API/estimators/trees/lexico_decision_tree_classifier/index.html b/API/estimators/trees/lexico_decision_tree_classifier/index.html new file mode 100644 index 0000000..8f01dcb --- /dev/null +++ b/API/estimators/trees/lexico_decision_tree_classifier/index.html @@ -0,0 +1,1967 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Lexicographical Decision Tree Classifier - Scikit-Longitudinal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Lexico Decision Tree Classifier

+

LexicoDecisionTreeClassifier

+

source

+
LexicoDecisionTreeClassifier(
+   threshold_gain: float = 0.0015, features_group: List[List[int]] = None,
+   criterion: str = 'entropy', splitter: str = 'lexicoRF',
+   max_depth: Optional[int] = None, min_samples_split: int = 2,
+   min_samples_leaf: int = 1, min_weight_fraction_leaf: float = 0.0,
+   max_features: Optional[Union[int, str]] = None, random_state: Optional[int] = None,
+   max_leaf_nodes: Optional[int] = None, min_impurity_decrease: float = 0.0,
+   class_weight: Optional[str] = None, ccp_alpha: float = 0.0
+)
+
+
+

The Lexico Decision Tree Classifier is an advanced classification model specifically designed for longitudinal data. +This implementation extends the traditional decision tree algorithm by incorporating a lexicographic optimisation approach.

+
+

Lexicographic Optimisation

+

The primary goal of this approach is to prioritise the selection of more recent data points (wave ids) when +determining splits in the decision tree, based on the premise that recent measurements are typically more +predictive and relevant than older ones.

+

Key Features:

+
    +
  1. Lexicographic Optimisation: The approach prioritises features based on both their information gain ratios +and the recency of the data, favoring splits with more recent information.
  2. +
  3. Cython Adaptation: This implementation leverages a fork of Scikit-learn’s fast C++-powered decision +tree to ensure that the Lexico Decision Tree is fast and efficient, avoiding the potential slowdown of a +from-scratch Python implementation. Further details on the algorithm can be found in the Cython adaptation available here at Scikit-Lexicographical-Trees specifically in the node_lexicoRF_split function.
  4. +
+

For further scientific references, please refer to the Notes section.

+
+

Parameters

+
    +
  • features_group (List[List[int]]): A temporal matrix representing the temporal dependency of a longitudinal dataset. Each tuple/list of integers in the outer list represents the indices of a longitudinal attribute's waves, with each longitudinal attribute having its own sublist in that outer list. For more details, see the documentation's "Temporal Dependency" page.
  • +
  • threshold_gain (float): The threshold value for comparing gain ratios of features during the decision tree construction.
  • +
  • criterion (str, optional, default="entropy"): The function to measure the quality of a split. Do not change this value.
  • +
  • splitter (str, optional, default="lexicoRF"): The strategy used to choose the split at each node. Do not change this value.
  • +
  • max_depth (Optional[int], default=None): The maximum depth of the tree.
  • +
  • min_samples_split (int, optional, default=2): The minimum number of samples required to split an internal node.
  • +
  • min_samples_leaf (int, optional, default=1): The minimum number of samples required to be at a leaf node.
  • +
  • min_weight_fraction_leaf (float, optional, default=0.0): The minimum weighted fraction of the sum total of weights required to be at a leaf node.
  • +
  • max_features (Optional[Union[int, str]], default=None): The number of features to consider when looking for the best split.
  • +
  • random_state (Optional[int], default=None): The seed used by the random number generator.
  • +
  • max_leaf_nodes (Optional[int], default=None): The maximum number of leaf nodes in the tree.
  • +
  • min_impurity_decrease (float, optional, default=0.0): The minimum impurity decrease required for a node to be split.
  • +
  • class_weight (Optional[str], default=None): Weights associated with classes in the form of {class_label: weight}.
  • +
  • ccp_alpha (float, optional, default=0.0): Complexity parameter used for Minimal Cost-Complexity Pruning.
  • +
+

Attributes

+
    +
  • classes_ (ndarray of shape (n_classes,)): The classes labels (single output problem).
  • +
  • n_classes_ (int): The number of classes (single output problem).
  • +
  • n_features_ (int): The number of features when fit is performed.
  • +
  • n_outputs_ (int): The number of outputs when fit is performed.
  • +
  • feature_importances_ (ndarray of shape (n_features,)): The impurity-based feature importances.
  • +
  • max_features_ (int): The inferred value of max_features.
  • +
  • tree_ (Tree object): The underlying Tree object.
  • +
+

Methods

+

Fit

+

source

+
.fit(
+   X: np.ndarray, y: np.ndarray, sample_weight: Optional[np.ndarray] = None,
+   check_input: bool = True, X_idx_sorted: Optional[np.ndarray] = None
+)
+
+

Fit the decision tree classifier.

+

This method fits the LexicoDecisionTreeClassifier to the given data.

+

Parameters

+
    +
  • X (np.ndarray): The training input samples of shape (n_samples, n_features).
  • +
  • y (np.ndarray): The target values of shape (n_samples,).
  • +
  • sample_weight (Optional[np.ndarray], default=None): Sample weights.
  • +
  • check_input (bool, default=True): Allow to bypass several input checking. Don’t use this parameter unless you know what you do.
  • +
  • X_idx_sorted (Optional[np.ndarray], default=None): The indices of the sorted training input samples. If many tree are grown on the same dataset, this allows the use of sorted representations in max_features and max_depth searches.
  • +
+

Returns

+
    +
  • LexicoDecisionTreeClassifier: The fitted decision tree classifier.
  • +
+

Predict

+

source

+
.predict(
+   X: np.ndarray
+)
+
+

Predict class or regression value for X.

+

The predicted class or the predict value of an input sample is computed as the mean predicted class of the trees in the forest.

+

Parameters

+
    +
  • X (np.ndarray): The input samples of shape (n_samples, n_features).
  • +
+

Returns

+
    +
  • np.ndarray: The predicted classes.
  • +
+

Predict Proba

+

source

+
.predict_proba(
+   X: np.ndarray
+)
+
+

Predict class probabilities for X.

+

The predicted class probabilities of an input sample are computed as the mean predicted class probabilities of the trees in the forest. The class probability of a single tree is the fraction of samples of the same class in a leaf.

+

Parameters

+
    +
  • X (np.ndarray): The input samples of shape (n_samples, n_features).
  • +
+

Returns

+
    +
  • np.ndarray: The predicted class probabilities.
  • +
+

Examples

+

Dummy Longitudinal Dataset

+
+

Consider the following dataset

+

Features:

+
    +
  • smoke (longitudinal) with two waves/time-points
  • +
  • cholesterol (longitudinal) with two waves/time-points
  • +
  • age (non-longitudinal)
  • +
  • gender (non-longitudinal)
  • +
+

Target:

+
    +
  • stroke (binary classification) at wave/time-point 2 only for the sake of the example
  • +
+

The dataset is shown below:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
smoke_wave_1smoke_wave_2cholesterol_wave_1cholesterol_wave_2agegenderstroke_wave_2
01014510
11115001
00005510
11116001
01016510
+
+

Example 1: Basic Usage

+

Example_1: Default Parameters
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
from sklearn_fork.metrics imp mators.tree import LexicoDecisionTreeClassifier
+
+features_group = [(0,1), (2,3)] # (1)
+
+clf = LexicoDecisionTreeClassifier(
+    features_group=features_group
+)
+clf.fit(X, y)
+y_pred = clf.predict(X)
+
+accuracy_score(y, y_pred) # (2)
+
+1. Either define the features_group manually or use a pre-set from the LongitudinalDataset class. It is unnecessary to include "non-longitudinal" features in this algorithm because they are not used in the lexicographical technique approach but are obviously used in the standard decision tree procedure. +2. Calculate the accuracy score for the predictions. Can use other metrics as well.

+

Example 2: How-To Set Threshold Gain of the Lexicographical Approach?

+
example_1: How-To Set Threshold Gain of the Lexicographical Approach
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
from sklearn_fork.metrics import accuracy_score
+from scikit_longitudinal.estimators.tree import LexicoDecisionTreeClassifier
+
+features_group = [(0,1), (2,3)] # (1)
+
+clf = LexicoDecisionTreeClassifier(
+    threshold_gain=0.001, # (2)
+    features_group=features_group
+)
+
+clf.fit(X, y)
+y_pred = clf.predict(X)
+
+accuracy_score(y, y_pred) # (3)
+
+
    +
  1. Define the features_group manually or use a pre-set from the LongitudinalDataset class. It is unnecessary to include "non-longitudinal" features in this algorithm because they are not used in the lexicographical technique approach but are obviously used in the standard decision tree procedure.
  2. +
  3. Set the threshold gain for the lexicographical approach. The lower the value, the closer will need the gain ratio to be between the two features to be considered equal before employing the lexicographical approach (i.e, the more recent wave will be chosen under certain conditions). The higher the value, the larger the gap needs can be between the gain ratios of the two features for the lexicographical approach to be employed.
  4. +
  5. Calculate the accuracy score for the predictions. Can use other metrics as well.
  6. +
+

Notes

+
+

For more information, please refer to the following paper:

+
+

References

+
    +
  • Ribeiro and Freitas (2020):
  • +
  • Ribeiro, C. and Freitas, A., 2020, December. A new random forest method for longitudinal data classification using a lexicographic bi-objective approach. In 2020 IEEE Symposium Series on Computational Intelligence (SSCI) (pp. 806-813). IEEE.
  • +
  • Ribeiro and Freitas (2024):
  • +
  • Ribeiro, C. and Freitas, A.A., 2024. A lexicographic optimisation approach to promote more recent features on longitudinal decision-tree-based classifiers: applications to the English Longitudinal Study of Ageing. Artificial Intelligence Review, 57(4), p.84.
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/API/estimators/trees/lexico_decision_tree_regressor/index.html b/API/estimators/trees/lexico_decision_tree_regressor/index.html new file mode 100644 index 0000000..3ff7767 --- /dev/null +++ b/API/estimators/trees/lexico_decision_tree_regressor/index.html @@ -0,0 +1,2135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Lexicographical Decision Tree Regressor - Scikit-Longitudinal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Lexico Decision Tree Regressor

+

LexicoDecisionTreeRegressor

+

source

+
LexicoDecisionTreeRegressor(
+   threshold_gain: float = 0.0015, features_group: List[List[int]] = None,
+   criterion: str = 'friedman_mse', splitter: str = 'lexicoRF',
+   max_depth: Optional[int] = None, min_samples_split: int = 2,
+   min_samples_leaf: int = 1, min_weight_fraction_leaf: float = 0.0,
+   max_features: Optional[Union[int, str]] = None, random_state: Optional[int] = None,
+   max_leaf_nodes: Optional[int] = None, min_impurity_decrease: float = 0.0,
+   ccp_alpha: float = 0.0
+)
+
+
+

The Lexico Decision Tree Regressor is an advanced regression model specifically designed for longitudinal data. +This implementation extends the traditional decision tree algorithm by incorporating a lexicographic Optimisation approach.

+
+

Lexicographical Optimisation

+

The primary goal of this approach is to prioritise the selection of more recent data points (wave ids) when +determining splits in the decision tree, based on the premise that recent measurements are typically more +predictive and relevant than older ones.

+

Key Features:

+
    +
  1. Lexicographic Optimisation: The appraoch prioritizes features based on both their information gain ratios and the recency of the data, favoring splits with more recent information.
  2. +
  3. Cython Adaptation: This implementation leverages a fork of Scikit-learn’s fast C++-powered decision tree to ensure that the Lexico Decision Tree is fast and efficient, avoiding the potential slowdown of a from-scratch Python implementation. Further details on the algorithm can be found in the Cython adaptation available at /scikit-longitudinal/scikit-learn/sklearn/tree/_splitter.pyx, specifically in the node_lexicoRF_split function.
  4. +
+

For further scientific references, please refer to the Notes section.

+
+
+

Why's there a regressor?

+

It is worth noting that while Sklong focuses on classification. This regressor is necessary for the Lexico Gradient Boosting. +However, it could be of-use for regression tasks.

+
+

Parameters

+
    +
  • features_group (List[List[int]]): A temporal matrix representing the temporal dependency of a longitudinal dataset. Each tuple/list of integers in the outer list represents the indices of a longitudinal attribute's waves, with each longitudinal attribute having its own sublist in that outer list. For more details, see the documentation's "Temporal Dependency" page.
  • +
  • threshold_gain (float): The threshold value for comparing gain ratios of features during the decision tree construction.
  • +
  • criterion (str, optional, default="friedman_mse"): The function to measure the quality of a split. It is not recommended to change this value.
  • +
  • splitter (str, optional, default="lexicoRF"): The strategy used to choose the split at each node. Do not change this value.
  • +
  • max_depth (Optional[int], default=None): The maximum depth of the tree.
  • +
  • min_samples_split (int, optional, default=2): The minimum number of samples required to split an internal node.
  • +
  • min_samples_leaf (int, optional, default=1): The minimum number of samples required to be at a leaf node.
  • +
  • min_weight_fraction_leaf (float, optional, default=0.0): The minimum weighted fraction of the sum total of weights required to be at a leaf node.
  • +
  • max_features (Optional[Union[int, str]], default=None): The number of features to consider when looking for the best split.
  • +
  • random_state (Optional[int], default=None): The seed used by the random number generator.
  • +
  • max_leaf_nodes (Optional[int], default=None): The maximum number of leaf nodes in the tree.
  • +
  • min_impurity_decrease (float, optional, default=0.0): The minimum impurity decrease required for a node to be split.
  • +
  • ccp_alpha (float, optional, default=0.0): Complexity parameter used for Minimal Cost-Complexity Pruning.
  • +
+

Attributes

+
    +
  • n_features_ (int): The number of features when fit is performed.
  • +
  • n_outputs_ (int): The number of outputs when fit is performed.
  • +
  • feature_importances_ (ndarray of shape (n_features,)): The impurity-based feature importances.
  • +
  • max_features_ (int): The inferred value of max_features.
  • +
  • tree_ (Tree object): The underlying Tree object.
  • +
+

Methods

+

Fit

+

source

+
.fit(
+   X: np.ndarray, y: np.ndarray, sample_weight: Optional[np.ndarray] = None,
+   check_input: bool = True, X_idx_sorted: Optional[np.ndarray] = None
+)
+
+

Fit the decision tree regressor.

+

This method fits the LexicoDecisionTreeRegressor to the given data.

+

Parameters

+
    +
  • X (np.ndarray): The training input samples of shape (n_samples, n_features).
  • +
  • y (np.ndarray): The target values of shape (n_samples,).
  • +
  • sample_weight (Optional[np.ndarray], default=None): Sample weights.
  • +
  • check_input (bool, default=True): Allow to bypass several input checking. Don’t use this parameter unless you know what you do.
  • +
  • X_idx_sorted (Optional[np.ndarray], default=None): The indices of the sorted training input samples. If many tree are grown on the same dataset, this allows the use of sorted representations in max_features and max_depth searches.
  • +
+

Returns

+
    +
  • LexicoDecisionTreeRegressor: The fitted decision tree regressor.
  • +
+

Predict

+

source

+
.predict(
+   X: np.ndarray
+)
+
+

Predict regression value for X.

+

The predicted value of an input sample is computed as the mean predicted value of the trees in the forest.

+

Parameters

+
    +
  • X (np.ndarray): The input samples of shape (n_samples, n_features).
  • +
+

Returns

+
    +
  • np.ndarray: The predicted values.
  • +
+

Predict Proba

+

source

+
.predict_proba(
+   X: np.ndarray
+)
+
+

Predict class probabilities for X.

+

The predicted class probabilities of an input sample are computed as the mean predicted class probabilities of the trees in the forest. The class probability of a single tree is the fraction of samples of the same class in a leaf.

+

Parameters

+
    +
  • X (np.ndarray): The input samples of shape (n_samples, n_features).
  • +
+

Returns

+
    +
  • np.ndarray: The predicted class probabilities.
  • +
+

Here's the documentation for the LexicoDecisionTreeRegressor, including examples and explanation:

+
# Lexico Decision Tree Regressor
+## LexicoDecisionTreeRegressor
+
+[source](https://github.com/simonprovost/scikit-longitudinal/blob/main/scikit_longitudinal/estimators/trees/lexicographical/lexico_decision_tree_regressor.py/#L8)
+
+``` py
+LexicoDecisionTreeRegressor(
+   threshold_gain: float = 0.0015, features_group: List[List[int]] = None,
+   criterion: str = 'friedman_mse', splitter: str = 'lexicoRF',
+   max_depth: Optional[int] = None, min_samples_split: int = 2,
+   min_samples_leaf: int = 1, min_weight_fraction_leaf: float = 0.0,
+   max_features: Optional[Union[int, str]] = None, random_state: Optional[int] = None,
+   max_leaf_nodes: Optional[int] = None, min_impurity_decrease: float = 0.0,
+   ccp_alpha: float = 0.0
+)
+
+
+

The Lexico Decision Tree Regressor is an advanced regression model specifically designed for longitudinal data. This implementation extends the traditional decision tree algorithm by incorporating a lexicographic Optimisation approach.

+
+

Lexicographic Optimisation

+

The primary goal of this approach is to prioritise the selection of more recent data points (wave ids) when determining splits in the decision tree, based on the premise that recent measurements are typically more predictive and relevant than older ones.

+

Key Features:

+
    +
  1. Lexicographic Optimisation: The approach prioritizes features based on both their information gain ratios and the recency of the data, favoring splits with more recent information.
  2. +
  3. Cython Adaptation: This implementation leverages a fork of Scikit-learn’s fast C++-powered decision tree to ensure that the Lexico Decision Tree is fast and efficient, avoiding the potential slowdown of a from-scratch Python implementation. Further details on the algorithm can be found in the Cython adaptation available here at Scikit-Lexicographical-Trees specifically in the node_lexicoRF_split function.
  4. +
+

For further scientific references, please refer to the Notes section.

+
+

Parameters

+
    +
  • threshold_gain (float, default=0.0015): The threshold value for comparing gain ratios of features during the decision tree construction.
  • +
  • features_group (List[List[int]]): A temporal matrix representing the temporal dependency of a longitudinal dataset. Each tuple/list of integers in the outer list represents the indices of a longitudinal attribute's waves, with each longitudinal attribute having its own sublist in that outer list. For more details, see the documentation's "Temporal Dependency" page.
  • +
  • criterion (str, default='friedman_mse'): The function to measure the quality of a split.
  • +
  • splitter (str, default='lexicoRF'): The strategy used to choose the split at each node.
  • +
  • max_depth (Optional[int], default=None): The maximum depth of the tree.
  • +
  • min_samples_split (int, default=2): The minimum number of samples required to split an internal node.
  • +
  • min_samples_leaf (int, default=1): The minimum number of samples required to be at a leaf node.
  • +
  • min_weight_fraction_leaf (float, default=0.0): The minimum weighted fraction of the sum total of weights required to be at a leaf node.
  • +
  • max_features (Optional[Union[int, str]], default=None): The number of features to consider when looking for the best split.
  • +
  • random_state (Optional[int], default=None): The seed used by the random number generator.
  • +
  • max_leaf_nodes (Optional[int], default=None): The maximum number of leaf nodes in the tree.
  • +
  • min_impurity_decrease (float, default=0.0): The minimum impurity decrease required for a node to be split.
  • +
  • ccp_alpha (float, default=0.0): Complexity parameter used for Minimal Cost-Complexity Pruning.
  • +
+

Methods

+

Fit

+

source

+
._fit(
+   X: np.ndarray, y: np.ndarray
+)
+
+

Fits the Lexico Decision Tree Regressor on the input data and target variable.

+

Parameters

+
    +
  • X (np.ndarray): The input data of shape (n_samples, n_features).
  • +
  • y (np.ndarray): The target variable of shape (n_samples).
  • +
+

Returns

+
    +
  • LexicoDecisionTreeRegressor: The fitted instance of the Lexico Decision Tree Regressor.
  • +
+

Predict

+

source

+
._predict(
+   X: np.ndarray
+)
+
+

Predicts the target data for the given input data.

+

Parameters

+
    +
  • X (np.ndarray): The input data.
  • +
+

Returns

+
    +
  • np.ndarray: The predicted target data.
  • +
+

Examples

+

Dummy Longitudinal Dataset

+
+

Consider the following dataset

+

Features:

+
    +
  • smoke (longitudinal) with two waves/time-points
  • +
  • cholesterol (longitudinal) with two waves/time-points
  • +
  • age (non-longitudinal)
  • +
  • gender (non-longitudinal)
  • +
+

Target:

+
    +
  • blood_pressure (continuous variable) at wave/time-point 2 only for the sake of the example
  • +
+

The dataset is shown below:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
smoke_wave_1smoke_wave_2cholesterol_wave_1cholesterol_wave_2agegenderblood_pressure_wave_2
0101451120
1111500130
0000551110
1111600140
0101651125
+
+

Example 1: Basic Usage

+

Example_1: Default Parameters
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
from sklearn_fork.metrics import mean_squared_error
+from scikit_longitudinal.estimators.tree import LexicoDecisionTreeRegressor
+
+features_group = [(0, 1), (2, 3)]  # (1)
+
+clf = LexicoDecisionTreeRegressor(
+    features_group=features_group
+)
+clf.fit(X, y)
+y_pred = clf.predict(X)
+
+mean_squared_error(y, y_pred)  # (2)
+
+1. Either define the features_group manually or use a pre-set from the LongitudinalDataset class. It is unnecessary to include "non-longitudinal" features in this algorithm because they are not used in the lexicographical technique approach but are obviously used in the standard decision tree procedure. +2. Calculate the mean squared error for the predictions. Can use other metrics as well.

+

Example 2: How-To Set Threshold Gain of the Lexicographical Approach?

+
Example_2: How-To Set Threshold Gain of the Lexicographical Approach
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
from sklearn_fork.metrics import mean_squared_error
+from scikit_longitudinal.estimators.tree import LexicoDecisionTreeRegressor
+
+features_group = [(0, 1), (2, 3)]  # (1)
+
+clf = LexicoDecisionTreeRegressor(
+    threshold_gain=0.001,  # (2)
+    features_group=features_group
+)
+
+clf.fit(X, y)
+y_pred = clf.predict(X)
+
+mean_squared_error(y, y_pred)  # (3)
+
+
    +
  1. Define the features_group manually or use a pre-set from the LongitudinalDataset class. It is unnecessary to include "non-longitudinal" features in this algorithm because they are not used in the lexicographical technique approach but are obviously used in the standard decision tree procedure.
  2. +
  3. Set the threshold gain for the lexicographical approach. The lower the value, the closer will need the gain ratio to be between the two features to be considered equal before employing the lexicographical approach (i.e., the more recent wave will be chosen under certain conditions). The higher the value, the larger the gap needs can be between the gain ratios of the two features for the lexicographical approach to be employed.
  4. +
  5. Calculate the mean squared error for the predictions. Can use other metrics as well.
  6. +
+

Notes

+
+

The Lexico Decision Tree Regressor leverages advanced techniques in decision tree Optimisation to handle longitudinal data effectively. For further reading, please refer to the following references:

+
+

References

+
    +
  • Ribeiro and Freitas (2020):
  • +
  • Ribeiro, C. and Freitas, A., 2020, December. A new random forest method for longitudinal data classification using a lexicographic bi-objective approach. In 2020 IEEE Symposium Series on Computational Intelligence (SSCI) (pp. 806-813). IEEE.
  • +
  • Ribeiro and Freitas (2024):
  • +
  • Ribeiro, C. and Freitas, A.A., 2024. A lexicographic optimisation approach to promote more recent features on longitudinal decision-tree-based classifiers: applications to the English Longitudinal Study of Ageing. Artificial Intelligence Review, 57(4), p.84.
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/API/index.html b/API/index.html new file mode 100644 index 0000000..1cd2708 --- /dev/null +++ b/API/index.html @@ -0,0 +1,1606 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Overview - Scikit-Longitudinal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + + + + + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/API/pipeline/index.html b/API/pipeline/index.html new file mode 100644 index 0000000..0916cbf --- /dev/null +++ b/API/pipeline/index.html @@ -0,0 +1,1939 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Longitudinal Pipeline - Scikit-Longitudinal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Longitudinal Pipeline

+

Longitudinal Pipeline

+

source

+
LongitudinalPipeline(
+   steps: List[Tuple[str, Any]], features_group: List[List[int]],
+   non_longitudinal_features: List[Union[int, str]] = None,
+   update_feature_groups_callback: Union[Callable, str] = None,
+   feature_list_names: List[str] = None
+)
+
+

Custom pipeline for handling and processing longitudinal techniques (preprocessors, classifier, etc.). This class extends scikit-learn's Pipeline to offer specialized methods and attributes for working with longitudinal data. It ensures that the longitudinal features and their structure are updated throughout the pipeline's transformations.

+

Parameters

+
    +
  • steps (List[Tuple[str, Any]]): List of (name, transform) tuples (implementing fit/transform) that are chained, in the order in which they are chained, with the last object being an estimator.
  • +
  • features_group (List[List[int]]): A temporal matrix representing the temporal dependency of a longitudinal dataset. Each tuple/list of integers in the outer list represents the indices of a longitudinal attribute's waves, with each longitudinal attribute having its own sublist in that outer list. For more details, see the documentation's "Temporal Dependency" page.
  • +
  • non_longitudinal_features (List[Union[int, str]], optional): A list of indices of features that are not longitudinal attributes. Defaults to None.
  • +
  • update_feature_groups_callback (Union[Callable, str], optional): Callback function to update feature groups. This function is invoked to update the structure of longitudinal features during pipeline transformations.
  • +
  • feature_list_names (List[str], optional): List of names corresponding to the features.
  • +
+

Attributes

+
    +
  • _longitudinal_data (np.ndarray): Longitudinal data being processed.
  • +
  • selected_feature_indices_ (np.ndarray): Indices of the selected features.
  • +
  • final_estimator (Any): Final step in the pipeline.
  • +
+
+

Note:
+While this class maintains the interface of scikit-learn's Pipeline, it includes specific methods and validations to ensure the correct processing of longitudinal data.

+
+

Methods

+

Fit

+

source

+
.fit(
+   X: np.ndarray, y: Optional[Union[pd.Series, np.ndarray]] = None,
+   **fit_params: Dict[str, Any]
+)
+
+

Fit the transformers in the pipeline and then the final estimator. For each step, the transformers are configured and fitted. The data is transformed and updated for each step, ensuring that the longitudinal feature structure is maintained.

+

Parameters

+
    +
  • X (np.ndarray): The input data.
  • +
  • y (Optional[Union[pd.Series, np.ndarray]]): The target variable.
  • +
  • fit_params (Dict[str, Any]): Additional fitting parameters.
  • +
+

Returns

+
    +
  • LongitudinalPipeline: The fitted pipeline.
  • +
+

Predict

+

source

+
.predict(
+   X: np.ndarray, **predict_params: Dict[str, Any]
+)
+
+

Predict the target values using the final estimator of the pipeline.

+

Parameters

+
    +
  • X (np.ndarray): The input data.
  • +
  • predict_params (Dict[str, Any]): Additional prediction parameters.
  • +
+

Returns

+
    +
  • np.ndarray: Predicted values.
  • +
+

Raises

+
    +
  • NotImplementedError: If the final estimator does not have a predict method.
  • +
+

Predict_proba

+

source

+
.predict_proba(
+   X: np.ndarray, **predict_params: Dict[str, Any]
+)
+
+

Predict the probability of the target values using the final estimator of the pipeline.

+

Parameters

+
    +
  • X (np.ndarray): The input data.
  • +
  • predict_params (Dict[str, Any]): Additional prediction parameters.
  • +
+

Returns

+
    +
  • np.ndarray: Predicted probabilities.
  • +
+

Raises

+
    +
  • NotImplementedError: If the final estimator does not have a predict_proba method.
  • +
+

Transform

+

source

+
.transform(
+   X: np.ndarray, **transform_params: Dict[str, Any]
+)
+
+

Transform the input data using the final estimator of the pipeline.

+

Parameters

+
    +
  • X (np.ndarray): The input data.
  • +
  • transform_params (Dict[str, Any]): Additional transformation parameters.
  • +
+

Returns

+
    +
  • np.ndarray: Transformed data.
  • +
+

Detailed Explanation of update_feature_groups_callback

+

The update_feature_groups_callback is a crucial component in the LongitudinalPipeline. This callback function is responsible for updating the structure of longitudinal features during each step of the pipeline. Here’s a detailed breakdown of how it works:

+

Purpose

+

The update_feature_groups_callback ensures that the structure of longitudinal features is accurately maintained and updated as data flows through the pipeline's transformers. This is essential because longitudinal data often requires specific handling to preserve its temporal or grouped characteristics.

+

Default Implementation

+

By default, the LongitudinalPipeline includes a built-in callback function that automatically manages the update of longitudinal features for the current transformers/estimators of the library. This default implementation ensures that users can utilise the pipeline without needing to provide a custom callback for the current available techniques, simplifying the initial setup.

+

Custom Implementation

+

For more advanced use cases, users can provide their custom callback function. E.g because you have a new data pre-processing technique that changes the temporal structure of the dataset. This custom function can be passed as a lambda or a regular function. The custom callback allows users to implement specific logic tailored to their unique longitudinal data processing needs.

+

Function Signature

+
def update_feature_groups_callback(
+    step_idx: int,
+    longitudinal_dataset: LongitudinalDataset,
+    y: Optional[Union[pd.Series, np.ndarray]],
+    name: str,
+    transformer: TransformerMixin
+) -> Tuple[np.ndarray, List[List[int]], List[Union[int, str]], List[str]]:
+    ...
+
+

Parameters

+
    +
  • step_idx (int): The index of the current step in the pipeline.
  • +
  • longitudinal_dataset (LongitudinalDataset): A custom dataset object that includes the longitudinal data and feature groups.
  • +
  • y (Optional[Union[pd.Series, np.ndarray]]): The target variable.
  • +
  • name (str): The name of the current transformer.
  • +
  • transformer (TransformerMixin): The current transformer being applied in the pipeline.
  • +
+

Returns

+
    +
  • updated_longitudinal_data (np.ndarray): The updated longitudinal data.
  • +
  • updated_features_group (List[List[int]]): The updated grouping of longitudinal features.
  • +
  • updated_non_longitudinal_features (List[Union[int, str]]): The updated list of non-longitudinal features.
  • +
  • updated_feature_list_names (List[str]): The updated list of feature names.
  • +
+

How It Works

+
    +
  1. +

    Initialise Dataset: The function starts by initialising a LongitudinalDataset object using the current state of the longitudinal data and feature groups.

    +
  2. +
  3. +

    Update Features: The callback function is invoked with the current step index, the LongitudinalDataset object, the target variable, the name of the transformer, and the transformer itself.

    +
  4. +
  5. +

    Return Updated Data: The callback function returns the updated longitudinal data, features group, non-longitudinal features, and feature list names, which are then used in subsequent steps of the pipeline.

    +
  6. +
+

Flexibility with Lambda Functions

+

Users can pass a lambda function as the update_feature_groups_callback to quickly define custom update logic. For example:

+
pipeline = LongitudinalPipeline(
+    steps=[...],
+    features_group=[...],
+    update_feature_groups_callback=lambda step_idx, dataset, y, name, transformer: (
+        custom_update_function(step_idx, dataset, y, name, transformer)
+    )
+)
+
+

This allows for easy customisation and experimentation with different feature group update strategies. In the meantime, +for further details on the LongitudinalPipeline class, refer to the source code, or open a Github issue.

+ + + + + + + + + + + + + + + + +
+
+ + + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/API/preprocessors/feature_selection/correlation_feature_selection_per_group/index.html b/API/preprocessors/feature_selection/correlation_feature_selection_per_group/index.html new file mode 100644 index 0000000..d31af18 --- /dev/null +++ b/API/preprocessors/feature_selection/correlation_feature_selection_per_group/index.html @@ -0,0 +1,2069 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Correlation Feature Selection Per Group - Scikit-Longitudinal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Correlation Based Feature Selection Per Group (CFS Per Group)

+

Correlation Based Feature Selection Per Group (CFS Per Group)

+

source

+
CorrelationBasedFeatureSelectionPerGroup(
+   non_longitudinal_features: Optional[List[int]] = None,
+   search_method: str = 'greedySearch',
+   features_group: Optional[List[List[int]]] = None, parallel: bool = False,
+   outer_search_method: str = None, inner_search_method: str = 'exhaustiveSearch',
+   version = 1, num_cpus: int = -1
+)
+
+

Correlation-based Feature Selection (CFS) per group (CFS Per Group).

+

This class performs feature selection using the CFS-Per-Group algorithm on given data. The CFS algorithm is, in-a-nutshell, +a filter method that selects features based on their correlation with the target variable and their mutual correlation +with each other. CFS-Per-Group, on the other hand, is an implementation that is adapted from the original CFS, +tailored to understand the Longitudinal temporality.

+
+

CFS-Per-Group a Longitudinal Variation of the Standard CFS Method

+

CFS-Per-Group, also known as Exh-CFS-Gr in the literature, is a longitudinal variation of the standard CFS method. +It is designed to handle longitudinal data by considering temporal variations across multiple waves (time points). +The method works in two phases:

+
    +
  1. Phase 1 (Can work independently from Phase 2): For each longitudinal feature, CFS with exhaustive search (or any other search method available) + is applied to a small set of temporal variations across waves to select a subset of relevant and non-redundant features. + The selected temporal variations of features are then merged into a single feature set.
  2. +
  3. Phase 2 (Works with Phase 1): The feature set from Phase 1 is combined with non-longitudinal features (for a less-biased process) + and standard CFS is applied to further remove redundant features.
  4. +
+

For more scientific references, refer to the Notes section.

+
+
+

Standard CFS Algorithm implementation available

+

If you would like to use the standard CFS algorithm, please refer to the CorrelationBasedFeatureSelection class. +Given that this is out of the scope of this documentation, we recommend checking the source code for more information.

+
+

Parameters

+
    +
  • features_group (Optional[List[Tuple[int, ...]]], default=None): A temporal matrix representing the temporal dependency of a longitudinal dataset. Each tuple/list of integers in the outer list represents the indices of a longitudinal attribute's waves, with each longitudinal attribute having its own sublist in that outer list. For more details, see the documentation's "Temporal Dependency" page.
  • +
  • non_longitudinal_features (Optional[List[int]]): A list of feature indices that are considered non-longitudinal. In version-2, these features will be employed in the second phase of the CFS per group algorithm.
  • +
  • search_method (str, default="greedySearch"): The search method to use (Phase-1). Options are "exhaustiveSearch" and "greedySearch".
  • +
  • version (int, default=2): The version of the CFS per group algorithm to use. Options are "1" and "2". Version 2 is the improved version with an outer search out of the final aggregated list of features of the first phase.
  • +
  • outer_search_method (str, default=None): The outer (to the final aggregated list of features) search method to use for the CFS per group (longitudinal component). If None, it defaults to the same as the search_method.
  • +
  • inner_search_method (str, default="exhaustiveSearch"): The inner (to each longitudinal attributes' waves') search method to use for the CFS per group (longitudinal component).
  • +
  • parallel (bool, default=False): Whether to use parallel processing for the CFS algorithm (especially useful for the exhaustive search method with the CFS per group, i.e., longitudinal component).
  • +
  • num_cpus (int, default=-1): The number of CPUs to use for parallel processing. If -1, all available CPUs will be used.
  • +
+

Attributes

+
    +
  • selected_features_ (ndarray of shape (n_features,)): The indices of the selected features.
  • +
+

Methods

+

Fit

+

source

+
._fit(
+   X: np.ndarray, y: np.ndarray
+)
+
+

Fits the CFS algorithm on the input data and target variable.

+

Parameters

+
    +
  • X (np.ndarray): The input data of shape (n_samples, n_features).
  • +
  • y (np.ndarray): The target variable of shape (n_samples).
  • +
+

Returns

+
    +
  • CorrelationBasedFeatureSelectionPerGroup: The fitted instance of the CFS algorithm.
  • +
+

Transform

+

source

+
._transform(
+   X: np.ndarray
+)
+
+

Reduces the input data to only the selected features.

+
+

Warning

+

Not to be used directly. Use the apply_selected_features_and_rename method instead.

+
+

Parameters

+
    +
  • X (np.ndarray): A numpy array of shape (n_samples, n_features) representing the input data.
  • +
+

Returns

+
    +
  • np.ndarray: The reduced input data as a numpy array of shape (n_samples, n_selected_features).
  • +
+

Apply selected features and rename

+

source

+
.apply_selected_features_and_rename(
+   df: pd.DataFrame, selected_features: List, regex_match = '^(.+)_w(\\d+)$'
+)
+
+

Apply selected features to the input DataFrame and rename non-longitudinal features. This function applies the +selected features using the selected_features_ attribute given. Therefore, you can capture by your_model.selected_features_. +It also renames the non-longitudinal features that may have become non-longitudinal if only one wave remains after the +feature selection process, to avoid them being considered as longitudinal attributes during future automatic feature +grouping.

+
+

Note

+

To avoid adding a "transform" parameter to the Transformer Mixin class, this function was created instead. +To avoid misunderstanding, given that changes to Longitudinal data features (longitudinal and non-longitudinal) are needed, +we created this new function replacing Transform. Rest assured, the LongitudinalPipeline interprets +this workaround by default without the need for anything from the user perspective.

+
+

Parameters

+
    +
  • df (pd.DataFrame): The input DataFrame to apply the selected features and perform renaming.
  • +
  • selected_features (List): The list of selected features to apply to the input DataFrame.
  • +
  • regex_match (str): The regex pattern to use for renaming non-longitudinal features. Follows by default the Elsa naming convention for longitudinal features. For more information, see the source code or open an issue.
  • +
+

Returns

+
    +
  • pd.DataFrame: The modified DataFrame with selected features applied and non-longitudinal features renamed.
  • +
+

Examples

+

Dummy Longitudinal Dataset

+
+

Consider the following dataset

+

Features:

+
    +
  • smoke (longitudinal) with two waves/time-points
  • +
  • cholesterol (longitudinal) with two waves/time-points
  • +
  • age (non-longitudinal)
  • +
  • gender (non-longitudinal)
  • +
+

Target:

+
    +
  • stroke (binary classification) at wave/time-point 2 only for the sake of the example
  • +
+

The dataset is shown below:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
smoke_wave_1smoke_wave_2cholesterol_wave_1cholesterol_wave_2agegenderstroke_wave_2
01014510
11115001
00005510
11116001
01016510
+
+

Example 1: Basic Usage

+
Example_1: Default Parameters
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
from scikit_longitudinal.preprocessors.feature_selection.correlation_feature_selection import CorrelationBasedFeatureSelectionPerGroup
+
+features_group = [(0,1), (2,3)]
+non_longitudinal_features = [4,5]
+
+cfs_longitudinal = CorrelationBasedFeatureSelectionPerGroup(
+    features_group=features_group # (1)
+    non_longitudinal_features=non_longitudinal_features # (2)
+)
+cfs_longitudinal.fit(X, y)
+
+
    +
  1. Either define the features_group manually or use a pre-set from the LongitudinalDataset class.
  2. +
  3. Either define the non-longitudinal features manually or use a pre-set from the LongitudinalDataset class.
  4. +
+

Example 2: Play with the Hyperparameters

+
Example_2: Custom Parameters: different search methods etc.
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
from scikit_longitudinal.preprocessors.feature_selection.correlation_feature_selection import CorrelationBasedFeatureSelectionPerGroup
+
+features_group = [(0,1), (2,3)]
+non_longitudinal_features = [4,5]
+
+cfs_longitudinal = CorrelationBasedFeatureSelectionPerGroup(
+    features_group=features_group # (1)
+    non_longitudinal_features=non_longitudinal_features, # (2)
+    search_method="greedySearch", # (3)
+    parallel=True, # (4)
+    num_cpus=4, # (5)
+)
+cfs_longitudinal.fit(X, y)
+
+
    +
  1. Either define the features_group manually or use a pre-set from the LongitudinalDataset class.
  2. +
  3. Either define the non-longitudinal features manually or use a pre-set from the LongitudinalDataset class.
  4. +
  5. Choose among the search methods: "greedySearch" or "exhaustiveSearch" (default).
  6. +
  7. Enable parallel processing or not.
  8. +
  9. Set the number of CPUs to use for parallel processing. Here we use 4 CPUs. This means that the CFS algorithm will use 4 CPUs for parallel processing. Or in another word, that each CFS running on each set of longitudinal attributes waves will have as much as dedicated CPUs available. If not enough CPUs, the algorithm will wait for the next available CPU to start the next CFS.
  10. +
+

Example 3: Play with the two different versions of the CFS Per Group

+
Example_3: Custom Parameters: different versions of the CFS Per Group
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
from scikit_longitudinal.preprocessors.feature_selection.correlation_feature_selection import CorrelationBasedFeatureSelectionPerGroup
+
+features_group = [(0,1), (2,3)]
+non_longitudinal_features = [4,5]
+
+cfs_longitudinal = CorrelationBasedFeatureSelectionPerGroup(
+    features_group=features_group # (1)
+    non_longitudinal_features=non_longitudinal_features, # (2)
+    version=2, # (3)
+)
+
+cfs_longitudinal.fit(X, y)
+
+
    +
  1. Either define the features_group manually or use a pre-set from the LongitudinalDataset class.
  2. +
  3. Either define the non-longitudinal features manually or use a pre-set from the LongitudinalDataset class.
  4. +
  5. Choose among the two versions of the CFS Per Group: "1" or "2" (default). See beginning of the documentation for more information on the versions.
  6. +
+

Example 4: How to transform (acquire the final feature sets) the data

+
Example_4: Transform the data
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
from scikit_longitudinal.preprocessors.feature_selection.correlation_feature_selection import CorrelationBasedFeatureSelectionPerGroup
+
+features_group = [(0,1), (2,3)]
+non_longitudinal_features = [4,5]
+
+cfs_longitudinal = CorrelationBasedFeatureSelectionPerGroup(
+    features_group=features_group # (1)
+    non_longitudinal_features=non_longitudinal_features # (2)
+)
+
+cfs_longitudinal.fit(X, y)
+print(f"Number of selected features: {len(cfs_longitudinal.selected_features_)}") # (3)
+X_reduced = cfs_longitudinal.apply_selected_features_and_rename(X, cfs_longitudinal.selected_features_)
+print(f"Reduced X: {X_reduced}")
+print(f"Selected features: {cfs_longitudinal.selected_features_}")
+
+
    +
  1. Either define the features_group manually or use a pre-set from the LongitudinalDataset class.
  2. +
  3. Either define the non-longitudinal features manually or use a pre-set from the LongitudinalDataset class.
  4. +
  5. Print the number of selected features after fitting the CFS-Per-Group algorithm.
  6. +
+

Notes

+
+

The improved Correlation-Based Feature Selection (CFS) algorithm is built upon the following key references:

+
+

GitHub Repositories

+
    +
  • Zixiao Shen's CFS Implementation:
  • +
  • Zixiao. S. (2019, August 11). GitHub - ZixiaoShen/Correlation-based-Feature-Selection. Available at: GitHub
  • +
  • Mastervii's CFS 2-Phase Variant:
  • +
  • Pomsuwan, T. (2023, February 24). GitHub - mastervii/CSF_2-phase-variant. Available at: GitHub
  • +
+

Longitudinal Component References

+
    +
  • VERSION-1 of the CFS Per Group:
  • +
  • Pomsuwan, T. and Freitas, A.A. (2017, November). Feature selection for the classification of longitudinal human ageing data. In 2017 IEEE International Conference on Data Mining Workshops (ICDMW) (pp. 739-746). IEEE.
  • +
  • VERSION-2 of the CFS Per Group:
  • +
  • Pomsuwan, T. and Freitas, A.A. (2018, February). Feature selection for the classification of longitudinal human ageing data. Master's thesis, University of Kent. Available at: University of Kent
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/animations/ScikitLongLogo.json b/assets/animations/ScikitLongLogo.json new file mode 100644 index 0000000..8776a48 --- /dev/null +++ b/assets/animations/ScikitLongLogo.json @@ -0,0 +1 @@ +{"v":"4.8.0","meta":{"g":"LottieFiles AE 3.5.4","a":"","k":"","d":"","tc":""},"fr":25,"ip":0,"op":100,"w":6500,"h":1957,"nm":"Example","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":2,"ty":3,"nm":"Controller","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"Gilbert Controller","np":17,"mn":"Pseudo/0vbarur0o9","ix":1,"en":1,"ef":[{"ty":6,"nm":"Animation","mn":"Pseudo/0vbarur0o9-0001","ix":1,"v":0},{"ty":0,"nm":"Start","mn":"Pseudo/0vbarur0o9-0002","ix":2,"v":{"a":1,"k":[{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[100]}],"ix":2}},{"ty":0,"nm":"End","mn":"Pseudo/0vbarur0o9-0003","ix":3,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[0]},{"t":20,"s":[100]}],"ix":3}},{"ty":0,"nm":"Offset","mn":"Pseudo/0vbarur0o9-0004","ix":4,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[-50]},{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[50]}],"ix":4}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0005","ix":5,"v":0},{"ty":6,"nm":"Color","mn":"Pseudo/0vbarur0o9-0006","ix":6,"v":0},{"ty":2,"nm":"Color 1","mn":"Pseudo/0vbarur0o9-0007","ix":7,"v":{"a":0,"k":[1,0.262745098039,0.219607843137,1],"ix":7}},{"ty":2,"nm":"Color 2","mn":"Pseudo/0vbarur0o9-0008","ix":8,"v":{"a":0,"k":[1,0.419607843137,0,1],"ix":8}},{"ty":2,"nm":"Color 3","mn":"Pseudo/0vbarur0o9-0009","ix":9,"v":{"a":0,"k":[1,0.78431372549,0.262745098039,1],"ix":9}},{"ty":2,"nm":"Color 4","mn":"Pseudo/0vbarur0o9-0010","ix":10,"v":{"a":0,"k":[0.019607843137,0.807843137255,0.486274509804,1],"ix":10}},{"ty":2,"nm":"Color 5","mn":"Pseudo/0vbarur0o9-0011","ix":11,"v":{"a":0,"k":[0,0.701960784314,0.890196078431,1],"ix":11}},{"ty":2,"nm":"Color 6","mn":"Pseudo/0vbarur0o9-0012","ix":12,"v":{"a":0,"k":[0.854901960784,0.227450980392,0.701960784314,1],"ix":12}},{"ty":7,"nm":"On white background","mn":"Pseudo/0vbarur0o9-0013","ix":13,"v":{"a":0,"k":1,"ix":13}},{"ty":7,"nm":"Use only Color 1","mn":"Pseudo/0vbarur0o9-0014","ix":14,"v":{"a":0,"k":0,"ix":14}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0015","ix":15,"v":0}]}],"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"S 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[501,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[61.1,0],[2.039,-46.182],[-52.471,-17.999],[2.119,-48.006],[47.271,0],[6.246,16.472],[0,12.356],[0,0]],"o":[[0,0],[0,-12.417],[-6.246,-16.472],[-47.27,0],[-2.12,48.007],[52.472,17.999],[-2.04,46.183],[-61.1,0],[0,0],[0,0],[0,0]],"v":[[93.258,263.568],[93.258,-95.692],[88.509,-119.109],[0.047,-174.453],[-88.379,-95.692],[0.022,-0.016],[88.425,95.661],[-0.001,174.422],[-88.464,119.078],[-93.258,95.661],[-93.258,-263.568]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0.137254908681,0.737254917622,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[500,491.359],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":4,"ty":4,"nm":"S BG","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[501,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[61.1,0],[2.039,-46.182],[-52.471,-17.999],[2.119,-48.006],[47.271,0],[6.246,16.472],[0,12.356],[0,0]],"o":[[0,0],[0,-12.417],[-6.246,-16.472],[-47.27,0],[-2.12,48.007],[52.472,17.999],[-2.04,46.183],[-61.1,0],[0,0],[0,0],[0,0]],"v":[[93.258,263.568],[93.258,-95.692],[88.509,-119.109],[0.047,-174.453],[-88.379,-95.692],[0.022,-0.016],[88.425,95.661],[-0.001,174.422],[-88.464,119.078],[-93.258,95.661],[-93.258,-263.568]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[500,491.359],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = FM_controllerLayer.effect('Gilbert Controller')('Color 1');\n } else {\n $bm_rt = value;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 100;\n } else {\n $bm_rt = $bm_mul(FM_controllerLayer.effect('Gilbert Controller')('On white background'), 100);\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":750,"st":0,"bm":0}]},{"id":"comp_1","layers":[{"ddd":0,"ind":2,"ty":3,"nm":"Controller","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"Gilbert Controller","np":17,"mn":"Pseudo/0vbarur0o9","ix":1,"en":1,"ef":[{"ty":6,"nm":"Animation","mn":"Pseudo/0vbarur0o9-0001","ix":1,"v":0},{"ty":0,"nm":"Start","mn":"Pseudo/0vbarur0o9-0002","ix":2,"v":{"a":1,"k":[{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[100]}],"ix":2}},{"ty":0,"nm":"End","mn":"Pseudo/0vbarur0o9-0003","ix":3,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[0]},{"t":20,"s":[100]}],"ix":3}},{"ty":0,"nm":"Offset","mn":"Pseudo/0vbarur0o9-0004","ix":4,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[-50]},{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[50]}],"ix":4}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0005","ix":5,"v":0},{"ty":6,"nm":"Color","mn":"Pseudo/0vbarur0o9-0006","ix":6,"v":0},{"ty":2,"nm":"Color 1","mn":"Pseudo/0vbarur0o9-0007","ix":7,"v":{"a":0,"k":[1,0.262745098039,0.219607843137,1],"ix":7}},{"ty":2,"nm":"Color 2","mn":"Pseudo/0vbarur0o9-0008","ix":8,"v":{"a":0,"k":[1,0.419607843137,0,1],"ix":8}},{"ty":2,"nm":"Color 3","mn":"Pseudo/0vbarur0o9-0009","ix":9,"v":{"a":0,"k":[1,0.78431372549,0.262745098039,1],"ix":9}},{"ty":2,"nm":"Color 4","mn":"Pseudo/0vbarur0o9-0010","ix":10,"v":{"a":0,"k":[0.019607843137,0.807843137255,0.486274509804,1],"ix":10}},{"ty":2,"nm":"Color 5","mn":"Pseudo/0vbarur0o9-0011","ix":11,"v":{"a":0,"k":[0,0.701960784314,0.890196078431,1],"ix":11}},{"ty":2,"nm":"Color 6","mn":"Pseudo/0vbarur0o9-0012","ix":12,"v":{"a":0,"k":[0.854901960784,0.227450980392,0.701960784314,1],"ix":12}},{"ty":7,"nm":"On white background","mn":"Pseudo/0vbarur0o9-0013","ix":13,"v":{"a":0,"k":1,"ix":13}},{"ty":7,"nm":"Use only Color 1","mn":"Pseudo/0vbarur0o9-0014","ix":14,"v":{"a":0,"k":0,"ix":14}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0015","ix":15,"v":0}]}],"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"c 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[519,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[4.82,-11.395],[8.618,-8.617],[11.395,-4.82],[13.151,0],[11.395,4.82],[8.618,8.618],[26.301,0],[17.236,-17.235],[0,-26.301],[-17.236,-17.235],[-26.3,0],[-17.236,17.236],[-11.395,4.819],[-13.15,0],[-11.394,-4.82],[-8.618,-8.618],[-4.819,-11.395],[0,-13.151]],"o":[[0,13.15],[-4.819,11.395],[-8.618,8.618],[-11.394,4.82],[-13.15,0],[-11.395,-4.82],[-17.236,-17.235],[-26.3,0],[-17.236,17.236],[0,26.301],[17.236,17.236],[26.301,0],[8.618,-8.618],[11.395,-4.82],[13.151,0],[11.395,4.819],[8.618,8.618],[4.82,11.394],[0,0]],"v":[[162.591,-134.695],[155.106,-97.622],[134.695,-67.348],[104.42,-46.936],[67.347,-39.451],[30.274,-46.936],[0,-67.348],[-67.348,-95.244],[-134.695,-67.348],[-162.591,0],[-134.695,67.347],[-67.348,95.244],[0,67.347],[30.274,46.936],[67.347,39.451],[104.42,46.936],[134.695,67.347],[155.106,97.622],[162.591,134.695]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.282352954149,0.384313732386,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[567.347,568.757],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":4,"ty":4,"nm":"c BG","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[519,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[4.82,-11.395],[8.618,-8.617],[11.395,-4.82],[13.151,0],[11.395,4.82],[8.618,8.618],[26.301,0],[17.236,-17.235],[0,-26.301],[-17.236,-17.235],[-26.3,0],[-17.236,17.236],[-11.395,4.819],[-13.15,0],[-11.394,-4.82],[-8.618,-8.618],[-4.819,-11.395],[0,-13.151]],"o":[[0,13.15],[-4.819,11.395],[-8.618,8.618],[-11.394,4.82],[-13.15,0],[-11.395,-4.82],[-17.236,-17.235],[-26.3,0],[-17.236,17.236],[0,26.301],[17.236,17.236],[26.301,0],[8.618,-8.618],[11.395,-4.82],[13.151,0],[11.395,4.819],[8.618,8.618],[4.82,11.394],[0,0]],"v":[[162.591,-134.695],[155.106,-97.622],[134.695,-67.348],[104.42,-46.936],[67.347,-39.451],[30.274,-46.936],[0,-67.348],[-67.348,-95.244],[-134.695,-67.348],[-162.591,0],[-134.695,67.347],[-67.348,95.244],[0,67.347],[30.274,46.936],[67.347,39.451],[104.42,46.936],[134.695,67.347],[155.106,97.622],[162.591,134.695]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = FM_controllerLayer.effect('Gilbert Controller')('Color 1');\n } else {\n $bm_rt = value;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 100;\n } else {\n $bm_rt = $bm_mul(FM_controllerLayer.effect('Gilbert Controller')('On white background'), 100);\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[567.347,568.757],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":0}]},{"id":"comp_2","layers":[{"ddd":0,"ind":2,"ty":3,"nm":"Controller","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"Gilbert Controller","np":17,"mn":"Pseudo/0vbarur0o9","ix":1,"en":1,"ef":[{"ty":6,"nm":"Animation","mn":"Pseudo/0vbarur0o9-0001","ix":1,"v":0},{"ty":0,"nm":"Start","mn":"Pseudo/0vbarur0o9-0002","ix":2,"v":{"a":1,"k":[{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[100]}],"ix":2}},{"ty":0,"nm":"End","mn":"Pseudo/0vbarur0o9-0003","ix":3,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[0]},{"t":20,"s":[100]}],"ix":3}},{"ty":0,"nm":"Offset","mn":"Pseudo/0vbarur0o9-0004","ix":4,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[-50]},{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[50]}],"ix":4}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0005","ix":5,"v":0},{"ty":6,"nm":"Color","mn":"Pseudo/0vbarur0o9-0006","ix":6,"v":0},{"ty":2,"nm":"Color 1","mn":"Pseudo/0vbarur0o9-0007","ix":7,"v":{"a":0,"k":[1,0.262745098039,0.219607843137,1],"ix":7}},{"ty":2,"nm":"Color 2","mn":"Pseudo/0vbarur0o9-0008","ix":8,"v":{"a":0,"k":[1,0.419607843137,0,1],"ix":8}},{"ty":2,"nm":"Color 3","mn":"Pseudo/0vbarur0o9-0009","ix":9,"v":{"a":0,"k":[1,0.78431372549,0.262745098039,1],"ix":9}},{"ty":2,"nm":"Color 4","mn":"Pseudo/0vbarur0o9-0010","ix":10,"v":{"a":0,"k":[0.019607843137,0.807843137255,0.486274509804,1],"ix":10}},{"ty":2,"nm":"Color 5","mn":"Pseudo/0vbarur0o9-0011","ix":11,"v":{"a":0,"k":[0,0.701960784314,0.890196078431,1],"ix":11}},{"ty":2,"nm":"Color 6","mn":"Pseudo/0vbarur0o9-0012","ix":12,"v":{"a":0,"k":[0.854901960784,0.227450980392,0.701960784314,1],"ix":12}},{"ty":7,"nm":"On white background","mn":"Pseudo/0vbarur0o9-0013","ix":13,"v":{"a":0,"k":1,"ix":13}},{"ty":7,"nm":"Use only Color 1","mn":"Pseudo/0vbarur0o9-0014","ix":14,"v":{"a":0,"k":0,"ix":14}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0015","ix":15,"v":0}]}],"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"i 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,-44.397],[0,0],[-44.397,0],[0,0]],"o":[[0,0],[44.397,0],[0,0],[0,44.397],[0,0],[0,0]],"v":[[-85.165,-211.454],[-80.388,-211.454],[0,-131.067],[0,131.066],[80.387,211.454],[85.164,211.454]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0.137254908681,0.737254917622,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[500,568.934],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":4,"ty":4,"nm":"i 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[500,247.472],[500,391.472]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.282352954149,0.384313732386,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":5,"ty":4,"nm":"i BG","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,-44.397],[0,0],[-44.397,0],[0,0]],"o":[[0,0],[44.397,0],[0,0],[0,44.397],[0,0],[0,0]],"v":[[-85.165,-211.454],[-80.388,-211.454],[0,-131.067],[0,131.066],[80.387,211.454],[85.164,211.454]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[500,568.934],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[500,247.472],[500,391.472]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = FM_controllerLayer.effect('Gilbert Controller')('Color 1');\n } else {\n $bm_rt = value;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 100;\n } else {\n $bm_rt = $bm_mul(FM_controllerLayer.effect('Gilbert Controller')('On white background'), 100);\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":750,"st":0,"bm":0}]},{"id":"comp_3","layers":[{"ddd":0,"ind":2,"ty":3,"nm":"Controller","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"Gilbert Controller","np":17,"mn":"Pseudo/0vbarur0o9","ix":1,"en":1,"ef":[{"ty":6,"nm":"Animation","mn":"Pseudo/0vbarur0o9-0001","ix":1,"v":0},{"ty":0,"nm":"Start","mn":"Pseudo/0vbarur0o9-0002","ix":2,"v":{"a":1,"k":[{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[100]}],"ix":2}},{"ty":0,"nm":"End","mn":"Pseudo/0vbarur0o9-0003","ix":3,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[0]},{"t":20,"s":[100]}],"ix":3}},{"ty":0,"nm":"Offset","mn":"Pseudo/0vbarur0o9-0004","ix":4,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[-50]},{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[50]}],"ix":4}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0005","ix":5,"v":0},{"ty":6,"nm":"Color","mn":"Pseudo/0vbarur0o9-0006","ix":6,"v":0},{"ty":2,"nm":"Color 1","mn":"Pseudo/0vbarur0o9-0007","ix":7,"v":{"a":0,"k":[1,0.262745098039,0.219607843137,1],"ix":7}},{"ty":2,"nm":"Color 2","mn":"Pseudo/0vbarur0o9-0008","ix":8,"v":{"a":0,"k":[1,0.419607843137,0,1],"ix":8}},{"ty":2,"nm":"Color 3","mn":"Pseudo/0vbarur0o9-0009","ix":9,"v":{"a":0,"k":[1,0.78431372549,0.262745098039,1],"ix":9}},{"ty":2,"nm":"Color 4","mn":"Pseudo/0vbarur0o9-0010","ix":10,"v":{"a":0,"k":[0.019607843137,0.807843137255,0.486274509804,1],"ix":10}},{"ty":2,"nm":"Color 5","mn":"Pseudo/0vbarur0o9-0011","ix":11,"v":{"a":0,"k":[0,0.701960784314,0.890196078431,1],"ix":11}},{"ty":2,"nm":"Color 6","mn":"Pseudo/0vbarur0o9-0012","ix":12,"v":{"a":0,"k":[0.854901960784,0.227450980392,0.701960784314,1],"ix":12}},{"ty":7,"nm":"On white background","mn":"Pseudo/0vbarur0o9-0013","ix":13,"v":{"a":0,"k":1,"ix":13}},{"ty":7,"nm":"Use only Color 1","mn":"Pseudo/0vbarur0o9-0014","ix":14,"v":{"a":0,"k":0,"ix":14}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0015","ix":15,"v":0}]}],"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"k 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[501,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,-38.947],[0,0],[38.947,0],[0,0]],"o":[[0,0],[38.947,0],[0,0],[0,38.947],[0,0],[0,0]],"v":[[-84.288,-279.365],[13.768,-279.365],[84.288,-208.845],[84.288,208.845],[13.768,279.365],[-84.288,279.365]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0.137254908681,0.737254917622,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[345.191,491.155],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":4,"ty":4,"nm":"k 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[501,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,38.947],[0,0],[-38.947,0],[0,38.947],[0,0],[0,0],[-38.947,0]],"o":[[0,0],[38.947,0],[0,0],[0,-38.948],[38.948,0],[0,0],[0,0],[0,-38.947],[0,0]],"v":[[-171.444,232.251],[-110.637,232.251],[-40.117,161.731],[-40.117,76.116],[30.403,5.595],[100.924,-64.924],[100.924,-100.924],[100.924,-161.732],[171.444,-232.252]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.282352954149,0.384313732386,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[469.597,538.269],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":5,"ty":4,"nm":"k 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[501,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,38.947],[0,0],[38.947,0],[0,-38.947],[0,0],[0,0],[38.947,0]],"o":[[0,0],[-38.947,0],[0,0],[0,-38.947],[-38.948,0],[0,0],[0,0],[0,38.947],[0,0]],"v":[[183.848,70.52],[98.233,70.52],[27.713,0],[27.713,-85.615],[-42.807,-156.135],[-113.328,-85.615],[-113.328,0],[-113.328,85.615],[-183.848,156.135]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.529411792755,0.552941203117,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[542.807,700],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":6,"ty":4,"nm":"k BG","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[501,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,-38.947],[0,0],[38.947,0],[0,0]],"o":[[0,0],[38.947,0],[0,0],[0,38.947],[0,0],[0,0]],"v":[[-84.288,-279.365],[13.768,-279.365],[84.288,-208.845],[84.288,208.845],[13.768,279.365],[-84.288,279.365]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[345.191,491.155],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,38.947],[0,0],[-38.947,0],[0,38.947],[0,0],[0,0],[-38.947,0]],"o":[[0,0],[38.947,0],[0,0],[0,-38.948],[38.948,0],[0,0],[0,0],[0,-38.947],[0,0]],"v":[[-171.444,232.251],[-110.637,232.251],[-40.117,161.731],[-40.117,76.116],[30.403,5.595],[100.924,-64.924],[100.924,-100.924],[100.924,-161.732],[171.444,-232.252]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[469.597,538.269],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,38.947],[0,0],[38.947,0],[0,-38.947],[0,0],[0,0],[38.947,0]],"o":[[0,0],[-38.947,0],[0,0],[0,-38.947],[-38.948,0],[0,0],[0,0],[0,38.947],[0,0]],"v":[[183.848,70.52],[98.233,70.52],[27.713,0],[27.713,-85.615],[-42.807,-156.135],[-113.328,-85.615],[-113.328,0],[-113.328,85.615],[-183.848,156.135]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[542.807,700],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":1,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":4,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = FM_controllerLayer.effect('Gilbert Controller')('Color 1');\n } else {\n $bm_rt = value;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 100;\n } else {\n $bm_rt = $bm_mul(FM_controllerLayer.effect('Gilbert Controller')('On white background'), 100);\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":750,"st":0,"bm":0}]},{"id":"comp_4","layers":[{"ddd":0,"ind":2,"ty":3,"nm":"Controller","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"Gilbert Controller","np":17,"mn":"Pseudo/0vbarur0o9","ix":1,"en":1,"ef":[{"ty":6,"nm":"Animation","mn":"Pseudo/0vbarur0o9-0001","ix":1,"v":0},{"ty":0,"nm":"Start","mn":"Pseudo/0vbarur0o9-0002","ix":2,"v":{"a":1,"k":[{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[100]}],"ix":2}},{"ty":0,"nm":"End","mn":"Pseudo/0vbarur0o9-0003","ix":3,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[0]},{"t":20,"s":[100]}],"ix":3}},{"ty":0,"nm":"Offset","mn":"Pseudo/0vbarur0o9-0004","ix":4,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[-50]},{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[50]}],"ix":4}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0005","ix":5,"v":0},{"ty":6,"nm":"Color","mn":"Pseudo/0vbarur0o9-0006","ix":6,"v":0},{"ty":2,"nm":"Color 1","mn":"Pseudo/0vbarur0o9-0007","ix":7,"v":{"a":0,"k":[1,0.262745098039,0.219607843137,1],"ix":7}},{"ty":2,"nm":"Color 2","mn":"Pseudo/0vbarur0o9-0008","ix":8,"v":{"a":0,"k":[1,0.419607843137,0,1],"ix":8}},{"ty":2,"nm":"Color 3","mn":"Pseudo/0vbarur0o9-0009","ix":9,"v":{"a":0,"k":[1,0.78431372549,0.262745098039,1],"ix":9}},{"ty":2,"nm":"Color 4","mn":"Pseudo/0vbarur0o9-0010","ix":10,"v":{"a":0,"k":[0.019607843137,0.807843137255,0.486274509804,1],"ix":10}},{"ty":2,"nm":"Color 5","mn":"Pseudo/0vbarur0o9-0011","ix":11,"v":{"a":0,"k":[0,0.701960784314,0.890196078431,1],"ix":11}},{"ty":2,"nm":"Color 6","mn":"Pseudo/0vbarur0o9-0012","ix":12,"v":{"a":0,"k":[0.854901960784,0.227450980392,0.701960784314,1],"ix":12}},{"ty":7,"nm":"On white background","mn":"Pseudo/0vbarur0o9-0013","ix":13,"v":{"a":0,"k":1,"ix":13}},{"ty":7,"nm":"Use only Color 1","mn":"Pseudo/0vbarur0o9-0014","ix":14,"v":{"a":0,"k":0,"ix":14}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0015","ix":15,"v":0}]}],"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"t 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-19.081,0],[0,0],[0,-19.082],[0,0],[0,0],[-19.081,0],[0,0],[0,0],[0,-19.082],[0,0],[19.082,0],[0,0]],"o":[[0,0],[0,-19.082],[0,0],[19.081,0],[0,0],[0,0],[0,19.081],[0,0],[0,0],[19.082,0],[0,0],[0,19.081],[0,0],[0,0]],"v":[[-110.099,-166.967],[-110.099,-230.837],[-75.55,-265.388],[-39.55,-265.388],[-5.001,-230.837],[-5.001,-220.837],[-5.001,125.74],[29.549,160.289],[65.549,160.289],[75.549,160.289],[110.099,194.839],[110.099,230.839],[75.549,265.388],[11.679,265.388]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0.137254908681,0.737254917622,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[498.194,503.711],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":4,"ty":4,"nm":"t 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[372.514,473.517],[627.486,473.517]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.282352954149,0.384313732386,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":5,"ty":4,"nm":"t BG","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-19.081,0],[0,0],[0,-19.082],[0,0],[0,0],[-19.081,0],[0,0],[0,0],[0,-19.082],[0,0],[19.082,0],[0,0]],"o":[[0,0],[0,-19.082],[0,0],[19.081,0],[0,0],[0,0],[0,19.081],[0,0],[0,0],[19.082,0],[0,0],[0,19.081],[0,0],[0,0]],"v":[[-110.099,-166.967],[-110.099,-230.837],[-75.55,-265.388],[-39.55,-265.388],[-5.001,-230.837],[-5.001,-220.837],[-5.001,125.74],[29.549,160.289],[65.549,160.289],[75.549,160.289],[110.099,194.839],[110.099,230.839],[75.549,265.388],[11.679,265.388]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[498.194,503.711],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[372.514,473.517],[627.486,473.517]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = FM_controllerLayer.effect('Gilbert Controller')('Color 1');\n } else {\n $bm_rt = value;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 100;\n } else {\n $bm_rt = $bm_mul(FM_controllerLayer.effect('Gilbert Controller')('On white background'), 100);\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":750,"st":0,"bm":0}]},{"id":"comp_5","layers":[{"ddd":0,"ind":2,"ty":3,"nm":"Controller","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"Gilbert Controller","np":17,"mn":"Pseudo/0vbarur0o9","ix":1,"en":1,"ef":[{"ty":6,"nm":"Animation","mn":"Pseudo/0vbarur0o9-0001","ix":1,"v":0},{"ty":0,"nm":"Start","mn":"Pseudo/0vbarur0o9-0002","ix":2,"v":{"a":1,"k":[{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[100]}],"ix":2}},{"ty":0,"nm":"End","mn":"Pseudo/0vbarur0o9-0003","ix":3,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[0]},{"t":20,"s":[100]}],"ix":3}},{"ty":0,"nm":"Offset","mn":"Pseudo/0vbarur0o9-0004","ix":4,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[-50]},{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[50]}],"ix":4}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0005","ix":5,"v":0},{"ty":6,"nm":"Color","mn":"Pseudo/0vbarur0o9-0006","ix":6,"v":0},{"ty":2,"nm":"Color 1","mn":"Pseudo/0vbarur0o9-0007","ix":7,"v":{"a":0,"k":[1,0.262745098039,0.219607843137,1],"ix":7}},{"ty":2,"nm":"Color 2","mn":"Pseudo/0vbarur0o9-0008","ix":8,"v":{"a":0,"k":[1,0.419607843137,0,1],"ix":8}},{"ty":2,"nm":"Color 3","mn":"Pseudo/0vbarur0o9-0009","ix":9,"v":{"a":0,"k":[1,0.78431372549,0.262745098039,1],"ix":9}},{"ty":2,"nm":"Color 4","mn":"Pseudo/0vbarur0o9-0010","ix":10,"v":{"a":0,"k":[0.019607843137,0.807843137255,0.486274509804,1],"ix":10}},{"ty":2,"nm":"Color 5","mn":"Pseudo/0vbarur0o9-0011","ix":11,"v":{"a":0,"k":[0,0.701960784314,0.890196078431,1],"ix":11}},{"ty":2,"nm":"Color 6","mn":"Pseudo/0vbarur0o9-0012","ix":12,"v":{"a":0,"k":[0.854901960784,0.227450980392,0.701960784314,1],"ix":12}},{"ty":7,"nm":"On white background","mn":"Pseudo/0vbarur0o9-0013","ix":13,"v":{"a":0,"k":1,"ix":13}},{"ty":7,"nm":"Use only Color 1","mn":"Pseudo/0vbarur0o9-0014","ix":14,"v":{"a":0,"k":0,"ix":14}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0015","ix":15,"v":0}]}],"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"L 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[415.415,73.465],[415.415,908.845]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0.137254908681,0.737254917622,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":4,"ty":4,"nm":"L 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[258.83,664],[741.17,664]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.282352954149,0.384313732386,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":5,"ty":4,"nm":"L BG","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[415.415,73.465],[415.415,908.845]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[258.83,664],[741.17,664]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = FM_controllerLayer.effect('Gilbert Controller')('Color 1');\n } else {\n $bm_rt = value;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 100;\n } else {\n $bm_rt = $bm_mul(FM_controllerLayer.effect('Gilbert Controller')('On white background'), 100);\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":750,"st":0,"bm":0}]},{"id":"comp_6","layers":[{"ddd":0,"ind":2,"ty":3,"nm":"Controller","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"Gilbert Controller","np":17,"mn":"Pseudo/0vbarur0o9","ix":1,"en":1,"ef":[{"ty":6,"nm":"Animation","mn":"Pseudo/0vbarur0o9-0001","ix":1,"v":0},{"ty":0,"nm":"Start","mn":"Pseudo/0vbarur0o9-0002","ix":2,"v":{"a":1,"k":[{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[100]}],"ix":2}},{"ty":0,"nm":"End","mn":"Pseudo/0vbarur0o9-0003","ix":3,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[0]},{"t":20,"s":[100]}],"ix":3}},{"ty":0,"nm":"Offset","mn":"Pseudo/0vbarur0o9-0004","ix":4,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[-50]},{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[50]}],"ix":4}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0005","ix":5,"v":0},{"ty":6,"nm":"Color","mn":"Pseudo/0vbarur0o9-0006","ix":6,"v":0},{"ty":2,"nm":"Color 1","mn":"Pseudo/0vbarur0o9-0007","ix":7,"v":{"a":0,"k":[1,0.262745098039,0.219607843137,1],"ix":7}},{"ty":2,"nm":"Color 2","mn":"Pseudo/0vbarur0o9-0008","ix":8,"v":{"a":0,"k":[1,0.419607843137,0,1],"ix":8}},{"ty":2,"nm":"Color 3","mn":"Pseudo/0vbarur0o9-0009","ix":9,"v":{"a":0,"k":[1,0.78431372549,0.262745098039,1],"ix":9}},{"ty":2,"nm":"Color 4","mn":"Pseudo/0vbarur0o9-0010","ix":10,"v":{"a":0,"k":[0.019607843137,0.807843137255,0.486274509804,1],"ix":10}},{"ty":2,"nm":"Color 5","mn":"Pseudo/0vbarur0o9-0011","ix":11,"v":{"a":0,"k":[0,0.701960784314,0.890196078431,1],"ix":11}},{"ty":2,"nm":"Color 6","mn":"Pseudo/0vbarur0o9-0012","ix":12,"v":{"a":0,"k":[0.854901960784,0.227450980392,0.701960784314,1],"ix":12}},{"ty":7,"nm":"On white background","mn":"Pseudo/0vbarur0o9-0013","ix":13,"v":{"a":0,"k":1,"ix":13}},{"ty":7,"nm":"Use only Color 1","mn":"Pseudo/0vbarur0o9-0014","ix":14,"v":{"a":0,"k":0,"ix":14}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0015","ix":15,"v":0}]}],"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"o 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-52.602,0],[0,52.602],[52.601,0],[0,-52.602],[0,0]],"o":[[0,0],[0,52.602],[52.601,0],[0,-52.602],[-52.602,0],[0,0],[0,0]],"v":[[-95.243,-299.26],[-95.243,0],[0,95.243],[95.243,0],[0,-95.245],[-95.243,0],[-95.243,299.259]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0.137254908681,0.737254917622,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[500,568.406],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":4,"ty":4,"nm":"o BG","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-52.602,0],[0,52.602],[52.601,0],[0,-52.602],[0,0]],"o":[[0,0],[0,52.602],[52.601,0],[0,-52.602],[-52.602,0],[0,0],[0,0]],"v":[[-95.243,-299.26],[-95.243,0],[0,95.243],[95.243,0],[0,-95.245],[-95.243,0],[-95.243,299.259]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[500,568.406],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = FM_controllerLayer.effect('Gilbert Controller')('Color 1');\n } else {\n $bm_rt = value;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 100;\n } else {\n $bm_rt = $bm_mul(FM_controllerLayer.effect('Gilbert Controller')('On white background'), 100);\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":750,"st":0,"bm":0}]},{"id":"comp_7","layers":[{"ddd":0,"ind":2,"ty":3,"nm":"Controller","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"Gilbert Controller","np":17,"mn":"Pseudo/0vbarur0o9","ix":1,"en":1,"ef":[{"ty":6,"nm":"Animation","mn":"Pseudo/0vbarur0o9-0001","ix":1,"v":0},{"ty":0,"nm":"Start","mn":"Pseudo/0vbarur0o9-0002","ix":2,"v":{"a":1,"k":[{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[100]}],"ix":2}},{"ty":0,"nm":"End","mn":"Pseudo/0vbarur0o9-0003","ix":3,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[0]},{"t":20,"s":[100]}],"ix":3}},{"ty":0,"nm":"Offset","mn":"Pseudo/0vbarur0o9-0004","ix":4,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[-50]},{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[50]}],"ix":4}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0005","ix":5,"v":0},{"ty":6,"nm":"Color","mn":"Pseudo/0vbarur0o9-0006","ix":6,"v":0},{"ty":2,"nm":"Color 1","mn":"Pseudo/0vbarur0o9-0007","ix":7,"v":{"a":0,"k":[1,0.262745098039,0.219607843137,1],"ix":7}},{"ty":2,"nm":"Color 2","mn":"Pseudo/0vbarur0o9-0008","ix":8,"v":{"a":0,"k":[1,0.419607843137,0,1],"ix":8}},{"ty":2,"nm":"Color 3","mn":"Pseudo/0vbarur0o9-0009","ix":9,"v":{"a":0,"k":[1,0.78431372549,0.262745098039,1],"ix":9}},{"ty":2,"nm":"Color 4","mn":"Pseudo/0vbarur0o9-0010","ix":10,"v":{"a":0,"k":[0.019607843137,0.807843137255,0.486274509804,1],"ix":10}},{"ty":2,"nm":"Color 5","mn":"Pseudo/0vbarur0o9-0011","ix":11,"v":{"a":0,"k":[0,0.701960784314,0.890196078431,1],"ix":11}},{"ty":2,"nm":"Color 6","mn":"Pseudo/0vbarur0o9-0012","ix":12,"v":{"a":0,"k":[0.854901960784,0.227450980392,0.701960784314,1],"ix":12}},{"ty":7,"nm":"On white background","mn":"Pseudo/0vbarur0o9-0013","ix":13,"v":{"a":0,"k":1,"ix":13}},{"ty":7,"nm":"Use only Color 1","mn":"Pseudo/0vbarur0o9-0014","ix":14,"v":{"a":0,"k":0,"ix":14}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0015","ix":15,"v":0}]}],"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"n 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[482,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,43.8],[0,0],[0,0],[-43.8,0],[0,-43.799],[0,0],[-43.799,0],[0,0]],"o":[[43.799,0],[0,0],[0,0],[0,-43.799],[43.799,0],[0,0],[0,43.799],[0,0],[0,0]],"v":[[-232.294,226.671],[-152.988,147.365],[-152.988,0],[-152.988,-147.366],[-73.683,-226.672],[5.622,-147.366],[5.622,0],[84.928,79.306],[232.294,79.306]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0.137254908681,0.737254917622,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[590.958,700],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":4,"ty":4,"nm":"n 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[482,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-19.081,0],[0,0],[0,-19.081],[0,0],[19.081,0],[0,0]],"o":[[0,0],[0,19.081],[0,0],[19.081,0],[0,0],[0,19.081],[0,0],[0,0]],"v":[[-44.41,-191.205],[-44.41,-104.377],[-9.861,-69.827],[26.139,-69.827],[60.689,-35.278],[60.689,156.656],[26.139,191.205],[-60.689,191.205]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.282352954149,0.384313732386,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[377.28,543.344],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":5,"ty":4,"nm":"n BG","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[482,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,43.8],[0,0],[0,0],[-43.8,0],[0,-43.799],[0,0],[-43.799,0],[0,0]],"o":[[43.799,0],[0,0],[0,0],[0,-43.799],[43.799,0],[0,0],[0,43.799],[0,0],[0,0]],"v":[[-232.294,226.671],[-152.988,147.365],[-152.988,0],[-152.988,-147.366],[-73.683,-226.672],[5.622,-147.366],[5.622,0],[84.928,79.306],[232.294,79.306]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[590.958,700],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-19.081,0],[0,0],[0,-19.081],[0,0],[19.081,0],[0,0]],"o":[[0,0],[0,19.081],[0,0],[19.081,0],[0,0],[0,19.081],[0,0],[0,0]],"v":[[-44.41,-191.205],[-44.41,-104.377],[-9.861,-69.827],[26.139,-69.827],[60.689,-35.278],[60.689,156.656],[26.139,191.205],[-60.689,191.205]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[377.28,543.344],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = FM_controllerLayer.effect('Gilbert Controller')('Color 1');\n } else {\n $bm_rt = value;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 100;\n } else {\n $bm_rt = $bm_mul(FM_controllerLayer.effect('Gilbert Controller')('On white background'), 100);\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":750,"st":0,"bm":0}]},{"id":"comp_8","layers":[{"ddd":0,"ind":2,"ty":3,"nm":"Controller","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"Gilbert Controller","np":17,"mn":"Pseudo/0vbarur0o9","ix":1,"en":1,"ef":[{"ty":6,"nm":"Animation","mn":"Pseudo/0vbarur0o9-0001","ix":1,"v":0},{"ty":0,"nm":"Start","mn":"Pseudo/0vbarur0o9-0002","ix":2,"v":{"a":1,"k":[{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[100]}],"ix":2}},{"ty":0,"nm":"End","mn":"Pseudo/0vbarur0o9-0003","ix":3,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[0]},{"t":20,"s":[100]}],"ix":3}},{"ty":0,"nm":"Offset","mn":"Pseudo/0vbarur0o9-0004","ix":4,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[-50]},{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[50]}],"ix":4}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0005","ix":5,"v":0},{"ty":6,"nm":"Color","mn":"Pseudo/0vbarur0o9-0006","ix":6,"v":0},{"ty":2,"nm":"Color 1","mn":"Pseudo/0vbarur0o9-0007","ix":7,"v":{"a":0,"k":[1,0.262745098039,0.219607843137,1],"ix":7}},{"ty":2,"nm":"Color 2","mn":"Pseudo/0vbarur0o9-0008","ix":8,"v":{"a":0,"k":[1,0.419607843137,0,1],"ix":8}},{"ty":2,"nm":"Color 3","mn":"Pseudo/0vbarur0o9-0009","ix":9,"v":{"a":0,"k":[1,0.78431372549,0.262745098039,1],"ix":9}},{"ty":2,"nm":"Color 4","mn":"Pseudo/0vbarur0o9-0010","ix":10,"v":{"a":0,"k":[0.019607843137,0.807843137255,0.486274509804,1],"ix":10}},{"ty":2,"nm":"Color 5","mn":"Pseudo/0vbarur0o9-0011","ix":11,"v":{"a":0,"k":[0,0.701960784314,0.890196078431,1],"ix":11}},{"ty":2,"nm":"Color 6","mn":"Pseudo/0vbarur0o9-0012","ix":12,"v":{"a":0,"k":[0.854901960784,0.227450980392,0.701960784314,1],"ix":12}},{"ty":7,"nm":"On white background","mn":"Pseudo/0vbarur0o9-0013","ix":13,"v":{"a":0,"k":1,"ix":13}},{"ty":7,"nm":"Use only Color 1","mn":"Pseudo/0vbarur0o9-0014","ix":14,"v":{"a":0,"k":0,"ix":14}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0015","ix":15,"v":0}]}],"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"g 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,-52.602],[0,0],[-52.601,0],[0,52.601],[52.602,0],[0,-52.602],[0,0]],"o":[[52.602,0],[0,0],[0,52.601],[52.602,0],[0,-52.602],[-52.601,0],[0,0],[0,0]],"v":[[-142.866,-272.067],[-47.622,-176.823],[-47.622,-27.193],[47.622,68.05],[142.865,-27.193],[47.622,-122.437],[-47.622,-27.193],[-47.622,272.067]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0.137254908681,0.737254917622,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[435.104,595.599],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":4,"ty":4,"nm":"g 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[26.211,0],[0,0],[0,26.212],[0,0],[0,0],[17.578,0],[0,0],[0,-17.578],[0,0],[52.601,0],[0,0],[0,0],[0,-26.211],[-26.211,0],[0,0],[0,0],[0,-26.211],[26.211,0],[0,0],[0,0],[0,78.634],[0,0]],"o":[[0,0],[0,26.212],[0,0],[-26.211,0],[0,0],[0,0],[0,-17.578],[0,0],[-17.578,0],[0,0],[0,52.602],[0,0],[0,0],[-26.211,0],[0,26.211],[0,0],[0,0],[26.211,0],[0,26.211],[0,0],[0,0],[-78.633,0],[0,0],[0,0]],"v":[[241.351,-111.453],[241.351,-27.669],[193.892,19.791],[193.891,19.791],[146.432,-27.669],[146.432,-94.919],[146.432,-158.335],[114.604,-190.163],[75.883,-190.163],[44.055,-158.335],[44.055,-94.919],[-51.188,0.325],[-51.189,0.325],[-98.973,0.325],[-146.432,47.784],[-98.973,95.244],[-51.189,95.244],[-3.404,95.244],[44.055,142.703],[-3.404,190.163],[-87.189,190.163],[-98.973,190.163],[-241.351,47.784],[-241.351,-130.325]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.282352954149,0.384313732386,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[533.914,663.675],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":5,"ty":4,"nm":"g BG","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,-52.602],[0,0],[-52.601,0],[0,52.601],[52.602,0],[0,-52.602],[0,0]],"o":[[52.602,0],[0,0],[0,52.601],[52.602,0],[0,-52.602],[-52.601,0],[0,0],[0,0]],"v":[[-142.866,-272.067],[-47.622,-176.823],[-47.622,-27.193],[47.622,68.05],[142.865,-27.193],[47.622,-122.437],[-47.622,-27.193],[-47.622,272.067]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[435.104,595.599],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[26.211,0],[0,0],[0,26.212],[0,0],[0,0],[17.578,0],[0,0],[0,-17.578],[0,0],[52.601,0],[0,0],[0,0],[0,-26.211],[-26.211,0],[0,0],[0,0],[0,-26.211],[26.211,0],[0,0],[0,0],[0,78.634],[0,0]],"o":[[0,0],[0,26.212],[0,0],[-26.211,0],[0,0],[0,0],[0,-17.578],[0,0],[-17.578,0],[0,0],[0,52.602],[0,0],[0,0],[-26.211,0],[0,26.211],[0,0],[0,0],[26.211,0],[0,26.211],[0,0],[0,0],[-78.633,0],[0,0],[0,0]],"v":[[241.351,-111.453],[241.351,-27.669],[193.892,19.791],[193.891,19.791],[146.432,-27.669],[146.432,-94.919],[146.432,-158.335],[114.604,-190.163],[75.883,-190.163],[44.055,-158.335],[44.055,-94.919],[-51.188,0.325],[-51.189,0.325],[-98.973,0.325],[-146.432,47.784],[-98.973,95.244],[-51.189,95.244],[-3.404,95.244],[44.055,142.703],[-3.404,190.163],[-87.189,190.163],[-98.973,190.163],[-241.351,47.784],[-241.351,-130.325]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[533.914,663.675],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = FM_controllerLayer.effect('Gilbert Controller')('Color 1');\n } else {\n $bm_rt = value;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 100;\n } else {\n $bm_rt = $bm_mul(FM_controllerLayer.effect('Gilbert Controller')('On white background'), 100);\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":750,"st":0,"bm":0}]},{"id":"comp_9","layers":[{"ddd":0,"ind":2,"ty":3,"nm":"Controller","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"Gilbert Controller","np":17,"mn":"Pseudo/0vbarur0o9","ix":1,"en":1,"ef":[{"ty":6,"nm":"Animation","mn":"Pseudo/0vbarur0o9-0001","ix":1,"v":0},{"ty":0,"nm":"Start","mn":"Pseudo/0vbarur0o9-0002","ix":2,"v":{"a":1,"k":[{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[100]}],"ix":2}},{"ty":0,"nm":"End","mn":"Pseudo/0vbarur0o9-0003","ix":3,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[0]},{"t":20,"s":[100]}],"ix":3}},{"ty":0,"nm":"Offset","mn":"Pseudo/0vbarur0o9-0004","ix":4,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[-50]},{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[50]}],"ix":4}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0005","ix":5,"v":0},{"ty":6,"nm":"Color","mn":"Pseudo/0vbarur0o9-0006","ix":6,"v":0},{"ty":2,"nm":"Color 1","mn":"Pseudo/0vbarur0o9-0007","ix":7,"v":{"a":0,"k":[1,0.262745098039,0.219607843137,1],"ix":7}},{"ty":2,"nm":"Color 2","mn":"Pseudo/0vbarur0o9-0008","ix":8,"v":{"a":0,"k":[1,0.419607843137,0,1],"ix":8}},{"ty":2,"nm":"Color 3","mn":"Pseudo/0vbarur0o9-0009","ix":9,"v":{"a":0,"k":[1,0.78431372549,0.262745098039,1],"ix":9}},{"ty":2,"nm":"Color 4","mn":"Pseudo/0vbarur0o9-0010","ix":10,"v":{"a":0,"k":[0.019607843137,0.807843137255,0.486274509804,1],"ix":10}},{"ty":2,"nm":"Color 5","mn":"Pseudo/0vbarur0o9-0011","ix":11,"v":{"a":0,"k":[0,0.701960784314,0.890196078431,1],"ix":11}},{"ty":2,"nm":"Color 6","mn":"Pseudo/0vbarur0o9-0012","ix":12,"v":{"a":0,"k":[0.854901960784,0.227450980392,0.701960784314,1],"ix":12}},{"ty":7,"nm":"On white background","mn":"Pseudo/0vbarur0o9-0013","ix":13,"v":{"a":0,"k":1,"ix":13}},{"ty":7,"nm":"Use only Color 1","mn":"Pseudo/0vbarur0o9-0014","ix":14,"v":{"a":0,"k":0,"ix":14}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0015","ix":15,"v":0}]}],"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"u 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[518,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,-19.081],[0,0],[0,0],[-19.081,0],[0,0],[0,0],[0,-19.081],[0,0]],"o":[[0,0],[19.081,0],[0,0],[0,0],[0,19.081],[0,0],[0,0],[19.081,0],[0,0],[0,0]],"v":[[-105.824,-198.808],[-69.824,-198.808],[-35.275,-164.259],[-35.275,-113.336],[-35.275,78.787],[-0.725,113.336],[35.275,113.336],[71.275,113.336],[105.824,147.885],[105.824,198.808]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.282352954149,0.384313732386,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[597.306,550.664],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":4,"ty":4,"nm":"u 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[518,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,-43.8],[0,0],[-43.799,0],[0,43.799],[0,0],[0,0],[-43.799,0],[0,0]],"o":[[0,0],[43.799,0],[0,0],[0.001,43.799],[43.8,0],[0,0],[0,0],[0,-43.8],[0,0],[0,0]],"v":[[-232.294,-79.306],[-84.928,-79.306],[-5.624,0],[-5.624,147.366],[73.683,226.672],[152.988,147.366],[152.988,0],[152.988,-147.366],[232.294,-226.672],[232.294,-226.672]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0.137254908681,0.737254917622,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[409.042,437.328],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":5,"ty":4,"nm":"u BG","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[518,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,-19.081],[0,0],[0,0],[-19.081,0],[0,0],[0,0],[0,-19.081],[0,0]],"o":[[0,0],[19.081,0],[0,0],[0,0],[0,19.081],[0,0],[0,0],[19.081,0],[0,0],[0,0]],"v":[[-105.824,-198.808],[-69.824,-198.808],[-35.275,-164.259],[-35.275,-113.336],[-35.275,78.787],[-0.725,113.336],[35.275,113.336],[71.275,113.336],[105.824,147.885],[105.824,198.808]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[597.306,550.664],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,-43.8],[0,0],[-43.799,0],[0,43.799],[0,0],[0,0],[-43.799,0],[0,0]],"o":[[0,0],[43.799,0],[0,0],[0.001,43.799],[43.8,0],[0,0],[0,0],[0,-43.8],[0,0],[0,0]],"v":[[-232.294,-79.306],[-84.928,-79.306],[-5.624,0],[-5.624,147.366],[73.683,226.672],[152.988,147.366],[152.988,0],[152.988,-147.366],[232.294,-226.672],[232.294,-226.672]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[409.042,437.328],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = FM_controllerLayer.effect('Gilbert Controller')('Color 1');\n } else {\n $bm_rt = value;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 100;\n } else {\n $bm_rt = $bm_mul(FM_controllerLayer.effect('Gilbert Controller')('On white background'), 100);\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":750,"st":0,"bm":0}]},{"id":"comp_10","layers":[{"ddd":0,"ind":2,"ty":3,"nm":"Controller","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"Gilbert Controller","np":17,"mn":"Pseudo/0vbarur0o9","ix":1,"en":1,"ef":[{"ty":6,"nm":"Animation","mn":"Pseudo/0vbarur0o9-0001","ix":1,"v":0},{"ty":0,"nm":"Start","mn":"Pseudo/0vbarur0o9-0002","ix":2,"v":{"a":1,"k":[{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[100]}],"ix":2}},{"ty":0,"nm":"End","mn":"Pseudo/0vbarur0o9-0003","ix":3,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[0]},{"t":20,"s":[100]}],"ix":3}},{"ty":0,"nm":"Offset","mn":"Pseudo/0vbarur0o9-0004","ix":4,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[-50]},{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[50]}],"ix":4}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0005","ix":5,"v":0},{"ty":6,"nm":"Color","mn":"Pseudo/0vbarur0o9-0006","ix":6,"v":0},{"ty":2,"nm":"Color 1","mn":"Pseudo/0vbarur0o9-0007","ix":7,"v":{"a":0,"k":[1,0.262745098039,0.219607843137,1],"ix":7}},{"ty":2,"nm":"Color 2","mn":"Pseudo/0vbarur0o9-0008","ix":8,"v":{"a":0,"k":[1,0.419607843137,0,1],"ix":8}},{"ty":2,"nm":"Color 3","mn":"Pseudo/0vbarur0o9-0009","ix":9,"v":{"a":0,"k":[1,0.78431372549,0.262745098039,1],"ix":9}},{"ty":2,"nm":"Color 4","mn":"Pseudo/0vbarur0o9-0010","ix":10,"v":{"a":0,"k":[0.019607843137,0.807843137255,0.486274509804,1],"ix":10}},{"ty":2,"nm":"Color 5","mn":"Pseudo/0vbarur0o9-0011","ix":11,"v":{"a":0,"k":[0,0.701960784314,0.890196078431,1],"ix":11}},{"ty":2,"nm":"Color 6","mn":"Pseudo/0vbarur0o9-0012","ix":12,"v":{"a":0,"k":[0.854901960784,0.227450980392,0.701960784314,1],"ix":12}},{"ty":7,"nm":"On white background","mn":"Pseudo/0vbarur0o9-0013","ix":13,"v":{"a":0,"k":1,"ix":13}},{"ty":7,"nm":"Use only Color 1","mn":"Pseudo/0vbarur0o9-0014","ix":14,"v":{"a":0,"k":0,"ix":14}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0015","ix":15,"v":0}]}],"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"d 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,52.602],[0,0],[0,0],[52.601,0],[0,0]],"o":[[-52.602,0],[0,0],[0,0],[0,-52.602],[0,0],[0,0]],"v":[[124.764,333.434],[29.52,238.19],[29.52,179.15],[29.52,-238.19],[-65.723,-333.434],[-124.764,-333.434]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.305882364511,0.384313732386,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[565.723,520.851],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":4,"ty":4,"nm":"d 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,-52.602],[52.602,0],[0,52.601],[-52.602,0],[0,0]],"o":[[0,0],[52.602,0],[0,52.601],[-52.602,0],[0,-52.602],[0,0],[0,0]],"v":[[-299.259,-95.243],[0,-95.243],[95.243,0.001],[0,95.244],[-95.245,0.001],[0,-95.243],[299.259,-95.243]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0.137254908681,0.737254917622,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[500,568.406],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":5,"ty":4,"nm":"d BG","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,52.602],[0,0],[0,0],[52.601,0],[0,0]],"o":[[-52.602,0],[0,0],[0,0],[0,-52.602],[0,0],[0,0]],"v":[[124.764,333.434],[29.52,238.19],[29.52,179.15],[29.52,-238.19],[-65.723,-333.434],[-124.764,-333.434]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[565.723,520.851],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,-52.602],[52.602,0],[0,52.601],[-52.602,0],[0,0]],"o":[[0,0],[52.602,0],[0,52.601],[-52.602,0],[0,-52.602],[0,0],[0,0]],"v":[[-299.259,-95.243],[0,-95.243],[95.243,0.001],[0,95.244],[-95.245,0.001],[0,-95.243],[299.259,-95.243]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[500,568.406],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = FM_controllerLayer.effect('Gilbert Controller')('Color 1');\n } else {\n $bm_rt = value;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 100;\n } else {\n $bm_rt = $bm_mul(FM_controllerLayer.effect('Gilbert Controller')('On white background'), 100);\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":750,"st":0,"bm":0}]},{"id":"comp_11","layers":[{"ddd":0,"ind":2,"ty":3,"nm":"Controller","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"Gilbert Controller","np":17,"mn":"Pseudo/0vbarur0o9","ix":1,"en":1,"ef":[{"ty":6,"nm":"Animation","mn":"Pseudo/0vbarur0o9-0001","ix":1,"v":0},{"ty":0,"nm":"Start","mn":"Pseudo/0vbarur0o9-0002","ix":2,"v":{"a":1,"k":[{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[100]}],"ix":2}},{"ty":0,"nm":"End","mn":"Pseudo/0vbarur0o9-0003","ix":3,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[0]},{"t":20,"s":[100]}],"ix":3}},{"ty":0,"nm":"Offset","mn":"Pseudo/0vbarur0o9-0004","ix":4,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[-50]},{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[50]}],"ix":4}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0005","ix":5,"v":0},{"ty":6,"nm":"Color","mn":"Pseudo/0vbarur0o9-0006","ix":6,"v":0},{"ty":2,"nm":"Color 1","mn":"Pseudo/0vbarur0o9-0007","ix":7,"v":{"a":0,"k":[1,0.262745098039,0.219607843137,1],"ix":7}},{"ty":2,"nm":"Color 2","mn":"Pseudo/0vbarur0o9-0008","ix":8,"v":{"a":0,"k":[1,0.419607843137,0,1],"ix":8}},{"ty":2,"nm":"Color 3","mn":"Pseudo/0vbarur0o9-0009","ix":9,"v":{"a":0,"k":[1,0.78431372549,0.262745098039,1],"ix":9}},{"ty":2,"nm":"Color 4","mn":"Pseudo/0vbarur0o9-0010","ix":10,"v":{"a":0,"k":[0.019607843137,0.807843137255,0.486274509804,1],"ix":10}},{"ty":2,"nm":"Color 5","mn":"Pseudo/0vbarur0o9-0011","ix":11,"v":{"a":0,"k":[0,0.701960784314,0.890196078431,1],"ix":11}},{"ty":2,"nm":"Color 6","mn":"Pseudo/0vbarur0o9-0012","ix":12,"v":{"a":0,"k":[0.854901960784,0.227450980392,0.701960784314,1],"ix":12}},{"ty":7,"nm":"On white background","mn":"Pseudo/0vbarur0o9-0013","ix":13,"v":{"a":0,"k":1,"ix":13}},{"ty":7,"nm":"Use only Color 1","mn":"Pseudo/0vbarur0o9-0014","ix":14,"v":{"a":0,"k":0,"ix":14}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0015","ix":15,"v":0}]}],"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"a 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-52.602,0],[0,-52.602],[52.601,0],[0,52.602],[0,0]],"o":[[0,0],[0,-52.602],[52.601,0],[0,52.602],[-52.602,0],[0,0],[0,0]],"v":[[-95.243,299.259],[-95.243,0],[0,-95.245],[95.243,0],[0,95.243],[-95.243,0],[-95.243,-299.26]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0.137254908681,0.737254917622,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[500,568.406],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":4,"ty":4,"nm":"a 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[595.244,305.919],[595.244,830.893]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.305882364511,0.384313732386,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":5,"ty":4,"nm":"a BG","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-52.602,0],[0,-52.602],[52.601,0],[0,52.602],[0,0]],"o":[[0,0],[0,-52.602],[52.601,0],[0,52.602],[-52.602,0],[0,0],[0,0]],"v":[[-95.243,299.259],[-95.243,0],[0,-95.245],[95.243,0],[0,95.243],[-95.243,0],[-95.243,-299.26]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[500,568.406],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[595.244,305.919],[595.244,830.893]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = FM_controllerLayer.effect('Gilbert Controller')('Color 1');\n } else {\n $bm_rt = value;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 100;\n } else {\n $bm_rt = $bm_mul(FM_controllerLayer.effect('Gilbert Controller')('On white background'), 100);\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":750,"st":0,"bm":0}]},{"id":"comp_12","layers":[{"ddd":0,"ind":2,"ty":3,"nm":"Controller","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"Gilbert Controller","np":17,"mn":"Pseudo/0vbarur0o9","ix":1,"en":1,"ef":[{"ty":6,"nm":"Animation","mn":"Pseudo/0vbarur0o9-0001","ix":1,"v":0},{"ty":0,"nm":"Start","mn":"Pseudo/0vbarur0o9-0002","ix":2,"v":{"a":1,"k":[{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[100]}],"ix":2}},{"ty":0,"nm":"End","mn":"Pseudo/0vbarur0o9-0003","ix":3,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[0]},{"t":20,"s":[100]}],"ix":3}},{"ty":0,"nm":"Offset","mn":"Pseudo/0vbarur0o9-0004","ix":4,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[-50]},{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[50]}],"ix":4}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0005","ix":5,"v":0},{"ty":6,"nm":"Color","mn":"Pseudo/0vbarur0o9-0006","ix":6,"v":0},{"ty":2,"nm":"Color 1","mn":"Pseudo/0vbarur0o9-0007","ix":7,"v":{"a":0,"k":[1,0.262745098039,0.219607843137,1],"ix":7}},{"ty":2,"nm":"Color 2","mn":"Pseudo/0vbarur0o9-0008","ix":8,"v":{"a":0,"k":[1,0.419607843137,0,1],"ix":8}},{"ty":2,"nm":"Color 3","mn":"Pseudo/0vbarur0o9-0009","ix":9,"v":{"a":0,"k":[1,0.78431372549,0.262745098039,1],"ix":9}},{"ty":2,"nm":"Color 4","mn":"Pseudo/0vbarur0o9-0010","ix":10,"v":{"a":0,"k":[0.019607843137,0.807843137255,0.486274509804,1],"ix":10}},{"ty":2,"nm":"Color 5","mn":"Pseudo/0vbarur0o9-0011","ix":11,"v":{"a":0,"k":[0,0.701960784314,0.890196078431,1],"ix":11}},{"ty":2,"nm":"Color 6","mn":"Pseudo/0vbarur0o9-0012","ix":12,"v":{"a":0,"k":[0.854901960784,0.227450980392,0.701960784314,1],"ix":12}},{"ty":7,"nm":"On white background","mn":"Pseudo/0vbarur0o9-0013","ix":13,"v":{"a":0,"k":1,"ix":13}},{"ty":7,"nm":"Use only Color 1","mn":"Pseudo/0vbarur0o9-0014","ix":14,"v":{"a":0,"k":0,"ix":14}},{"ty":6,"nm":"Gilbert Controller","mn":"Pseudo/0vbarur0o9-0015","ix":15,"v":0}]}],"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"l 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[517,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,-19.081],[0,0],[0,0],[-19.081,0],[0,0],[0,0],[0,-19.081],[0,0]],"o":[[0,0],[19.081,0],[0,0],[0,0],[0,19.081],[0,0],[0,0],[19.082,0],[0,0],[0,0]],"v":[[-152.04,-307.61],[-23.608,-307.61],[10.941,-273.061],[10.941,-237.061],[10.941,110.08],[45.49,144.629],[81.49,144.629],[117.49,144.629],[152.04,179.179],[152.04,307.61]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0.137254908681,0.737254917622,1],"ix":3},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 0;\n } else {\n $bm_rt = 100;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[471.784,519.371],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":1},{"ddd":0,"ind":4,"ty":4,"nm":"l BG","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[517,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,-19.081],[0,0],[0,0],[-19.081,0],[0,0],[0,0],[0,-19.081],[0,0]],"o":[[0,0],[19.081,0],[0,0],[0,0],[0,19.081],[0,0],[0,0],[19.082,0],[0,0],[0,0]],"v":[[-152.04,-307.61],[-23.608,-307.61],[10.941,-273.061],[10.941,-237.061],[10.941,110.08],[45.49,144.629],[81.49,144.629],[117.49,144.629],[152.04,179.179],[152.04,307.61]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[471.784,519.371],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('Start'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"e":{"a":0,"k":100,"ix":2,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = $bm_div(FM_controllerLayer.effect('Gilbert Controller')('End'), 2);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":0,"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n $bm_rt = linear(FM_controllerLayer.effect('Gilbert Controller')('Offset'), -50, 50, 0, 180);\n} catch (e) {\n $bm_rt = value;\n}"},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = FM_controllerLayer.effect('Gilbert Controller')('Color 1');\n } else {\n $bm_rt = value;\n }\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":100,"ix":4,"x":"var $bm_rt;\ntry {\n var FM_controllerComp = thisComp;\n var FM_controllerLayer = FM_controllerComp.layer('Controller');\n if (FM_controllerLayer.effect('Gilbert Controller')('Use only Color 1') == 1) {\n $bm_rt = 100;\n } else {\n $bm_rt = $bm_mul(FM_controllerLayer.effect('Gilbert Controller')('On white background'), 100);\n }\n} catch (e) {\n $bm_rt = value;\n}"},"w":{"a":0,"k":72,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":750,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"pride [Controller]","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[3234,1674.5,0],"ix":2},"a":{"a":0,"k":[611.523,415.206,0],"ix":1},"s":{"a":0,"k":[433.593,315.796,100],"ix":6}},"ao":0,"ef":[{"ty":5,"nm":"Gilbert Controller","np":17,"mn":"Pseudo/0vbarur0o9","ix":1,"en":1,"ef":[{"ty":6,"nm":"Animation","mn":"Pseudo/0vbarur0o9-0001","ix":1,"v":0},{"ty":0,"nm":"Start","mn":"Pseudo/0vbarur0o9-0002","ix":2,"v":{"a":1,"k":[{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[100]}],"ix":2}},{"ty":0,"nm":"End","mn":"Pseudo/0vbarur0o9-0003","ix":3,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[0]},{"t":20,"s":[100]}],"ix":3}},{"ty":0,"nm":"Offset","mn":"Pseudo/0vbarur0o9-0004","ix":4,"v":{"a":1,"k":[{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.001],"y":[0]},"t":0,"s":[-50]},{"i":{"x":[0.25],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.75],"y":[0]},"t":75,"s":[0]},{"t":95,"s":[50]}],"ix":4}},{"ty":6,"nm":"","mn":"Pseudo/0vbarur0o9-0005","ix":5,"v":0},{"ty":6,"nm":"Color","mn":"Pseudo/0vbarur0o9-0006","ix":6,"v":0},{"ty":2,"nm":"Color 1","mn":"Pseudo/0vbarur0o9-0007","ix":7,"v":{"a":0,"k":[1,0.262745112181,0.219607844949,1],"ix":7}},{"ty":2,"nm":"Color 2","mn":"Pseudo/0vbarur0o9-0008","ix":8,"v":{"a":0,"k":[1,0.419607847929,0,1],"ix":8}},{"ty":2,"nm":"Color 3","mn":"Pseudo/0vbarur0o9-0009","ix":9,"v":{"a":0,"k":[1,0.784313738346,0.262745112181,1],"ix":9}},{"ty":2,"nm":"Color 4","mn":"Pseudo/0vbarur0o9-0010","ix":10,"v":{"a":0,"k":[0.019607843831,0.807843148708,0.486274510622,1],"ix":10}},{"ty":2,"nm":"Color 5","mn":"Pseudo/0vbarur0o9-0011","ix":11,"v":{"a":0,"k":[0,0.701960802078,0.890196084976,1],"ix":11}},{"ty":2,"nm":"Color 6","mn":"Pseudo/0vbarur0o9-0012","ix":12,"v":{"a":0,"k":[0.854901969433,0.227450981736,0.701960802078,1],"ix":12}},{"ty":7,"nm":"On white background","mn":"Pseudo/0vbarur0o9-0013","ix":13,"v":{"a":0,"k":1,"ix":13}},{"ty":7,"nm":"Use only Color 1","mn":"Pseudo/0vbarur0o9-0014","ix":14,"v":{"a":0,"k":0,"ix":14}},{"ty":6,"nm":"","mn":"Pseudo/0vbarur0o9-0015","ix":15,"v":0}]},{"ty":5,"nm":"Font Controller","np":10,"mn":"Pseudo/Ib61aa4a42yOa","ix":2,"en":1,"ef":[{"ty":6,"nm":"","mn":"Pseudo/Ib61aa4a42yOa-0001","ix":1,"v":0},{"ty":6,"nm":"","mn":"Pseudo/Ib61aa4a42yOa-0002","ix":2,"v":0},{"ty":0,"nm":"Tracking","mn":"Pseudo/Ib61aa4a42yOa-0003","ix":3,"v":{"a":0,"k":0,"ix":3}},{"ty":0,"nm":"Tracking center","mn":"Pseudo/Ib61aa4a42yOa-0004","ix":4,"v":{"a":0,"k":0,"ix":4}},{"ty":0,"nm":"Line spacing","mn":"Pseudo/Ib61aa4a42yOa-0005","ix":5,"v":{"a":0,"k":157.259,"ix":5}},{"ty":0,"nm":"Offset animation time","mn":"Pseudo/Ib61aa4a42yOa-0006","ix":6,"v":{"a":0,"k":0,"ix":6}},{"ty":0,"nm":"Y-Offset","mn":"Pseudo/Ib61aa4a42yOa-0007","ix":7,"v":{"a":0,"k":0,"ix":7}},{"ty":0,"nm":"Z-Offset","mn":"Pseudo/Ib61aa4a42yOa-0008","ix":8,"v":{"a":0,"k":0,"ix":8}}]}],"ip":0,"op":125,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"S","parent":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[74.614,163.145,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[46.126,63.332,100],"ix":6}},"ao":0,"w":1000,"h":1000,"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":0,"nm":"c","parent":1,"refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[194.542,164.412,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[46.126,63.332,100],"ix":6}},"ao":0,"w":1000,"h":1000,"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":0,"nm":"i","parent":1,"refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[272.957,170.745,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[46.126,63.332,100],"ix":6}},"ao":0,"w":1000,"h":1000,"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":0,"nm":"k","parent":1,"refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[345.836,169.478,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[46.126,63.332,100],"ix":6}},"ao":0,"w":1000,"h":1000,"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":0,"nm":"i","parent":1,"refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[419.638,169.478,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[46.126,63.332,100],"ix":6}},"ao":0,"w":1000,"h":1000,"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":0,"nm":"t","parent":1,"refId":"comp_4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[474.99,169.478,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[46.126,63.332,100],"ix":6}},"ao":0,"w":1000,"h":1000,"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":0,"nm":"L","parent":1,"refId":"comp_5","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[594.918,220.144,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[46.126,63.332,100],"ix":6}},"ao":0,"w":1000,"h":1000,"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":0,"nm":"o","parent":1,"refId":"comp_6","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[687.17,286.009,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[23.063,31.666,100],"ix":6}},"ao":0,"w":1000,"h":1000,"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":0,"nm":"n","parent":1,"refId":"comp_7","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[751.747,283.476,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[23.063,31.666,100],"ix":6}},"ao":0,"w":1000,"h":1000,"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":0,"nm":"g","parent":1,"refId":"comp_8","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[814.478,283.476,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[23.063,31.666,100],"ix":6}},"ao":0,"w":1000,"h":1000,"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":0,"nm":"i","parent":1,"refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[859.682,281.576,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[23.063,31.666,100],"ix":6}},"ao":0,"w":1000,"h":1000,"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":0,"nm":"t","parent":1,"refId":"comp_4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[886.896,281.576,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[23.063,31.666,100],"ix":6}},"ao":0,"w":1000,"h":1000,"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":0,"nm":"u","parent":1,"refId":"comp_9","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[936.251,284.742,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[23.063,31.666,100],"ix":6}},"ao":0,"w":1000,"h":1000,"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":15,"ty":0,"nm":"d","parent":1,"refId":"comp_10","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1002.673,282.209,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[23.063,31.666,100],"ix":6}},"ao":0,"w":1000,"h":1000,"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":16,"ty":0,"nm":"i","parent":1,"refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1046.032,282.209,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[23.063,31.666,100],"ix":6}},"ao":0,"w":1000,"h":1000,"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":17,"ty":0,"nm":"n","parent":1,"refId":"comp_7","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1093.08,280.942,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[23.063,31.666,100],"ix":6}},"ao":0,"w":1000,"h":1000,"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":18,"ty":0,"nm":"a","parent":1,"refId":"comp_11","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1152.122,280.942,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[23.063,31.666,100],"ix":6}},"ao":0,"w":1000,"h":1000,"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":19,"ty":0,"nm":"l","parent":1,"refId":"comp_12","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1195.48,280.942,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[23.063,31.666,100],"ix":6}},"ao":0,"w":1000,"h":1000,"ip":0,"op":750,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f332.svg b/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f332.svg new file mode 100644 index 0000000..540f186 --- /dev/null +++ b/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f332.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f389.svg b/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f389.svg new file mode 100644 index 0000000..a4b8305 --- /dev/null +++ b/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f389.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f4ca.svg b/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f4ca.svg new file mode 100644 index 0000000..3c572cb --- /dev/null +++ b/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f4ca.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f4d6.svg b/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f4d6.svg new file mode 100644 index 0000000..0dfd083 --- /dev/null +++ b/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f4d6.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f527.svg b/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f527.svg new file mode 100644 index 0000000..73a06d0 --- /dev/null +++ b/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f527.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f6a7.svg b/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f6a7.svg new file mode 100644 index 0000000..a5d135c --- /dev/null +++ b/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f6a7.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f9f0.svg b/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f9f0.svg new file mode 100644 index 0000000..ae06531 --- /dev/null +++ b/assets/external/cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/1f9f0.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/external/cdn.jsdelivr.net/npm/wicked-good-xpath@1.3.0/dist/wgxpath.install.js b/assets/external/cdn.jsdelivr.net/npm/wicked-good-xpath@1.3.0/dist/wgxpath.install.js new file mode 100644 index 0000000..a983680 --- /dev/null +++ b/assets/external/cdn.jsdelivr.net/npm/wicked-good-xpath@1.3.0/dist/wgxpath.install.js @@ -0,0 +1,77 @@ +(function(){'use strict';var k=this; +function aa(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("call"))return"function"}else return"null";else if("function"== +b&&"undefined"==typeof a.call)return"object";return b}function l(a){return"string"==typeof a}function ba(a,b,c){return a.call.apply(a.bind,arguments)}function ca(a,b,c){if(!a)throw Error();if(2b?1:0};var ha=Array.prototype.indexOf?function(a,b,c){return Array.prototype.indexOf.call(a,b,c)}:function(a,b,c){c=null==c?0:0>c?Math.max(0,a.length+c):c;if(l(a))return l(b)&&1==b.length?a.indexOf(b,c):-1;for(;cc?null:l(a)?a.charAt(c):a[c]}function la(a){return Array.prototype.concat.apply(Array.prototype,arguments)}function ma(a,b,c){return 2>=arguments.length?Array.prototype.slice.call(a,b):Array.prototype.slice.call(a,b,c)};var u;a:{var na=k.navigator;if(na){var oa=na.userAgent;if(oa){u=oa;break a}}u=""};var pa=q(u,"Opera")||q(u,"OPR"),v=q(u,"Trident")||q(u,"MSIE"),qa=q(u,"Edge"),ra=q(u,"Gecko")&&!(q(u.toLowerCase(),"webkit")&&!q(u,"Edge"))&&!(q(u,"Trident")||q(u,"MSIE"))&&!q(u,"Edge"),sa=q(u.toLowerCase(),"webkit")&&!q(u,"Edge");function ta(){var a=k.document;return a?a.documentMode:void 0}var ua; +a:{var va="",wa=function(){var a=u;if(ra)return/rv\:([^\);]+)(\)|;)/.exec(a);if(qa)return/Edge\/([\d\.]+)/.exec(a);if(v)return/\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(a);if(sa)return/WebKit\/(\S+)/.exec(a);if(pa)return/(?:Version)[ \/]?(\S+)/.exec(a)}();wa&&(va=wa?wa[1]:"");if(v){var xa=ta();if(null!=xa&&xa>parseFloat(va)){ua=String(xa);break a}}ua=va}var ya={}; +function za(a){if(!ya[a]){for(var b=0,c=fa(String(ua)).split("."),d=fa(String(a)).split("."),e=Math.max(c.length,d.length),f=0;0==b&&f",4,2,function(a,b,c){return O(function(a,b){return a>b},a,b,c)});P("<=",4,2,function(a,b,c){return O(function(a,b){return a<=b},a,b,c)});P(">=",4,2,function(a,b,c){return O(function(a,b){return a>=b},a,b,c)});var Wa=P("=",3,2,function(a,b,c){return O(function(a,b){return a==b},a,b,c,!0)});P("!=",3,2,function(a,b,c){return O(function(a,b){return a!=b},a,b,c,!0)});P("and",2,2,function(a,b,c){return M(a,c)&&M(b,c)});P("or",1,2,function(a,b,c){return M(a,c)||M(b,c)});function Q(a,b,c){this.a=a;this.b=b||1;this.f=c||1};function Za(a,b){if(b.a.length&&4!=a.i)throw Error("Primary expression must evaluate to nodeset if filter has predicate(s).");n.call(this,a.i);this.c=a;this.h=b;this.g=a.g;this.b=a.b}m(Za);Za.prototype.a=function(a){a=this.c.a(a);return $a(this.h,a)};Za.prototype.toString=function(){var a;a="Filter:"+J(this.c);return a+=J(this.h)};function ab(a,b){if(b.lengtha.v)throw Error("Function "+a.j+" expects at most "+a.v+" arguments, "+b.length+" given");a.B&&r(b,function(b,d){if(4!=b.i)throw Error("Argument "+d+" to function "+a.j+" is not of type Nodeset: "+b);});n.call(this,a.i);this.h=a;this.c=b;Ua(this,a.g||ja(b,function(a){return a.g}));Va(this,a.D&&!b.length||a.C&&!!b.length||ja(b,function(a){return a.b}))}m(ab); +ab.prototype.a=function(a){return this.h.m.apply(null,la(a,this.c))};ab.prototype.toString=function(){var a="Function: "+this.h;if(this.c.length)var b=t(this.c,function(a,b){return a+J(b)},"Arguments:"),a=a+J(b);return a};function bb(a,b,c,d,e,f,g,h,p){this.j=a;this.i=b;this.g=c;this.D=d;this.C=e;this.m=f;this.A=g;this.v=void 0!==h?h:g;this.B=!!p}bb.prototype.toString=function(){return this.j};var cb={}; +function R(a,b,c,d,e,f,g,h){if(cb.hasOwnProperty(a))throw Error("Function already created: "+a+".");cb[a]=new bb(a,b,c,d,!1,e,f,g,h)}R("boolean",2,!1,!1,function(a,b){return M(b,a)},1);R("ceiling",1,!1,!1,function(a,b){return Math.ceil(K(b,a))},1);R("concat",3,!1,!1,function(a,b){return t(ma(arguments,1),function(b,d){return b+L(d,a)},"")},2,null);R("contains",2,!1,!1,function(a,b,c){return q(L(b,a),L(c,a))},2);R("count",1,!1,!1,function(a,b){return b.a(a).l},1,1,!0); +R("false",2,!1,!1,function(){return!1},0);R("floor",1,!1,!1,function(a,b){return Math.floor(K(b,a))},1);R("id",4,!1,!1,function(a,b){function c(a){if(w){var b=e.all[a];if(b){if(b.nodeType&&a==b.id)return b;if(b.length)return ka(b,function(b){return a==b.id})}return null}return e.getElementById(a)}var d=a.a,e=9==d.nodeType?d:d.ownerDocument,d=L(b,a).split(/\s+/),f=[];r(d,function(a){a=c(a);!a||0<=ha(f,a)||f.push(a)});f.sort(La);var g=new C;r(f,function(a){F(g,a)});return g},1); +R("lang",2,!1,!1,function(){return!1},1);R("last",1,!0,!1,function(a){if(1!=arguments.length)throw Error("Function last expects ()");return a.f},0);R("local-name",3,!1,!0,function(a,b){var c=b?Ra(b.a(a)):a.a;return c?c.localName||c.nodeName.toLowerCase():""},0,1,!0);R("name",3,!1,!0,function(a,b){var c=b?Ra(b.a(a)):a.a;return c?c.nodeName.toLowerCase():""},0,1,!0);R("namespace-uri",3,!0,!1,function(){return""},0,1,!0); +R("normalize-space",3,!1,!0,function(a,b){return(b?L(b,a):z(a.a)).replace(/[\s\xa0]+/g," ").replace(/^\s+|\s+$/g,"")},0,1);R("not",2,!1,!1,function(a,b){return!M(b,a)},1);R("number",1,!1,!0,function(a,b){return b?K(b,a):+z(a.a)},0,1);R("position",1,!0,!1,function(a){return a.b},0);R("round",1,!1,!1,function(a,b){return Math.round(K(b,a))},1);R("starts-with",2,!1,!1,function(a,b,c){b=L(b,a);a=L(c,a);return 0==b.lastIndexOf(a,0)},2);R("string",3,!1,!0,function(a,b){return b?L(b,a):z(a.a)},0,1); +R("string-length",1,!1,!0,function(a,b){return(b?L(b,a):z(a.a)).length},0,1);R("substring",3,!1,!1,function(a,b,c,d){c=K(c,a);if(isNaN(c)||Infinity==c||-Infinity==c)return"";d=d?K(d,a):Infinity;if(isNaN(d)||-Infinity===d)return"";c=Math.round(c)-1;var e=Math.max(c,0);a=L(b,a);return Infinity==d?a.substring(e):a.substring(e,c+Math.round(d))},2,3);R("substring-after",3,!1,!1,function(a,b,c){b=L(b,a);a=L(c,a);c=b.indexOf(a);return-1==c?"":b.substring(c+a.length)},2); +R("substring-before",3,!1,!1,function(a,b,c){b=L(b,a);a=L(c,a);a=b.indexOf(a);return-1==a?"":b.substring(0,a)},2);R("sum",1,!1,!1,function(a,b){for(var c=H(b.a(a)),d=0,e=I(c);e;e=I(c))d+=+z(e);return d},1,1,!0);R("translate",3,!1,!1,function(a,b,c,d){b=L(b,a);c=L(c,a);var e=L(d,a);a={};for(d=0;d]=|\s+|./g,hb=/^\s/;function S(a,b){return a.b[a.a+(b||0)]}function T(a){return a.b[a.a++]}function ib(a){return a.b.length<=a.a};function jb(a){n.call(this,3);this.c=a.substring(1,a.length-1)}m(jb);jb.prototype.a=function(){return this.c};jb.prototype.toString=function(){return"Literal: "+this.c};function E(a,b){this.j=a.toLowerCase();var c;c="*"==this.j?"*":"http://www.w3.org/1999/xhtml";this.c=b?b.toLowerCase():c}E.prototype.a=function(a){var b=a.nodeType;if(1!=b&&2!=b)return!1;b=void 0!==a.localName?a.localName:a.nodeName;return"*"!=this.j&&this.j!=b.toLowerCase()?!1:"*"==this.c?!0:this.c==(a.namespaceURI?a.namespaceURI.toLowerCase():"http://www.w3.org/1999/xhtml")};E.prototype.f=function(){return this.j}; +E.prototype.toString=function(){return"Name Test: "+("http://www.w3.org/1999/xhtml"==this.c?"":this.c+":")+this.j};function kb(a,b){n.call(this,a.i);this.h=a;this.c=b;this.g=a.g;this.b=a.b;if(1==this.c.length){var c=this.c[0];c.u||c.c!=lb||(c=c.o,"*"!=c.f()&&(this.f={name:c.f(),s:null}))}}m(kb);function mb(){n.call(this,4)}m(mb);mb.prototype.a=function(a){var b=new C;a=a.a;9==a.nodeType?F(b,a):F(b,a.ownerDocument);return b};mb.prototype.toString=function(){return"Root Helper Expression"};function nb(){n.call(this,4)}m(nb);nb.prototype.a=function(a){var b=new C;F(b,a.a);return b};nb.prototype.toString=function(){return"Context Helper Expression"}; +function ob(a){return"/"==a||"//"==a}kb.prototype.a=function(a){var b=this.h.a(a);if(!(b instanceof C))throw Error("Filter expression must evaluate to nodeset.");a=this.c;for(var c=0,d=a.length;ca.length)throw Error("Unclosed literal string");return new jb(a)} +function Hb(a){var b,c=[],d;if(ob(S(a.a))){b=T(a.a);d=S(a.a);if("/"==b&&(ib(a.a)||"."!=d&&".."!=d&&"@"!=d&&"*"!=d&&!/(?![0-9])[\w]/.test(d)))return new mb;d=new mb;W(a,"Missing next location step.");b=Ib(a,b);c.push(b)}else{a:{b=S(a.a);d=b.charAt(0);switch(d){case "$":throw Error("Variable reference not allowed in HTML XPath");case "(":T(a.a);b=Cb(a);W(a,'unclosed "("');Eb(a,")");break;case '"':case "'":b=Gb(a);break;default:if(isNaN(+b))if(!db(b)&&/(?![0-9])[\w]/.test(d)&&"("==S(a.a,1)){b=T(a.a); +b=cb[b]||null;T(a.a);for(d=[];")"!=S(a.a);){W(a,"Missing function argument list.");d.push(Cb(a));if(","!=S(a.a))break;T(a.a)}W(a,"Unclosed function argument list.");Fb(a);b=new ab(b,d)}else{b=null;break a}else b=new Ab(+T(a.a))}"["==S(a.a)&&(d=new sb(Jb(a)),b=new Za(b,d))}if(b)if(ob(S(a.a)))d=b;else return b;else b=Ib(a,"/"),d=new nb,c.push(b)}for(;ob(S(a.a));)b=T(a.a),W(a,"Missing next location step."),b=Ib(a,b),c.push(b);return new kb(d,c)} +function Ib(a,b){var c,d,e;if("/"!=b&&"//"!=b)throw Error('Step op should be "/" or "//"');if("."==S(a.a))return d=new U(yb,new G("node")),T(a.a),d;if(".."==S(a.a))return d=new U(xb,new G("node")),T(a.a),d;var f;if("@"==S(a.a))f=lb,T(a.a),W(a,"Missing attribute name");else if("::"==S(a.a,1)){if(!/(?![0-9])[\w]/.test(S(a.a).charAt(0)))throw Error("Bad token: "+T(a.a));c=T(a.a);f=wb[c]||null;if(!f)throw Error("No axis with name: "+c);T(a.a);W(a,"Missing node name")}else f=tb;c=S(a.a);if(/(?![0-9])[\w\*]/.test(c.charAt(0)))if("("== +S(a.a,1)){if(!db(c))throw Error("Invalid node type: "+c);c=T(a.a);if(!db(c))throw Error("Invalid type name: "+c);Eb(a,"(");W(a,"Bad nodetype");e=S(a.a).charAt(0);var g=null;if('"'==e||"'"==e)g=Gb(a);W(a,"Bad nodetype");Fb(a);c=new G(c,g)}else if(c=T(a.a),e=c.indexOf(":"),-1==e)c=new E(c);else{var g=c.substring(0,e),h;if("*"==g)h="*";else if(h=a.b(g),!h)throw Error("Namespace prefix not declared: "+g);c=c.substr(e+1);c=new E(c,h)}else throw Error("Bad token: "+T(a.a));e=new sb(Jb(a),f.a);return d|| +new U(f,c,e,"//"==b)}function Jb(a){for(var b=[];"["==S(a.a);){T(a.a);W(a,"Missing predicate expression.");var c=Cb(a);b.push(c);W(a,"Unclosed predicate expression.");Eb(a,"]")}return b}function Db(a){if("-"==S(a.a))return T(a.a),new zb(Db(a));var b=Hb(a);if("|"!=S(a.a))a=b;else{for(b=[b];"|"==T(a.a);)W(a,"Missing next union location path."),b.push(Hb(a));a.a.a--;a=new rb(b)}return a};function Kb(a){switch(a.nodeType){case 1:return ea(Lb,a);case 9:return Kb(a.documentElement);case 11:case 10:case 6:case 12:return Mb;default:return a.parentNode?Kb(a.parentNode):Mb}}function Mb(){return null}function Lb(a,b){if(a.prefix==b)return a.namespaceURI||"http://www.w3.org/1999/xhtml";var c=a.getAttributeNode("xmlns:"+b);return c&&c.specified?c.value||null:a.parentNode&&9!=a.parentNode.nodeType?Lb(a.parentNode,b):null};function Nb(a,b){if(!a.length)throw Error("Empty XPath expression.");var c=fb(a);if(ib(c))throw Error("Invalid XPath expression.");b?"function"==aa(b)||(b=da(b.lookupNamespaceURI,b)):b=function(){return null};var d=Cb(new Bb(c,b));if(!ib(c))throw Error("Bad token: "+T(c));this.evaluate=function(a,b){var c=d.a(new Q(a));return new Y(c,b)}} +function Y(a,b){if(0==b)if(a instanceof C)b=4;else if("string"==typeof a)b=2;else if("number"==typeof a)b=1;else if("boolean"==typeof a)b=3;else throw Error("Unexpected evaluation result.");if(2!=b&&1!=b&&3!=b&&!(a instanceof C))throw Error("value could not be converted to the specified type");this.resultType=b;var c;switch(b){case 2:this.stringValue=a instanceof C?Sa(a):""+a;break;case 1:this.numberValue=a instanceof C?+Sa(a):+a;break;case 3:this.booleanValue=a instanceof C?0=c.length?null:c[f++]};this.snapshotItem=function(a){if(6!=b&&7!=b)throw Error("snapshotItem called with wrong result type");return a>=c.length|| +0>a?null:c[a]}}Y.ANY_TYPE=0;Y.NUMBER_TYPE=1;Y.STRING_TYPE=2;Y.BOOLEAN_TYPE=3;Y.UNORDERED_NODE_ITERATOR_TYPE=4;Y.ORDERED_NODE_ITERATOR_TYPE=5;Y.UNORDERED_NODE_SNAPSHOT_TYPE=6;Y.ORDERED_NODE_SNAPSHOT_TYPE=7;Y.ANY_UNORDERED_NODE_TYPE=8;Y.FIRST_ORDERED_NODE_TYPE=9;function Ob(a){this.lookupNamespaceURI=Kb(a)} +function Pb(a,b){var c=a||k,d=c.Document&&c.Document.prototype||c.document;if(!d.evaluate||b)c.XPathResult=Y,d.evaluate=function(a,b,c,d){return(new Nb(a,c)).evaluate(b,d)},d.createExpression=function(a,b){return new Nb(a,b)},d.createNSResolver=function(a){return new Ob(a)}}var Qb=["wgxpath","install"],Z=k;Qb[0]in Z||!Z.execScript||Z.execScript("var "+Qb[0]);for(var Rb;Qb.length&&(Rb=Qb.shift());)Qb.length||void 0===Pb?Z[Rb]?Z=Z[Rb]:Z=Z[Rb]={}:Z[Rb]=Pb;}).call(this) diff --git a/assets/external/fonts.googleapis.com/css.49ea35f2.css b/assets/external/fonts.googleapis.com/css.49ea35f2.css new file mode 100644 index 0000000..8187a64 --- /dev/null +++ b/assets/external/fonts.googleapis.com/css.49ea35f2.css @@ -0,0 +1,594 @@ +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc3CsTKlA.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc-CsTKlA.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc2CsTKlA.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc5CsTKlA.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc1CsTKlA.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc0CsTKlA.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc6CsQ.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xFIzIFKw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xMIzIFKw.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xEIzIFKw.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xLIzIFKw.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xHIzIFKw.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xGIzIFKw.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xIIzI.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic3CsTKlA.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic-CsTKlA.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic2CsTKlA.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic5CsTKlA.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic1CsTKlA.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic0CsTKlA.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic6CsQ.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCRc4EsA.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fABc4EsA.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCBc4EsA.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBxc4EsA.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCxc4EsA.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fChc4EsA.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBBc4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu72xKOzY.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu5mxKOzY.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7mxKOzY.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4WxKOzY.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7WxKOzY.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7GxKOzY.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxK.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCRc4EsA.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfABc4EsA.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCBc4EsA.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBxc4EsA.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCxc4EsA.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfChc4EsA.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBBc4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEluUlYIw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEn-UlYIw.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEmOUlYIw.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtElOUlYIw.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEleUlYIw.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEm-Ul.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEluUlYIw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEn-UlYIw.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEmOUlYIw.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtElOUlYIw.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEleUlYIw.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto Mono'; + font-style: italic; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEm-Ul.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSV0mf0h.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSx0mf0h.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSt0mf0h.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSd0mf0h.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSZ0mf0h.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 400; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSh0mQ.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSV0mf0h.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSx0mf0h.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSt0mf0h.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSd0mf0h.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSZ0mf0h.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Roboto Mono'; + font-style: normal; + font-weight: 700; + font-display: fallback; + src: url(../fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSh0mQ.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc-CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc-CsTKlA.woff2 new file mode 100644 index 0000000..943c5a0 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc-CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc0CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc0CsTKlA.woff2 new file mode 100644 index 0000000..2bfc2ce Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc0CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc1CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc1CsTKlA.woff2 new file mode 100644 index 0000000..b2391b9 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc1CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc2CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc2CsTKlA.woff2 new file mode 100644 index 0000000..a4699c7 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc2CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc3CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc3CsTKlA.woff2 new file mode 100644 index 0000000..bfcc76f Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc3CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc5CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc5CsTKlA.woff2 new file mode 100644 index 0000000..d4ec189 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc5CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc6CsQ.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc6CsQ.woff2 new file mode 100644 index 0000000..22c57b0 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc6CsQ.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic-CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic-CsTKlA.woff2 new file mode 100644 index 0000000..d2f30b5 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic-CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic0CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic0CsTKlA.woff2 new file mode 100644 index 0000000..c88b8ae Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic0CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic1CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic1CsTKlA.woff2 new file mode 100644 index 0000000..6363b1c Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic1CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic2CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic2CsTKlA.woff2 new file mode 100644 index 0000000..dd5a4a2 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic2CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic3CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic3CsTKlA.woff2 new file mode 100644 index 0000000..6abf54d Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic3CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic5CsTKlA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic5CsTKlA.woff2 new file mode 100644 index 0000000..c8091bc Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic5CsTKlA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic6CsQ.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic6CsQ.woff2 new file mode 100644 index 0000000..a56a6ed Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic6CsQ.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xEIzIFKw.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xEIzIFKw.woff2 new file mode 100644 index 0000000..508baef Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xEIzIFKw.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xFIzIFKw.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xFIzIFKw.woff2 new file mode 100644 index 0000000..9213da0 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xFIzIFKw.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xGIzIFKw.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xGIzIFKw.woff2 new file mode 100644 index 0000000..ef920e5 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xGIzIFKw.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xHIzIFKw.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xHIzIFKw.woff2 new file mode 100644 index 0000000..9a378af Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xHIzIFKw.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xIIzI.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xIIzI.woff2 new file mode 100644 index 0000000..e1b7a79 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xIIzI.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xLIzIFKw.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xLIzIFKw.woff2 new file mode 100644 index 0000000..e0d3c43 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xLIzIFKw.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xMIzIFKw.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xMIzIFKw.woff2 new file mode 100644 index 0000000..dd587a2 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xMIzIFKw.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fABc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fABc4EsA.woff2 new file mode 100644 index 0000000..9d7fb7f Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fABc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBBc4.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBBc4.woff2 new file mode 100644 index 0000000..6068138 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBBc4.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBxc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBxc4EsA.woff2 new file mode 100644 index 0000000..b289f00 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBxc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCBc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCBc4EsA.woff2 new file mode 100644 index 0000000..87711c0 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCBc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCRc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCRc4EsA.woff2 new file mode 100644 index 0000000..0f6e60b Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCRc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fChc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fChc4EsA.woff2 new file mode 100644 index 0000000..91231c9 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fChc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCxc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCxc4EsA.woff2 new file mode 100644 index 0000000..c009987 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCxc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfABc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfABc4EsA.woff2 new file mode 100644 index 0000000..1bb7737 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfABc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBBc4.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBBc4.woff2 new file mode 100644 index 0000000..771fbec Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBBc4.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBxc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBxc4EsA.woff2 new file mode 100644 index 0000000..cb9bfa7 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBxc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCBc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCBc4EsA.woff2 new file mode 100644 index 0000000..a0d68e2 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCBc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCRc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCRc4EsA.woff2 new file mode 100644 index 0000000..6399552 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCRc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfChc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfChc4EsA.woff2 new file mode 100644 index 0000000..94ab5fb Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfChc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCxc4EsA.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCxc4EsA.woff2 new file mode 100644 index 0000000..3c45011 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCxc4EsA.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4WxKOzY.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4WxKOzY.woff2 new file mode 100644 index 0000000..fc71d94 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4WxKOzY.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxK.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxK.woff2 new file mode 100644 index 0000000..020729e Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxK.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu5mxKOzY.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu5mxKOzY.woff2 new file mode 100644 index 0000000..47da362 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu5mxKOzY.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu72xKOzY.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu72xKOzY.woff2 new file mode 100644 index 0000000..22ddee9 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu72xKOzY.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7GxKOzY.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7GxKOzY.woff2 new file mode 100644 index 0000000..8a8de61 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7GxKOzY.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7WxKOzY.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7WxKOzY.woff2 new file mode 100644 index 0000000..6284d2e Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7WxKOzY.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7mxKOzY.woff2 b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7mxKOzY.woff2 new file mode 100644 index 0000000..72ce0e9 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7mxKOzY.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSV0mf0h.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSV0mf0h.woff2 new file mode 100644 index 0000000..022274d Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSV0mf0h.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSZ0mf0h.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSZ0mf0h.woff2 new file mode 100644 index 0000000..48edd1b Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSZ0mf0h.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSd0mf0h.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSd0mf0h.woff2 new file mode 100644 index 0000000..cb41535 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSd0mf0h.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSh0mQ.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSh0mQ.woff2 new file mode 100644 index 0000000..1d988a3 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSh0mQ.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSt0mf0h.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSt0mf0h.woff2 new file mode 100644 index 0000000..11e6a46 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSt0mf0h.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSx0mf0h.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSx0mf0h.woff2 new file mode 100644 index 0000000..50fb8e7 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSx0mf0h.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtElOUlYIw.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtElOUlYIw.woff2 new file mode 100644 index 0000000..1f1c97f Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtElOUlYIw.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEleUlYIw.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEleUlYIw.woff2 new file mode 100644 index 0000000..1623005 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEleUlYIw.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEluUlYIw.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEluUlYIw.woff2 new file mode 100644 index 0000000..6f232c3 Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEluUlYIw.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEm-Ul.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEm-Ul.woff2 new file mode 100644 index 0000000..a3e5aef Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEm-Ul.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEmOUlYIw.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEmOUlYIw.woff2 new file mode 100644 index 0000000..f73f27d Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEmOUlYIw.woff2 differ diff --git a/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEn-UlYIw.woff2 b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEn-UlYIw.woff2 new file mode 100644 index 0000000..135d06e Binary files /dev/null and b/assets/external/fonts.gstatic.com/s/robotomono/v23/L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEn-UlYIw.woff2 differ diff --git a/assets/external/img.icons8.com/ios-filled/50/000000/info.png b/assets/external/img.icons8.com/ios-filled/50/000000/info.png new file mode 100644 index 0000000..444de00 Binary files /dev/null and b/assets/external/img.icons8.com/ios-filled/50/000000/info.png differ diff --git a/assets/external/img.icons8.com/ios-filled/50/000000/warning-shield.png b/assets/external/img.icons8.com/ios-filled/50/000000/warning-shield.png new file mode 100644 index 0000000..4df652f Binary files /dev/null and b/assets/external/img.icons8.com/ios-filled/50/000000/warning-shield.png differ diff --git a/assets/external/media.www.kent.ac.uk/se/11746/Alex-Freitas_400x400_inline.webp b/assets/external/media.www.kent.ac.uk/se/11746/Alex-Freitas_400x400_inline.webp new file mode 100644 index 0000000..ab42c11 Binary files /dev/null and b/assets/external/media.www.kent.ac.uk/se/11746/Alex-Freitas_400x400_inline.webp differ diff --git a/assets/external/polyfill.io/v3/polyfill.min.7596a0b8.js b/assets/external/polyfill.io/v3/polyfill.min.7596a0b8.js new file mode 100644 index 0000000..c80c2f4 --- /dev/null +++ b/assets/external/polyfill.io/v3/polyfill.min.7596a0b8.js @@ -0,0 +1,5 @@ +/* + * Polyfill service v3.111.0 + * Disable minification (remove `.min` from URL path) for more info +*/ + diff --git a/assets/external/unpkg.com/@lottiefiles/lottie-player@latest/dist/lottie-player.js b/assets/external/unpkg.com/@lottiefiles/lottie-player@latest/dist/lottie-player.js new file mode 100644 index 0000000..bb57e8c --- /dev/null +++ b/assets/external/unpkg.com/@lottiefiles/lottie-player@latest/dist/lottie-player.js @@ -0,0 +1,77 @@ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self)["lottie-player"]={})}(this,(function(exports){"use strict";function _asyncIterator(t){var e,r,i,s=2;for("undefined"!=typeof Symbol&&(r=Symbol.asyncIterator,i=Symbol.iterator);s--;){if(r&&null!=(e=t[r]))return e.call(t);if(i&&null!=(e=t[i]))return new AsyncFromSyncIterator(e.call(t));r="@@asyncIterator",i="@@iterator"}throw new TypeError("Object is not async iterable")}function AsyncFromSyncIterator(t){function e(t){if(Object(t)!==t)return Promise.reject(new TypeError(t+" is not an object."));var e=t.done;return Promise.resolve(t.value).then((function(t){return{value:t,done:e}}))}return AsyncFromSyncIterator=function(t){this.s=t,this.n=t.next},AsyncFromSyncIterator.prototype={s:null,n:null,next:function(){return e(this.n.apply(this.s,arguments))},return:function(t){var r=this.s.return;return void 0===r?Promise.resolve({value:t,done:!0}):e(r.apply(this.s,arguments))},throw:function(t){var r=this.s.return;return void 0===r?Promise.reject(t):e(r.apply(this.s,arguments))}},new AsyncFromSyncIterator(t)}var REACT_ELEMENT_TYPE;function _jsx(t,e,r,i){REACT_ELEMENT_TYPE||(REACT_ELEMENT_TYPE="function"==typeof Symbol&&Symbol.for&&Symbol.for("react.element")||60103);var s=t&&t.defaultProps,a=arguments.length-3;if(e||0===a||(e={children:void 0}),1===a)e.children=i;else if(a>1){for(var n=new Array(a),o=0;o]+)>/g,(function(t,e){return"$"+a[e]})))}if("function"==typeof s){var n=this;return t[Symbol.replace].call(this,r,(function(){var t=arguments;return"object"!=typeof t[t.length-1]&&(t=[].slice.call(t)).push(i(t,n)),s.apply(this,t)}))}return t[Symbol.replace].call(this,r,s)},_wrapRegExp.apply(this,arguments)}function _AwaitValue(t){this.wrapped=t}function _AsyncGenerator(t){var e,r;function i(e,r){try{var a=t[e](r),n=a.value,o=n instanceof _AwaitValue;Promise.resolve(o?n.wrapped:n).then((function(t){o?i("return"===e?"return":"next",t):s(a.done?"return":"normal",t)}),(function(t){i("throw",t)}))}catch(t){s("throw",t)}}function s(t,s){switch(t){case"return":e.resolve({value:s,done:!0});break;case"throw":e.reject(s);break;default:e.resolve({value:s,done:!1})}(e=e.next)?i(e.key,e.arg):r=null}this._invoke=function(t,s){return new Promise((function(a,n){var o={key:t,arg:s,resolve:a,reject:n,next:null};r?r=r.next=o:(e=r=o,i(t,s))}))},"function"!=typeof t.return&&(this.return=void 0)}function _wrapAsyncGenerator(t){return function(){return new _AsyncGenerator(t.apply(this,arguments))}}function _awaitAsyncGenerator(t){return new _AwaitValue(t)}function _asyncGeneratorDelegate(t,e){var r={},i=!1;function s(r,s){return i=!0,s=new Promise((function(e){e(t[r](s))})),{done:!1,value:e(s)}}return r["undefined"!=typeof Symbol&&Symbol.iterator||"@@iterator"]=function(){return this},r.next=function(t){return i?(i=!1,t):s("next",t)},"function"==typeof t.throw&&(r.throw=function(t){if(i)throw i=!1,t;return s("throw",t)}),"function"==typeof t.return&&(r.return=function(t){return i?(i=!1,t):s("return",t)}),r}function asyncGeneratorStep(t,e,r,i,s,a,n){try{var o=t[a](n),h=o.value}catch(t){return void r(t)}o.done?e(h):Promise.resolve(h).then(i,s)}function _asyncToGenerator(t){return function(){var e=this,r=arguments;return new Promise((function(i,s){var a=t.apply(e,r);function n(t){asyncGeneratorStep(a,i,s,n,o,"next",t)}function o(t){asyncGeneratorStep(a,i,s,n,o,"throw",t)}n(void 0)}))}}function _classCallCheck(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function _defineProperties(t,e){for(var r=0;r=0||(s[r]=t[r]);return s}function _objectWithoutProperties(t,e){if(null==t)return{};var r,i,s=_objectWithoutPropertiesLoose(t,e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(t,r)&&(s[r]=t[r])}return s}function _assertThisInitialized(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}function _possibleConstructorReturn(t,e){if(e&&("object"==typeof e||"function"==typeof e))return e;if(void 0!==e)throw new TypeError("Derived constructors may only return object or undefined");return _assertThisInitialized(t)}function _createSuper(t){var e=_isNativeReflectConstruct();return function(){var r,i=_getPrototypeOf(t);if(e){var s=_getPrototypeOf(this).constructor;r=Reflect.construct(i,arguments,s)}else r=i.apply(this,arguments);return _possibleConstructorReturn(this,r)}}function _superPropBase(t,e){for(;!Object.prototype.hasOwnProperty.call(t,e)&&null!==(t=_getPrototypeOf(t)););return t}function _get(){return _get="undefined"!=typeof Reflect&&Reflect.get?Reflect.get:function(t,e,r){var i=_superPropBase(t,e);if(i){var s=Object.getOwnPropertyDescriptor(i,e);return s.get?s.get.call(arguments.length<3?t:r):s.value}},_get.apply(this,arguments)}function set(t,e,r,i){return set="undefined"!=typeof Reflect&&Reflect.set?Reflect.set:function(t,e,r,i){var s,a=_superPropBase(t,e);if(a){if((s=Object.getOwnPropertyDescriptor(a,e)).set)return s.set.call(i,r),!0;if(!s.writable)return!1}if(s=Object.getOwnPropertyDescriptor(i,e)){if(!s.writable)return!1;s.value=r,Object.defineProperty(i,e,s)}else _defineProperty(i,e,r);return!0},set(t,e,r,i)}function _set(t,e,r,i,s){if(!set(t,e,r,i||t)&&s)throw new Error("failed to set property");return r}function _taggedTemplateLiteral(t,e){return e||(e=t.slice(0)),Object.freeze(Object.defineProperties(t,{raw:{value:Object.freeze(e)}}))}function _taggedTemplateLiteralLoose(t,e){return e||(e=t.slice(0)),t.raw=e,t}function _readOnlyError(t){throw new TypeError('"'+t+'" is read-only')}function _writeOnlyError(t){throw new TypeError('"'+t+'" is write-only')}function _classNameTDZError(t){throw new Error('Class "'+t+'" cannot be referenced in computed property keys.')}function _temporalUndefined(){}function _tdz(t){throw new ReferenceError(t+" is not defined - temporal dead zone")}function _temporalRef(t,e){return t===_temporalUndefined?_tdz(e):t}function _slicedToArray(t,e){return _arrayWithHoles(t)||_iterableToArrayLimit(t,e)||_unsupportedIterableToArray(t,e)||_nonIterableRest()}function _slicedToArrayLoose(t,e){return _arrayWithHoles(t)||_iterableToArrayLimitLoose(t,e)||_unsupportedIterableToArray(t,e)||_nonIterableRest()}function _toArray(t){return _arrayWithHoles(t)||_iterableToArray(t)||_unsupportedIterableToArray(t)||_nonIterableRest()}function _toConsumableArray(t){return _arrayWithoutHoles(t)||_iterableToArray(t)||_unsupportedIterableToArray(t)||_nonIterableSpread()}function _arrayWithoutHoles(t){if(Array.isArray(t))return _arrayLikeToArray(t)}function _arrayWithHoles(t){if(Array.isArray(t))return t}function _maybeArrayLike(t,e,r){if(e&&!Array.isArray(e)&&"number"==typeof e.length){var i=e.length;return _arrayLikeToArray(e,void 0!==r&&rt.length)&&(e=t.length);for(var r=0,i=new Array(e);r=t.length?{done:!0}:{done:!1,value:t[i++]}},e:function(t){throw t},f:s}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,n=!0,o=!1;return{s:function(){r=r.call(t)},n:function(){var t=r.next();return n=t.done,t},e:function(t){o=!0,a=t},f:function(){try{n||null==r.return||r.return()}finally{if(o)throw a}}}}function _createForOfIteratorHelperLoose(t,e){var r="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(r)return(r=r.call(t)).next.bind(r);if(Array.isArray(t)||(r=_unsupportedIterableToArray(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var i=0;return function(){return i>=t.length?{done:!0}:{done:!1,value:t[i++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _skipFirstGeneratorNext(t){return function(){var e=t.apply(this,arguments);return e.next(),e}}function _toPrimitive(t,e){if("object"!=typeof t||null===t)return t;var r=t[Symbol.toPrimitive];if(void 0!==r){var i=r.call(t,e||"default");if("object"!=typeof i)return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}function _toPropertyKey(t){var e=_toPrimitive(t,"string");return"symbol"==typeof e?e:String(e)}function _initializerWarningHelper(t,e){throw new Error("Decorating class property failed. Please ensure that proposal-class-properties is enabled and runs after the decorators transform.")}function _initializerDefineProperty(t,e,r,i){r&&Object.defineProperty(t,e,{enumerable:r.enumerable,configurable:r.configurable,writable:r.writable,value:r.initializer?r.initializer.call(i):void 0})}function _applyDecoratedDescriptor(t,e,r,i,s){var a={};return Object.keys(i).forEach((function(t){a[t]=i[t]})),a.enumerable=!!a.enumerable,a.configurable=!!a.configurable,("value"in a||a.initializer)&&(a.writable=!0),a=r.slice().reverse().reduce((function(r,i){return i(t,e,r)||r}),a),s&&void 0!==a.initializer&&(a.value=a.initializer?a.initializer.call(s):void 0,a.initializer=void 0),void 0===a.initializer&&(Object.defineProperty(t,e,a),a=null),a}_AsyncGenerator.prototype["function"==typeof Symbol&&Symbol.asyncIterator||"@@asyncIterator"]=function(){return this},_AsyncGenerator.prototype.next=function(t){return this._invoke("next",t)},_AsyncGenerator.prototype.throw=function(t){return this._invoke("throw",t)},_AsyncGenerator.prototype.return=function(t){return this._invoke("return",t)};var id=0;function _classPrivateFieldLooseKey(t){return"__private_"+id+++"_"+t}function _classPrivateFieldLooseBase(t,e){if(!Object.prototype.hasOwnProperty.call(t,e))throw new TypeError("attempted to use private field on non-instance");return t}function _classPrivateFieldGet(t,e){return _classApplyDescriptorGet(t,_classExtractFieldDescriptor(t,e,"get"))}function _classPrivateFieldSet(t,e,r){return _classApplyDescriptorSet(t,_classExtractFieldDescriptor(t,e,"set"),r),r}function _classPrivateFieldDestructureSet(t,e){return _classApplyDescriptorDestructureSet(t,_classExtractFieldDescriptor(t,e,"set"))}function _classExtractFieldDescriptor(t,e,r){if(!e.has(t))throw new TypeError("attempted to "+r+" private field on non-instance");return e.get(t)}function _classStaticPrivateFieldSpecGet(t,e,r){return _classCheckPrivateStaticAccess(t,e),_classCheckPrivateStaticFieldDescriptor(r,"get"),_classApplyDescriptorGet(t,r)}function _classStaticPrivateFieldSpecSet(t,e,r,i){return _classCheckPrivateStaticAccess(t,e),_classCheckPrivateStaticFieldDescriptor(r,"set"),_classApplyDescriptorSet(t,r,i),i}function _classStaticPrivateMethodGet(t,e,r){return _classCheckPrivateStaticAccess(t,e),r}function _classStaticPrivateMethodSet(){throw new TypeError("attempted to set read only static private field")}function _classApplyDescriptorGet(t,e){return e.get?e.get.call(t):e.value}function _classApplyDescriptorSet(t,e,r){if(e.set)e.set.call(t,r);else{if(!e.writable)throw new TypeError("attempted to set read only private field");e.value=r}}function _classApplyDescriptorDestructureSet(t,e){if(e.set)return"__destrObj"in e||(e.__destrObj={set value(r){e.set.call(t,r)}}),e.__destrObj;if(!e.writable)throw new TypeError("attempted to set read only private field");return e}function _classStaticPrivateFieldDestructureSet(t,e,r){return _classCheckPrivateStaticAccess(t,e),_classCheckPrivateStaticFieldDescriptor(r,"set"),_classApplyDescriptorDestructureSet(t,r)}function _classCheckPrivateStaticAccess(t,e){if(t!==e)throw new TypeError("Private static access of wrong provenance")}function _classCheckPrivateStaticFieldDescriptor(t,e){if(void 0===t)throw new TypeError("attempted to "+e+" private static field before its declaration")}function _decorate(t,e,r,i){var s=_getDecoratorsApi();if(i)for(var a=0;a=0;a--){var n=e[t.placement];n.splice(n.indexOf(t.key),1);var o=this.fromElementDescriptor(t),h=this.toElementFinisherExtras((0,s[a])(o)||o);t=h.element,this.addElementPlacement(t,e),h.finisher&&i.push(h.finisher);var l=h.extras;if(l){for(var p=0;p=0;i--){var s=this.fromClassDescriptor(t),a=this.toClassDescriptor((0,e[i])(s)||s);if(void 0!==a.finisher&&r.push(a.finisher),void 0!==a.elements){t=a.elements;for(var n=0;n=0;o--)(s=t[o])&&(n=(a<3?s(n):a>3?s(e,r,n):s(e,r))||n);return a>3&&n&&Object.defineProperty(e,r,n),n}function __param(t,e){return function(r,i){e(r,i,t)}}function __metadata(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)}function __awaiter(t,e,r,i){return new(r||(r=Promise))((function(s,a){function n(t){try{h(i.next(t))}catch(t){a(t)}}function o(t){try{h(i.throw(t))}catch(t){a(t)}}function h(t){var e;t.done?s(t.value):(e=t.value,e instanceof r?e:new r((function(t){t(e)}))).then(n,o)}h((i=i.apply(t,e||[])).next())}))}function __generator(t,e){var r,i,s,a,n={label:0,sent:function(){if(1&s[0])throw s[1];return s[1]},trys:[],ops:[]};return a={next:o(0),throw:o(1),return:o(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function o(a){return function(o){return function(a){if(r)throw new TypeError("Generator is already executing.");for(;n;)try{if(r=1,i&&(s=2&a[0]?i.return:a[0]?i.throw||((s=i.return)&&s.call(i),0):i.next)&&!(s=s.call(i,a[1])).done)return s;switch(i=0,s&&(a=[2&a[0],s.value]),a[0]){case 0:case 1:s=a;break;case 4:return n.label++,{value:a[1],done:!1};case 5:n.label++,i=a[1],a=[0];continue;case 7:a=n.ops.pop(),n.trys.pop();continue;default:if(!(s=n.trys,(s=s.length>0&&s[s.length-1])||6!==a[0]&&2!==a[0])){n=0;continue}if(3===a[0]&&(!s||a[1]>s[0]&&a[1]=t.length&&(t=void 0),{value:t&&t[i++],done:!t}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}function __read(t,e){var r="function"==typeof Symbol&&t[Symbol.iterator];if(!r)return t;var i,s,a=r.call(t),n=[];try{for(;(void 0===e||e-- >0)&&!(i=a.next()).done;)n.push(i.value)}catch(t){s={error:t}}finally{try{i&&!i.done&&(r=a.return)&&r.call(a)}finally{if(s)throw s.error}}return n}function __spread(){for(var t=[],e=0;e1||o(t,e)}))})}function o(t,e){try{!function(t){t.value instanceof __await?Promise.resolve(t.value.v).then(h,l):p(a[0][2],t)}(s[t](e))}catch(t){p(a[0][3],t)}}function h(t){o("next",t)}function l(t){o("throw",t)}function p(t,e){t(e),a.shift(),a.length&&o(a[0][0],a[0][1])}}function __asyncDelegator(t){var e,r;return e={},i("next"),i("throw",(function(t){throw t})),i("return"),e[Symbol.iterator]=function(){return this},e;function i(i,s){e[i]=t[i]?function(e){return(r=!r)?{value:__await(t[i](e)),done:"return"===i}:s?s(e):e}:s}}function __asyncValues(t){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var e,r=t[Symbol.asyncIterator];return r?r.call(t):(t="function"==typeof __values?__values(t):t[Symbol.iterator](),e={},i("next"),i("throw"),i("return"),e[Symbol.asyncIterator]=function(){return this},e);function i(r){e[r]=t[r]&&function(e){return new Promise((function(i,s){(function(t,e,r,i){Promise.resolve(i).then((function(e){t({value:e,done:r})}),e)})(i,s,(e=t[r](e)).done,e.value)}))}}}function __makeTemplateObject(t,e){return Object.defineProperty?Object.defineProperty(t,"raw",{value:e}):t.raw=e,t}var __setModuleDefault=Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e};function __importStar(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)"default"!==r&&Object.prototype.hasOwnProperty.call(t,r)&&__createBinding(e,t,r);return __setModuleDefault(e,t),e}function __importDefault(t){return t&&t.__esModule?t:{default:t}}function __classPrivateFieldGet(t,e,r,i){if("a"===r&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!i:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?i:"a"===r?i.call(t):i?i.value:e.get(t)}function __classPrivateFieldSet(t,e,r,i,s){if("m"===i)throw new TypeError("Private method is not writable");if("a"===i&&!s)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof e?t!==e||!s:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===i?s.call(t,r):s?s.value=r:e.set(t,r),r +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */}var t$3=window.ShadowRoot&&(void 0===window.ShadyCSS||window.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,e$8=Symbol(),n$5=new Map;class s$3{constructor(t,e){if(this._$cssResult$=!0,e!==e$8)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t}get styleSheet(){var t=n$5.get(this.cssText);return t$3&&void 0===t&&(n$5.set(this.cssText,t=new CSSStyleSheet),t.replaceSync(this.cssText)),t}toString(){return this.cssText}}var o$5=t=>new s$3("string"==typeof t?t:t+"",e$8),r$3=function(t){for(var e=arguments.length,r=new Array(e>1?e-1:0),i=1;ie+(t=>{if(!0===t._$cssResult$)return t.cssText;if("number"==typeof t)return t;throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(r)+t[i+1]),t[0]);return new s$3(s,e$8)},i$3=(t,e)=>{t$3?t.adoptedStyleSheets=e.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet)):e.forEach((e=>{var r=document.createElement("style"),i=window.litNonce;void 0!==i&&r.setAttribute("nonce",i),r.textContent=e.cssText,t.appendChild(r)}))},S$1=t$3?t=>t:t=>t instanceof CSSStyleSheet?(t=>{var e="";for(var r of t.cssRules)e+=r.cssText;return o$5(e)})(t):t +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */,s$2,e$7=window.trustedTypes,r$2=e$7?e$7.emptyScript:"",h$2=window.reactiveElementPolyfillSupport,o$4={toAttribute(t,e){switch(e){case Boolean:t=t?r$2:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){var r=t;switch(e){case Boolean:r=null!==t;break;case Number:r=null===t?null:Number(t);break;case Object:case Array:try{r=JSON.parse(t)}catch(t){r=null}}return r}},n$4=(t,e)=>e!==t&&(e==e||t==t),l$3={attribute:!0,type:String,converter:o$4,reflect:!1,hasChanged:n$4},t$2;class a$1 extends HTMLElement{constructor(){super(),this._$Et=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Ei=null,this.o()}static addInitializer(t){var e;null!==(e=this.l)&&void 0!==e||(this.l=[]),this.l.push(t)}static get observedAttributes(){this.finalize();var t=[];return this.elementProperties.forEach(((e,r)=>{var i=this._$Eh(r,e);void 0!==i&&(this._$Eu.set(i,r),t.push(i))})),t}static createProperty(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:l$3;if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){var r="symbol"==typeof t?Symbol():"__"+t,i=this.getPropertyDescriptor(t,r,e);void 0!==i&&Object.defineProperty(this.prototype,t,i)}}static getPropertyDescriptor(t,e,r){return{get(){return this[e]},set(i){var s=this[t];this[e]=i,this.requestUpdate(t,s,r)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||l$3}static finalize(){if(this.hasOwnProperty("finalized"))return!1;this.finalized=!0;var t=Object.getPrototypeOf(this);if(t.finalize(),this.elementProperties=new Map(t.elementProperties),this._$Eu=new Map,this.hasOwnProperty("properties")){var e=this.properties,r=[...Object.getOwnPropertyNames(e),...Object.getOwnPropertySymbols(e)];for(var i of r)this.createProperty(i,e[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}static finalizeStyles(t){var e=[];if(Array.isArray(t)){var r=new Set(t.flat(1/0).reverse());for(var i of r)e.unshift(S$1(i))}else void 0!==t&&e.push(S$1(t));return e}static _$Eh(t,e){var r=e.attribute;return!1===r?void 0:"string"==typeof r?r:"string"==typeof t?t.toLowerCase():void 0}o(){var t;this._$Ep=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$Em(),this.requestUpdate(),null===(t=this.constructor.l)||void 0===t||t.forEach((t=>t(this)))}addController(t){var e,r;(null!==(e=this._$Eg)&&void 0!==e?e:this._$Eg=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(r=t.hostConnected)||void 0===r||r.call(t))}removeController(t){var e;null===(e=this._$Eg)||void 0===e||e.splice(this._$Eg.indexOf(t)>>>0,1)}_$Em(){this.constructor.elementProperties.forEach(((t,e)=>{this.hasOwnProperty(e)&&(this._$Et.set(e,this[e]),delete this[e])}))}createRenderRoot(){var t,e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return i$3(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$Eg)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)}))}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$Eg)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)}))}attributeChangedCallback(t,e,r){this._$AK(t,r)}_$ES(t,e){var r,i,s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:l$3,a=this.constructor._$Eh(t,s);if(void 0!==a&&!0===s.reflect){var n=(null!==(i=null===(r=s.converter)||void 0===r?void 0:r.toAttribute)&&void 0!==i?i:o$4.toAttribute)(e,s.type);this._$Ei=t,null==n?this.removeAttribute(a):this.setAttribute(a,n),this._$Ei=null}}_$AK(t,e){var r,i,s,a=this.constructor,n=a._$Eu.get(t);if(void 0!==n&&this._$Ei!==n){var o=a.getPropertyOptions(n),h=o.converter,l=null!==(s=null!==(i=null===(r=h)||void 0===r?void 0:r.fromAttribute)&&void 0!==i?i:"function"==typeof h?h:null)&&void 0!==s?s:o$4.fromAttribute;this._$Ei=n,this[n]=l(e,o.type),this._$Ei=null}}requestUpdate(t,e,r){var i=!0;void 0!==t&&(((r=r||this.constructor.getPropertyOptions(t)).hasChanged||n$4)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===r.reflect&&this._$Ei!==t&&(void 0===this._$E_&&(this._$E_=new Map),this._$E_.set(t,r))):i=!1),!this.isUpdatePending&&i&&(this._$Ep=this._$EC())}_$EC(){var t=this;return _asyncToGenerator((function*(){t.isUpdatePending=!0;try{yield t._$Ep}catch(e){Promise.reject(e)}var e=t.scheduleUpdate();return null!=e&&(yield e),!t.isUpdatePending}))()}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(this.isUpdatePending){this.hasUpdated,this._$Et&&(this._$Et.forEach(((t,e)=>this[e]=t)),this._$Et=void 0);var e=!1,r=this._$AL;try{(e=this.shouldUpdate(r))?(this.willUpdate(r),null===(t=this._$Eg)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)})),this.update(r)):this._$EU()}catch(t){throw e=!1,this._$EU(),t}e&&this._$AE(r)}}willUpdate(t){}_$AE(t){var e;null===(e=this._$Eg)||void 0===e||e.forEach((t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EU(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$Ep}shouldUpdate(t){return!0}update(t){void 0!==this._$E_&&(this._$E_.forEach(((t,e)=>this._$ES(e,this[e],t))),this._$E_=void 0),this._$EU()}updated(t){}firstUpdated(t){}}a$1.finalized=!0,a$1.elementProperties=new Map,a$1.elementStyles=[],a$1.shadowRootOptions={mode:"open"},null==h$2||h$2({ReactiveElement:a$1}),(null!==(s$2=globalThis.reactiveElementVersions)&&void 0!==s$2?s$2:globalThis.reactiveElementVersions=[]).push("1.2.1");var i$2=globalThis.trustedTypes,s$1=i$2?i$2.createPolicy("lit-html",{createHTML:t=>t}):void 0,e$6="lit$".concat((Math.random()+"").slice(9),"$"),o$3="?"+e$6,n$3="<".concat(o$3,">"),l$2=document,h$1=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";return l$2.createComment(t)},r$1=t=>null===t||"object"!=typeof t&&"function"!=typeof t,d=Array.isArray,u=t=>{var e;return d(t)||"function"==typeof(null===(e=t)||void 0===e?void 0:e[Symbol.iterator])},c=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,v=/-->/g,a=/>/g,f=/>|[ \n \r](?:([^\s"'>=/]+)([ \n \r]*=[ \n \r]*(?:[^ \n \r"'`<>=]|("|')|))|$)/g,_=/'/g,m=/"/g,g=/^(?:script|style|textarea)$/i,p=t=>function(e){for(var r=arguments.length,i=new Array(r>1?r-1:0),s=1;s{var i,s,a=null!==(i=null==r?void 0:r.renderBefore)&&void 0!==i?i:e,n=a._$litPart$;if(void 0===n){var o=null!==(s=null==r?void 0:r.renderBefore)&&void 0!==s?s:null;a._$litPart$=n=new N(e.insertBefore(h$1(),o),o,void 0,null!=r?r:{})}return n._$AI(t),n},A=l$2.createTreeWalker(l$2,129,null,!1),C=(t,e)=>{for(var r,i=t.length-1,s=[],n=2===e?"":"",o=c,h=0;h"===u[0]?(o=null!=r?r:c,d=-1):void 0===u[1]?d=-2:(d=o.lastIndex-u[2].length,p=u[1],o=void 0===u[3]?f:'"'===u[3]?m:_):o===m||o===_?o=f:o===v||o===a?o=c:(o=f,r=void 0);var b=o===f&&t[h+1].startsWith("/>")?" ":"";n+=o===c?l+n$3:d>=0?(s.push(p),l.slice(0,d)+"$lit$"+l.slice(d)+e$6+b):l+e$6+(-2===d?(s.push(void 0),h):b)}var P=n+(t[i]||"")+(2===e?"":"");if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return[void 0!==s$1?s$1.createHTML(P):P,s]};class E{constructor(t,e){var r,{strings:i,_$litType$:s}=t;this.parts=[];var a=0,n=0,o=i.length-1,h=this.parts,[l,p]=C(i,s);if(this.el=E.createElement(l,e),A.currentNode=this.el.content,2===s){var c=this.el.content,f=c.firstChild;f.remove(),c.append(...f.childNodes)}for(;null!==(r=A.nextNode())&&h.length0){r.textContent=i$2?i$2.emptyScript:"";for(var x=0;x2&&void 0!==arguments[2]?arguments[2]:t,o=arguments.length>3?arguments[3]:void 0;if(e===b)return e;var h=void 0!==o?null===(r=n._$Cl)||void 0===r?void 0:r[o]:n._$Cu,l=r$1(e)?void 0:e._$litDirective$;return(null==h?void 0:h.constructor)!==l&&(null===(i=null==h?void 0:h._$AO)||void 0===i||i.call(h,!1),void 0===l?h=void 0:(h=new l(t))._$AT(t,n,o),void 0!==o?(null!==(s=(a=n)._$Cl)&&void 0!==s?s:a._$Cl=[])[o]=h:n._$Cu=h),void 0!==h&&(e=P(t,h._$AS(t,e.values),h,o)),e}class V{constructor(t,e){this.v=[],this._$AN=void 0,this._$AD=t,this._$AM=e}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}p(t){var e,{el:{content:r},parts:i}=this._$AD,s=(null!==(e=null==t?void 0:t.creationScope)&&void 0!==e?e:l$2).importNode(r,!0);A.currentNode=s;for(var a=A.nextNode(),n=0,o=0,h=i[0];void 0!==h;){if(n===h.index){var l=void 0;2===h.type?l=new N(a,a.nextSibling,this,t):1===h.type?l=new h.ctor(a,h.name,h.strings,this,t):6===h.type&&(l=new L(a,this,t)),this.v.push(l),h=i[++o]}n!==(null==h?void 0:h.index)&&(a=A.nextNode(),n++)}return s}m(t){var e=0;for(var r of this.v)void 0!==r&&(void 0!==r.strings?(r._$AI(t,r,e),e+=r.strings.length-2):r._$AI(t[e])),e++}}class N{constructor(t,e,r,i){var s;this.type=2,this._$AH=w,this._$AN=void 0,this._$AA=t,this._$AB=e,this._$AM=r,this.options=i,this._$Cg=null===(s=null==i?void 0:i.isConnected)||void 0===s||s}get _$AU(){var t,e;return null!==(e=null===(t=this._$AM)||void 0===t?void 0:t._$AU)&&void 0!==e?e:this._$Cg}get parentNode(){var t=this._$AA.parentNode,e=this._$AM;return void 0!==e&&11===t.nodeType&&(t=e.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t){t=P(this,t,arguments.length>1&&void 0!==arguments[1]?arguments[1]:this),r$1(t)?t===w||null==t||""===t?(this._$AH!==w&&this._$AR(),this._$AH=w):t!==this._$AH&&t!==b&&this.$(t):void 0!==t._$litType$?this.T(t):void 0!==t.nodeType?this.S(t):u(t)?this.A(t):this.$(t)}M(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this._$AB;return this._$AA.parentNode.insertBefore(t,e)}S(t){this._$AH!==t&&(this._$AR(),this._$AH=this.M(t))}$(t){this._$AH!==w&&r$1(this._$AH)?this._$AA.nextSibling.data=t:this.S(l$2.createTextNode(t)),this._$AH=t}T(t){var e,{values:r,_$litType$:i}=t,s="number"==typeof i?this._$AC(t):(void 0===i.el&&(i.el=E.createElement(i.h,this.options)),i);if((null===(e=this._$AH)||void 0===e?void 0:e._$AD)===s)this._$AH.m(r);else{var a=new V(s,this),n=a.p(this.options);a.m(r),this.S(n),this._$AH=a}}_$AC(t){var e=T.get(t.strings);return void 0===e&&T.set(t.strings,e=new E(t)),e}A(t){d(this._$AH)||(this._$AH=[],this._$AR());var e,r=this._$AH,i=0;for(var s of t)i===r.length?r.push(e=new N(this.M(h$1()),this.M(h$1()),this,this.options)):e=r[i],e._$AI(s),i++;i0&&void 0!==arguments[0]?arguments[0]:this._$AA.nextSibling,r=arguments.length>1?arguments[1]:void 0;for(null===(t=this._$AP)||void 0===t||t.call(this,!1,!0,r);e&&e!==this._$AB;){var i=e.nextSibling;e.remove(),e=i}}setConnected(t){var e;void 0===this._$AM&&(this._$Cg=t,null===(e=this._$AP)||void 0===e||e.call(this,t))}}class S{constructor(t,e,r,i,s){this.type=1,this._$AH=w,this._$AN=void 0,this.element=t,this.name=e,this._$AM=i,this.options=s,r.length>2||""!==r[0]||""!==r[1]?(this._$AH=Array(r.length-1).fill(new String),this.strings=r):this._$AH=w}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this,r=arguments.length>2?arguments[2]:void 0,i=arguments.length>3?arguments[3]:void 0,s=this.strings,a=!1;if(void 0===s)t=P(this,t,e,0),(a=!r$1(t)||t!==this._$AH&&t!==b)&&(this._$AH=t);else{var n,o,h=t;for(t=s[0],n=0;n1&&void 0!==arguments[1]?arguments[1]:this,0))&&void 0!==e?e:w)!==b){var r=this._$AH,i=t===w&&r!==w||t.capture!==r.capture||t.once!==r.once||t.passive!==r.passive,s=t!==w&&(r===w||i);i&&this.element.removeEventListener(this.name,this,r),s&&this.element.addEventListener(this.name,this,t),this._$AH=t}}handleEvent(t){var e,r;"function"==typeof this._$AH?this._$AH.call(null!==(r=null===(e=this.options)||void 0===e?void 0:e.host)&&void 0!==r?r:this.element,t):this._$AH.handleEvent(t)}}class L{constructor(t,e,r){this.element=t,this.type=6,this._$AN=void 0,this._$AM=e,this.options=r}get _$AU(){return this._$AM._$AU}_$AI(t){P(this,t)}}var R={P:"$lit$",V:e$6,L:o$3,I:1,N:C,R:V,D:u,j:P,H:N,O:S,F:H,B:I,W:M,Z:L},z=window.litHtmlPolyfillSupport,l$1,o$2;null==z||z(E,N),(null!==(t$2=globalThis.litHtmlVersions)&&void 0!==t$2?t$2:globalThis.litHtmlVersions=[]).push("2.1.2");var r=a$1;class s extends a$1{constructor(){super(...arguments),this.renderOptions={host:this},this._$Dt=void 0}createRenderRoot(){var t,e,r=super.createRenderRoot();return null!==(t=(e=this.renderOptions).renderBefore)&&void 0!==t||(e.renderBefore=r.firstChild),r}update(t){var e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Dt=x(e,this.renderRoot,this.renderOptions)}connectedCallback(){var t;super.connectedCallback(),null===(t=this._$Dt)||void 0===t||t.setConnected(!0)}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this._$Dt)||void 0===t||t.setConnected(!1)}render(){return b}}s.finalized=!0,s._$litElement$=!0,null===(l$1=globalThis.litElementHydrateSupport)||void 0===l$1||l$1.call(globalThis,{LitElement:s});var n$2=globalThis.litElementPolyfillSupport;null==n$2||n$2({LitElement:s});var h={_$AK:(t,e,r)=>{t._$AK(e,r)},_$AL:t=>t._$AL};(null!==(o$2=globalThis.litElementVersions)&&void 0!==o$2?o$2:globalThis.litElementVersions=[]).push("3.1.2"); +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +var n$1=t=>e=>"function"==typeof e?((t,e)=>(window.customElements.define(t,e),e))(t,e):((t,e)=>{var{kind:r,elements:i}=e;return{kind:r,elements:i,finisher(e){window.customElements.define(t,e)}}})(t,e) +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */,i$1=(t,e)=>"method"===e.kind&&e.descriptor&&!("value"in e.descriptor)?_objectSpread2(_objectSpread2({},e),{},{finisher(r){r.createProperty(e.key,t)}}):{kind:"field",key:Symbol(),placement:"own",descriptor:{},originalKey:e.key,initializer(){"function"==typeof e.initializer&&(this[e.key]=e.initializer.call(this))},finisher(r){r.createProperty(e.key,t)}};function e$5(t){return(e,r)=>void 0!==r?((t,e,r)=>{e.constructor.createProperty(r,t)})(t,e,r):i$1(t,e)} +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */function t$1(t){return e$5(_objectSpread2(_objectSpread2({},t),{},{state:!0}))} +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */var e$4=(t,e,r)=>{Object.defineProperty(e,r,t)},t=(t,e)=>({kind:"method",placement:"prototype",key:e.key,descriptor:t}),o$1=t=>{var{finisher:e,descriptor:r}=t;return(t,i)=>{var s;if(void 0===i){var a=null!==(s=t.originalKey)&&void 0!==s?s:t.key,n=null!=r?{kind:"method",placement:"prototype",key:a,descriptor:r(t.key)}:_objectSpread2(_objectSpread2({},t),{},{key:a});return null!=e&&(n.finisher=function(t){e(t,a)}),n}var o=t.constructor;void 0!==r&&Object.defineProperty(t,i,r(i)),null==e||e(o,i)}},n; +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */function e$3(t){return o$1({finisher:(e,r)=>{Object.assign(e.prototype[r],t)}})} +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */function i(t,e){return o$1({descriptor:r=>{var i={get(){var e,r;return null!==(r=null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t))&&void 0!==r?r:null},enumerable:!0,configurable:!0};if(e){var s="symbol"==typeof r?Symbol():"__"+r;i.get=function(){var e,r;return void 0===this[s]&&(this[s]=null!==(r=null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t))&&void 0!==r?r:null),this[s]}}return i}})} +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */function e$2(t){return o$1({descriptor:e=>({get(){var e,r;return null!==(r=null===(e=this.renderRoot)||void 0===e?void 0:e.querySelectorAll(t))&&void 0!==r?r:[]},enumerable:!0,configurable:!0})})} +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */function e$1(t){return o$1({descriptor:e=>({get(){var e=this;return _asyncToGenerator((function*(){var r;return yield e.updateComplete,null===(r=e.renderRoot)||void 0===r?void 0:r.querySelector(t)}))()},enumerable:!0,configurable:!0})})} +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */var e=null!=(null===(n=window.HTMLSlotElement)||void 0===n?void 0:n.prototype.assignedElements)?(t,e)=>t.assignedElements(e):(t,e)=>t.assignedNodes(e).filter((t=>t.nodeType===Node.ELEMENT_NODE));function l(t){var{slot:r,selector:i}=null!=t?t:{};return o$1({descriptor:s=>({get(){var s,a="slot"+(r?"[name=".concat(r,"]"):":not([name])"),n=null===(s=this.renderRoot)||void 0===s?void 0:s.querySelector(a),o=null!=n?e(n,t):[];return i?o.filter((t=>t.matches(i))):o},enumerable:!0,configurable:!0})})} +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */function o(t,e,r){var i,s=t;return"object"==typeof t?(s=t.slot,i=t):i={flatten:e},r?l({slot:s,flatten:e,selector:r}):o$1({descriptor:t=>({get(){var t,e,r="slot"+(s?"[name=".concat(s,"]"):":not([name])"),a=null===(t=this.renderRoot)||void 0===t?void 0:t.querySelector(r);return null!==(e=null==a?void 0:a.assignedNodes(i))&&void 0!==e?e:[]},enumerable:!0,configurable:!0})})}var commonjsGlobal="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function getDefaultExportFromCjs(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}function getDefaultExportFromNamespaceIfPresent(t){return t&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}function getDefaultExportFromNamespaceIfNotNamed(t){return t&&Object.prototype.hasOwnProperty.call(t,"default")&&1===Object.keys(t).length?t.default:t}function getAugmentedNamespace(t){if(t.__esModule)return t;var e=Object.defineProperty({},"__esModule",{value:!0});return Object.keys(t).forEach((function(r){var i=Object.getOwnPropertyDescriptor(t,r);Object.defineProperty(e,r,i.get?i:{enumerable:!0,get:function(){return t[r]}})})),e}function commonjsRequire(t){throw new Error('Could not dynamically require "'+t+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var lottie$1={exports:{}};(function(module,exports){var factory;"undefined"!=typeof navigator&&(factory=function(){var svgNS="http://www.w3.org/2000/svg",locationHref="",_useWebWorker=!1,initialDefaultFrame=-999999,setWebWorker=function(t){_useWebWorker=!!t},getWebWorker=function(){return _useWebWorker},setLocationHref=function(t){locationHref=t},getLocationHref=function(){return locationHref};function createTag(t){return document.createElement(t)}function extendPrototype(t,e){var r,i,s=t.length;for(r=0;r1?r[1]=1:r[1]<=0&&(r[1]=0),HSVtoRGB(r[0],r[1],r[2])}function addBrightnessToRGB(t,e){var r=RGBtoHSV(255*t[0],255*t[1],255*t[2]);return r[2]+=e,r[2]>1?r[2]=1:r[2]<0&&(r[2]=0),HSVtoRGB(r[0],r[1],r[2])}function addHueToRGB(t,e){var r=RGBtoHSV(255*t[0],255*t[1],255*t[2]);return r[0]+=e/360,r[0]>1?r[0]-=1:r[0]<0&&(r[0]+=1),HSVtoRGB(r[0],r[1],r[2])}var rgbToHex=function(){var t,e,r=[];for(t=0;t<256;t+=1)e=t.toString(16),r[t]=1===e.length?"0"+e:e;return function(t,e,i){return t<0&&(t=0),e<0&&(e=0),i<0&&(i=0),"#"+r[t]+r[e]+r[i]}}(),setSubframeEnabled=function(t){subframeEnabled=!!t},getSubframeEnabled=function(){return subframeEnabled},setExpressionsPlugin=function(t){expressionsPlugin=t},getExpressionsPlugin=function(){return expressionsPlugin},setExpressionInterfaces=function(t){expressionsInterfaces=t},getExpressionInterfaces=function(){return expressionsInterfaces},setDefaultCurveSegments=function(t){defaultCurveSegments=t},getDefaultCurveSegments=function(){return defaultCurveSegments},setIdPrefix=function(t){idPrefix$1=t},getIdPrefix=function(){return idPrefix$1};function createNS(t){return document.createElementNS(svgNS,t)}function _typeof$5(t){return _typeof$5="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},_typeof$5(t)}var dataManager=function(){var t,e,r=1,i=[],s={onmessage:function(){},postMessage:function(e){t({data:e})}},_workerSelf={postMessage:function(t){s.onmessage({data:t})}};function a(){e||(e=function(e){if(window.Worker&&window.Blob&&getWebWorker()){var r=new Blob(["var _workerSelf = self; self.onmessage = ",e.toString()],{type:"text/javascript"}),i=URL.createObjectURL(r);return new Worker(i)}return t=e,s}((function(t){if(_workerSelf.dataManager||(_workerSelf.dataManager=function(){function t(s,a){var n,o,h,l,p,f,u=s.length;for(o=0;o=0;e-=1)if("sh"===t[e].ty)if(t[e].ks.k.i)i(t[e].ks.k);else for(a=t[e].ks.k.length,s=0;sr[0]||!(r[0]>t[0])&&(t[1]>r[1]||!(r[1]>t[1])&&(t[2]>r[2]||!(r[2]>t[2])&&null))}var a,n=function(){var t=[4,4,14];function e(t){var e,r,i,s=t.length;for(e=0;e=0;r-=1)if("sh"===t[r].ty)if(t[r].ks.k.i)t[r].ks.k.c=t[r].closed;else for(s=t[r].ks.k.length,i=0;i500)&&(this._imageLoaded(),clearInterval(r)),e+=1}.bind(this),50)}function a(t){var e={assetData:t},r=i(t,this.assetsPath,this.path);return dataManager.loadData(r,function(t){e.img=t,this._footageLoaded()}.bind(this),function(){e.img={},this._footageLoaded()}.bind(this)),e}function n(){this._imageLoaded=e.bind(this),this._footageLoaded=r.bind(this),this.testImageLoaded=s.bind(this),this.createFootageData=a.bind(this),this.assetsPath="",this.path="",this.totalImages=0,this.totalFootages=0,this.loadedAssets=0,this.loadedFootagesCount=0,this.imagesLoadedCb=null,this.images=[]}return n.prototype={loadAssets:function(t,e){var r;this.imagesLoadedCb=e;var i=t.length;for(r=0;rthis.animationData.op&&(this.animationData.op=t.op,this.totalFrames=Math.floor(t.op-this.animationData.ip));var e,r,i=this.animationData.layers,s=i.length,a=t.layers,n=a.length;for(r=0;rthis.timeCompleted&&(this.currentFrame=this.timeCompleted),this.trigger("enterFrame"),this.renderFrame(),this.trigger("drawnFrame")},AnimationItem.prototype.renderFrame=function(){if(!1!==this.isLoaded&&this.renderer)try{this.expressionsPlugin&&this.expressionsPlugin.resetFrame(),this.renderer.renderFrame(this.currentFrame+this.firstFrame)}catch(t){this.triggerRenderFrameError(t)}},AnimationItem.prototype.play=function(t){t&&this.name!==t||!0===this.isPaused&&(this.isPaused=!1,this.trigger("_play"),this.audioController.resume(),this._idle&&(this._idle=!1,this.trigger("_active")))},AnimationItem.prototype.pause=function(t){t&&this.name!==t||!1===this.isPaused&&(this.isPaused=!0,this.trigger("_pause"),this._idle=!0,this.trigger("_idle"),this.audioController.pause())},AnimationItem.prototype.togglePause=function(t){t&&this.name!==t||(!0===this.isPaused?this.play():this.pause())},AnimationItem.prototype.stop=function(t){t&&this.name!==t||(this.pause(),this.playCount=0,this._completedLoop=!1,this.setCurrentRawFrameValue(0))},AnimationItem.prototype.getMarkerData=function(t){for(var e,r=0;r=this.totalFrames-1&&this.frameModifier>0?this.loop&&this.playCount!==this.loop?e>=this.totalFrames?(this.playCount+=1,this.checkSegments(e%this.totalFrames)||(this.setCurrentRawFrameValue(e%this.totalFrames),this._completedLoop=!0,this.trigger("loopComplete"))):this.setCurrentRawFrameValue(e):this.checkSegments(e>this.totalFrames?e%this.totalFrames:0)||(r=!0,e=this.totalFrames-1):e<0?this.checkSegments(e%this.totalFrames)||(!this.loop||this.playCount--<=0&&!0!==this.loop?(r=!0,e=0):(this.setCurrentRawFrameValue(this.totalFrames+e%this.totalFrames),this._completedLoop?this.trigger("loopComplete"):this._completedLoop=!0)):this.setCurrentRawFrameValue(e),r&&(this.setCurrentRawFrameValue(e),this.pause(),this.trigger("complete"))}},AnimationItem.prototype.adjustSegment=function(t,e){this.playCount=0,t[1]0&&(this.playSpeed<0?this.setSpeed(-this.playSpeed):this.setDirection(-1)),this.totalFrames=t[0]-t[1],this.timeCompleted=this.totalFrames,this.firstFrame=t[1],this.setCurrentRawFrameValue(this.totalFrames-.001-e)):t[1]>t[0]&&(this.frameModifier<0&&(this.playSpeed<0?this.setSpeed(-this.playSpeed):this.setDirection(1)),this.totalFrames=t[1]-t[0],this.timeCompleted=this.totalFrames,this.firstFrame=t[0],this.setCurrentRawFrameValue(.001+e)),this.trigger("segmentStart")},AnimationItem.prototype.setSegment=function(t,e){var r=-1;this.isPaused&&(this.currentRawFrame+this.firstFramee&&(r=e-t)),this.firstFrame=t,this.totalFrames=e-t,this.timeCompleted=this.totalFrames,-1!==r&&this.goToAndStop(r,!0)},AnimationItem.prototype.playSegments=function(t,e){if(e&&(this.segments.length=0),"object"===_typeof$4(t[0])){var r,i=t.length;for(r=0;r=0;r-=1)e[r].animation.destroy(t)},t.freeze=function(){n=!0},t.unfreeze=function(){n=!1,d()},t.setVolume=function(t,r){var s;for(s=0;s=.001?function(t,e,r,i){for(var s=0;s<4;++s){var a=h(e,r,i);if(0===a)return e;e-=(o(e,r,i)-t)/a}return e}(t,l,e,i):0===p?l:function(t,e,r,i,s){var a,n,h=0;do{(a=o(n=e+(r-e)/2,i,s)-t)>0?r=n:e=n}while(Math.abs(a)>1e-7&&++h<10);return n}(t,a,a+r,e,i)}},t}(),pooling={double:function(t){return t.concat(createSizedArray(t.length))}},poolFactory=function(t,e,r){var i=0,s=t,a=createSizedArray(s);return{newElement:function(){return i?a[i-=1]:e()},release:function(t){i===s&&(a=pooling.double(a),s*=2),r&&r(t),a[i]=t,i+=1}}},bezierLengthPool=poolFactory(8,(function(){return{addedLength:0,percents:createTypedArray("float32",getDefaultCurveSegments()),lengths:createTypedArray("float32",getDefaultCurveSegments())}})),segmentsLengthPool=poolFactory(8,(function(){return{lengths:[],totalLength:0}}),(function(t){var e,r=t.lengths.length;for(e=0;e-.001&&n<.001}var r=function(t,e,r,i){var s,a,n,o,h,l,p=getDefaultCurveSegments(),c=0,f=[],u=[],d=bezierLengthPool.newElement();for(n=r.length,s=0;sn?-1:1,l=!0;l;)if(i[a]<=n&&i[a+1]>n?(o=(n-i[a])/(i[a+1]-i[a]),l=!1):a+=h,a<0||a>=s-1){if(a===s-1)return r[a];l=!1}return r[a]+(r[a+1]-r[a])*o}var h=createTypedArray("float32",8);return{getSegmentsLength:function(t){var e,i=segmentsLengthPool.newElement(),s=t.c,a=t.v,n=t.o,o=t.i,h=t._length,l=i.lengths,p=0;for(e=0;e1&&(a=1);var p,c=o(a,l),f=o(n=n>1?1:n,l),u=e.length,d=1-c,m=1-f,y=d*d*d,g=c*d*d*3,v=c*c*d*3,b=c*c*c,_=d*d*m,P=c*d*m+d*c*m+d*d*f,S=c*c*m+d*c*f+c*d*f,E=c*c*f,x=d*m*m,C=c*m*m+d*f*m+d*m*f,A=c*f*m+d*f*f+c*m*f,w=c*f*f,k=m*m*m,T=f*m*m+m*f*m+m*m*f,M=f*f*m+m*f*f+f*m*f,D=f*f*f;for(p=0;pu?f>d?f-u-d:d-u-f:d>u?d-u-f:u-f-d)>-1e-4&&c<1e-4}}}var bez=bezFunction(),initFrame=initialDefaultFrame,mathAbs=Math.abs;function interpolateValue(t,e){var r,i=this.offsetTime;"multidimensional"===this.propType&&(r=createTypedArray("float32",this.pv.length));for(var s,a,n,o,h,l,p,c,f,u=e.lastIndex,d=u,m=this.keyframes.length-1,y=!0;y;){if(s=this.keyframes[d],a=this.keyframes[d+1],d===m-1&&t>=a.t-i){s.h&&(s=a),u=0;break}if(a.t-i>t){u=d;break}d=v||t=v?_.points.length-1:0;for(h=_.points[P].point.length,o=0;o=x&&E=v?(r[0]=g[0],r[1]=g[1],r[2]=g[2]):t<=b?(r[0]=s.s[0],r[1]=s.s[1],r[2]=s.s[2]):quaternionToEuler(r,slerp(createQuaternion(s.s),createQuaternion(g),(t-b)/(v-b)));else for(d=0;d=v?l=1:t1e-6?(i=Math.acos(s),a=Math.sin(i),n=Math.sin((1-r)*i)/a,o=Math.sin(r*i)/a):(n=1-r,o=r),h[0]=n*l+o*u,h[1]=n*p+o*d,h[2]=n*c+o*m,h[3]=n*f+o*y,h}function quaternionToEuler(t,e){var r=e[0],i=e[1],s=e[2],a=e[3],n=Math.atan2(2*i*a-2*r*s,1-2*i*i-2*s*s),o=Math.asin(2*r*i+2*s*a),h=Math.atan2(2*r*a-2*i*s,1-2*r*r-2*s*s);t[0]=n/degToRads,t[1]=o/degToRads,t[2]=h/degToRads}function createQuaternion(t){var e=t[0]*degToRads,r=t[1]*degToRads,i=t[2]*degToRads,s=Math.cos(e/2),a=Math.cos(r/2),n=Math.cos(i/2),o=Math.sin(e/2),h=Math.sin(r/2),l=Math.sin(i/2);return[o*h*n+s*a*l,o*a*n+s*h*l,s*h*n-o*a*l,s*a*n-o*h*l]}function getValueAtCurrentTime(){var t=this.comp.renderedFrame-this.offsetTime,e=this.keyframes[0].t-this.offsetTime,r=this.keyframes[this.keyframes.length-1].t-this.offsetTime;if(!(t===this._caching.lastFrame||this._caching.lastFrame!==initFrame&&(this._caching.lastFrame>=r&&t>=r||this._caching.lastFrame=t&&(this._caching._lastKeyframeIndex=-1,this._caching.lastIndex=0);var i=this.interpolateValue(t,this._caching);this.pv=i}return this._caching.lastFrame=t,this.pv}function setVValue(t){var e;if("unidimensional"===this.propType)e=t*this.mult,mathAbs(this.v-e)>1e-5&&(this.v=e,this._mdf=!0);else for(var r=0,i=this.v.length;r1e-5&&(this.v[r]=e,this._mdf=!0),r+=1}function processEffectsSequence(){if(this.elem.globalData.frameId!==this.frameId&&this.effectsSequence.length)if(this.lock)this.setVValue(this.pv);else{var t;this.lock=!0,this._mdf=this._isFirstFrame;var e=this.effectsSequence.length,r=this.kf?this.pv:this.data.k;for(t=0;t=this._maxLength&&this.doubleArrayLength(),r){case"v":a=this.v;break;case"i":a=this.i;break;case"o":a=this.o;break;default:a=[]}(!a[i]||a[i]&&!s)&&(a[i]=pointPool.newElement()),a[i][0]=t,a[i][1]=e},ShapePath.prototype.setTripleAt=function(t,e,r,i,s,a,n,o){this.setXYAt(t,e,"v",n,o),this.setXYAt(r,i,"o",n,o),this.setXYAt(s,a,"i",n,o)},ShapePath.prototype.reverse=function(){var t=new ShapePath;t.setPathData(this.c,this._length);var e=this.v,r=this.o,i=this.i,s=0;this.c&&(t.setTripleAt(e[0][0],e[0][1],i[0][0],i[0][1],r[0][0],r[0][1],0,!1),s=1);var a,n=this._length-1,o=this._length;for(a=s;a=u[u.length-1].t-this.offsetTime)i=u[u.length-1].s?u[u.length-1].s[0]:u[u.length-2].e[0],a=!0;else{for(var d,m,y,g=f,v=u.length-1,b=!0;b&&(d=u[g],!((m=u[g+1]).t-this.offsetTime>t));)g=m.t-this.offsetTime)p=1;else if(ti&&e>i)||(this._caching.lastIndex=s0||t>-1e-6&&t<0?i(1e4*t)/1e4:t}function I(){var t=this.props;return"matrix("+F(t[0])+","+F(t[1])+","+F(t[4])+","+F(t[5])+","+F(t[12])+","+F(t[13])+")"}return function(){this.reset=s,this.rotate=a,this.rotateX=n,this.rotateY=o,this.rotateZ=h,this.skew=p,this.skewFromAxis=c,this.shear=l,this.scale=f,this.setTransform=u,this.translate=d,this.transform=m,this.multiply=y,this.applyToPoint=P,this.applyToX=S,this.applyToY=E,this.applyToZ=x,this.applyToPointArray=T,this.applyToTriplePoints=k,this.applyToPointStringified=M,this.toCSS=D,this.to2dCSS=I,this.clone=b,this.cloneFromProps=_,this.equals=v,this.inversePoints=w,this.inversePoint=A,this.getInverseMatrix=C,this._t=this.transform,this.isIdentity=g,this._identity=!0,this._identityCalculated=!1,this.props=createTypedArray("float32",16),this.reset()}}();function _typeof$3(t){return _typeof$3="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},_typeof$3(t)}var lottie={},standalone="__[STANDALONE]__",animationData="__[ANIMATIONDATA]__",renderer="";function setLocation(t){setLocationHref(t)}function searchAnimations(){!0===standalone?animationManager.searchAnimations(animationData,standalone,renderer):animationManager.searchAnimations()}function setSubframeRendering(t){setSubframeEnabled(t)}function setPrefix(t){setIdPrefix(t)}function loadAnimation(t){return!0===standalone&&(t.animationData=JSON.parse(animationData)),animationManager.loadAnimation(t)}function setQuality(t){if("string"==typeof t)switch(t){case"high":setDefaultCurveSegments(200);break;default:case"medium":setDefaultCurveSegments(50);break;case"low":setDefaultCurveSegments(10)}else!isNaN(t)&&t>1&&setDefaultCurveSegments(t);getDefaultCurveSegments()>=50?roundValues(!1):roundValues(!0)}function inBrowser(){return"undefined"!=typeof navigator}function installPlugin(t,e){"expressions"===t&&setExpressionsPlugin(e)}function getFactory(t){switch(t){case"propertyFactory":return PropertyFactory;case"shapePropertyFactory":return ShapePropertyFactory;case"matrix":return Matrix;default:return null}}function checkReady(){"complete"===document.readyState&&(clearInterval(readyStateCheckInterval),searchAnimations())}function getQueryVariable(t){for(var e=queryString.split("&"),r=0;r=1?a.push({s:t-1,e:e-1}):(a.push({s:t,e:1}),a.push({s:0,e:e-1}));var n,o,h=[],l=a.length;for(n=0;ni+r||(p=o.s*s<=i?0:(o.s*s-i)/r,c=o.e*s>=i+r?1:(o.e*s-i)/r,h.push([p,c]))}return h.length||h.push([0,0]),h},TrimModifier.prototype.releasePathsData=function(t){var e,r=t.length;for(e=0;e1?1+a:this.s.v<0?0+a:this.s.v+a)>(r=this.e.v>1?1+a:this.e.v<0?0+a:this.e.v+a)){var n=e;e=r,r=n}e=1e-4*Math.round(1e4*e),r=1e-4*Math.round(1e4*r),this.sValue=e,this.eValue=r}else e=this.sValue,r=this.eValue;var o,h,l,p,c,f=this.shapes.length,u=0;if(r===e)for(s=0;s=0;s-=1)if((d=this.shapes[s]).shape._mdf){for((m=d.localShapeCollection).releaseShapes(),2===this.m&&f>1?(g=this.calculateShapeEdges(e,r,d.totalShapeLength,_,u),_+=d.totalShapeLength):g=[[v,b]],h=g.length,o=0;o=1?y.push({s:d.totalShapeLength*(v-1),e:d.totalShapeLength*(b-1)}):(y.push({s:d.totalShapeLength*v,e:d.totalShapeLength}),y.push({s:0,e:d.totalShapeLength*(b-1)}));var P=this.addShapes(d,y[0]);if(y[0].s!==y[0].e){if(y.length>1)if(d.shape.paths.shapes[d.shape.paths._length-1].c){var S=P.pop();this.addPaths(P,m),P=this.addShapes(d,y[1],S)}else this.addPaths(P,m),P=this.addShapes(d,y[1]);this.addPaths(P,m)}}d.shape.paths=m}}},TrimModifier.prototype.addPaths=function(t,e){var r,i=t.length;for(r=0;re.e){r.c=!1;break}e.s<=d&&e.e>=d+n.addedLength?(this.addSegment(f[i].v[s-1],f[i].o[s-1],f[i].i[s],f[i].v[s],r,o,y),y=!1):(l=bez.getNewSegment(f[i].v[s-1],f[i].v[s],f[i].o[s-1],f[i].i[s],(e.s-d)/n.addedLength,(e.e-d)/n.addedLength,h[s-1]),this.addSegmentFromArray(l,r,o,y),y=!1,r.c=!1),d+=n.addedLength,o+=1}if(f[i].c&&h.length){if(n=h[s-1],d<=e.e){var g=h[s-1].addedLength;e.s<=d&&e.e>=d+g?(this.addSegment(f[i].v[s-1],f[i].o[s-1],f[i].i[0],f[i].v[0],r,o,y),y=!1):(l=bez.getNewSegment(f[i].v[s-1],f[i].v[0],f[i].o[s-1],f[i].i[0],(e.s-d)/g,(e.e-d)/g,h[s-1]),this.addSegmentFromArray(l,r,o,y),y=!1,r.c=!1)}else r.c=!1;d+=n.addedLength,o+=1}if(r._length&&(r.setXYAt(r.v[p][0],r.v[p][1],"i",p),r.setXYAt(r.v[r._length-1][0],r.v[r._length-1][1],"o",r._length-1)),d>e.e)break;i=this.p.keyframes[this.p.keyframes.length-1].t?(i=this.p.getValueAtTime(this.p.keyframes[this.p.keyframes.length-1].t/r,0),s=this.p.getValueAtTime((this.p.keyframes[this.p.keyframes.length-1].t-.05)/r,0)):(i=this.p.pv,s=this.p.getValueAtTime((this.p._caching.lastFrame+this.p.offsetTime-.01)/r,this.p.offsetTime));else if(this.px&&this.px.keyframes&&this.py.keyframes&&this.px.getValueAtTime&&this.py.getValueAtTime){i=[],s=[];var a=this.px,n=this.py;a._caching.lastFrame+a.offsetTime<=a.keyframes[0].t?(i[0]=a.getValueAtTime((a.keyframes[0].t+.01)/r,0),i[1]=n.getValueAtTime((n.keyframes[0].t+.01)/r,0),s[0]=a.getValueAtTime(a.keyframes[0].t/r,0),s[1]=n.getValueAtTime(n.keyframes[0].t/r,0)):a._caching.lastFrame+a.offsetTime>=a.keyframes[a.keyframes.length-1].t?(i[0]=a.getValueAtTime(a.keyframes[a.keyframes.length-1].t/r,0),i[1]=n.getValueAtTime(n.keyframes[n.keyframes.length-1].t/r,0),s[0]=a.getValueAtTime((a.keyframes[a.keyframes.length-1].t-.01)/r,0),s[1]=n.getValueAtTime((n.keyframes[n.keyframes.length-1].t-.01)/r,0)):(i=[a.pv,n.pv],s[0]=a.getValueAtTime((a._caching.lastFrame+a.offsetTime-.01)/r,a.offsetTime),s[1]=n.getValueAtTime((n._caching.lastFrame+n.offsetTime-.01)/r,n.offsetTime))}else i=s=t;this.v.rotate(-Math.atan2(i[1]-s[1],i[0]-s[0]))}this.data.p&&this.data.p.s?this.data.p.z?this.v.translate(this.px.v,this.py.v,-this.pz.v):this.v.translate(this.px.v,this.py.v,0):this.v.translate(this.p.v[0],this.p.v[1],-this.p.v[2])}this.frameId=this.elem.globalData.frameId}},precalculateMatrix:function(){if(this.appliedTransformations=0,this.pre.reset(),!this.a.effectsSequence.length&&(this.pre.translate(-this.a.v[0],-this.a.v[1],this.a.v[2]),this.appliedTransformations=1,!this.s.effectsSequence.length)){if(this.pre.scale(this.s.v[0],this.s.v[1],this.s.v[2]),this.appliedTransformations=2,this.sk){if(this.sk.effectsSequence.length||this.sa.effectsSequence.length)return;this.pre.skewFromAxis(-this.sk.v,this.sa.v),this.appliedTransformations=3}this.r?this.r.effectsSequence.length||(this.pre.rotate(-this.r.v),this.appliedTransformations=4):this.rz.effectsSequence.length||this.ry.effectsSequence.length||this.rx.effectsSequence.length||this.or.effectsSequence.length||(this.pre.rotateZ(-this.rz.v).rotateY(this.ry.v).rotateX(this.rx.v).rotateZ(-this.or.v[2]).rotateY(this.or.v[1]).rotateX(this.or.v[0]),this.appliedTransformations=4)}},autoOrient:function(){}},extendPrototype([DynamicPropertyContainer],e),e.prototype.addDynamicProperty=function(t){this._addDynamicProperty(t),this.elem.addDynamicProperty(t),this._isDirty=!0},e.prototype._addDynamicProperty=DynamicPropertyContainer.prototype.addDynamicProperty,{getTransformProperty:function(t,r,i){return new e(t,r,i)}}}();function RepeaterModifier(){}function RoundCornersModifier(){}function floatEqual(t,e){return 1e5*Math.abs(t-e)<=Math.min(Math.abs(t),Math.abs(e))}function floatZero(t){return Math.abs(t)<=1e-5}function lerp(t,e,r){return t*(1-r)+e*r}function lerpPoint(t,e,r){return[lerp(t[0],e[0],r),lerp(t[1],e[1],r)]}function quadRoots(t,e,r){if(0===t)return[];var i=e*e-4*t*r;if(i<0)return[];var s=-e/(2*t);if(0===i)return[s];var a=Math.sqrt(i)/(2*t);return[s-a,s+a]}function polynomialCoefficients(t,e,r,i){return[3*e-t-3*r+i,3*t-6*e+3*r,-3*t+3*e,t]}function singlePoint(t){return new PolynomialBezier(t,t,t,t,!1)}function PolynomialBezier(t,e,r,i,s){s&&pointEqual(t,e)&&(e=lerpPoint(t,i,1/3)),s&&pointEqual(r,i)&&(r=lerpPoint(t,i,2/3));var a=polynomialCoefficients(t[0],e[0],r[0],i[0]),n=polynomialCoefficients(t[1],e[1],r[1],i[1]);this.a=[a[0],n[0]],this.b=[a[1],n[1]],this.c=[a[2],n[2]],this.d=[a[3],n[3]],this.points=[t,e,r,i]}function extrema(t,e){var r=t.points[0][e],i=t.points[t.points.length-1][e];if(r>i){var s=i;i=r,r=s}for(var a=quadRoots(3*t.a[e],2*t.b[e],t.c[e]),n=0;n0&&a[n]<1){var o=t.point(a[n])[e];oi&&(i=o)}return{min:r,max:i}}function intersectData(t,e,r){var i=t.boundingBox();return{cx:i.cx,cy:i.cy,width:i.width,height:i.height,bez:t,t:(e+r)/2,t1:e,t2:r}}function splitData(t){var e=t.bez.split(.5);return[intersectData(e[0],t.t1,t.t),intersectData(e[1],t.t,t.t2)]}function boxIntersect(t,e){return 2*Math.abs(t.cx-e.cx)=a||t.width<=i&&t.height<=i&&e.width<=i&&e.height<=i)s.push([t.t,e.t]);else{var n=splitData(t),o=splitData(e);intersectsImpl(n[0],o[0],r+1,i,s,a),intersectsImpl(n[0],o[1],r+1,i,s,a),intersectsImpl(n[1],o[0],r+1,i,s,a),intersectsImpl(n[1],o[1],r+1,i,s,a)}}function crossProduct(t,e){return[t[1]*e[2]-t[2]*e[1],t[2]*e[0]-t[0]*e[2],t[0]*e[1]-t[1]*e[0]]}function lineIntersection(t,e,r,i){var s=[t[0],t[1],1],a=[e[0],e[1],1],n=[r[0],r[1],1],o=[i[0],i[1],1],h=crossProduct(crossProduct(s,a),crossProduct(n,o));return floatZero(h[2])?null:[h[0]/h[2],h[1]/h[2]]}function polarOffset(t,e,r){return[t[0]+Math.cos(e)*r,t[1]-Math.sin(e)*r]}function pointDistance(t,e){return Math.hypot(t[0]-e[0],t[1]-e[1])}function pointEqual(t,e){return floatEqual(t[0],e[0])&&floatEqual(t[1],e[1])}function ZigZagModifier(){}function setPoint(t,e,r,i,s,a,n){var o=r-Math.PI/2,h=r+Math.PI/2,l=e[0]+Math.cos(r)*i*s,p=e[1]-Math.sin(r)*i*s;t.setTripleAt(l,p,l+Math.cos(o)*a,p-Math.sin(o)*a,l+Math.cos(h)*n,p-Math.sin(h)*n,t.length())}function getPerpendicularVector(t,e){var r=[e[0]-t[0],e[1]-t[1]],i=.5*-Math.PI;return[Math.cos(i)*r[0]-Math.sin(i)*r[1],Math.sin(i)*r[0]+Math.cos(i)*r[1]]}function getProjectingAngle(t,e){var r=0===e?t.length()-1:e-1,i=(e+1)%t.length(),s=getPerpendicularVector(t.v[r],t.v[i]);return Math.atan2(0,1)-Math.atan2(s[1],s[0])}function zigZagCorner(t,e,r,i,s,a,n){var o=getProjectingAngle(e,r),h=e.v[r%e._length],l=e.v[0===r?e._length-1:r-1],p=e.v[(r+1)%e._length],c=2===a?Math.sqrt(Math.pow(h[0]-l[0],2)+Math.pow(h[1]-l[1],2)):0,f=2===a?Math.sqrt(Math.pow(h[0]-p[0],2)+Math.pow(h[1]-p[1],2)):0;setPoint(t,e.v[r%e._length],o,n,i,f/(2*(s+1)),c/(2*(s+1)),a)}function zigZagSegment(t,e,r,i,s,a){for(var n=0;n1&&e.length>1&&(s=getIntersection(t[0],e[e.length-1]))?[[t[0].split(s[0])[0]],[e[e.length-1].split(s[1])[1]]]:[r,i]}function pruneIntersections(t){for(var e,r=1;r1&&(e=pruneSegmentIntersection(t[t.length-1],t[0]),t[t.length-1]=e[0],t[0]=e[1]),t}function offsetSegmentSplit(t,e){var r,i,s,a,n=t.inflectionPoints();if(0===n.length)return[offsetSegment(t,e)];if(1===n.length||floatEqual(n[1],1))return r=(s=t.split(n[0]))[0],i=s[1],[offsetSegment(r,e),offsetSegment(i,e)];r=(s=t.split(n[0]))[0];var o=(n[1]-n[0])/(1-n[0]);return a=(s=s[1].split(o))[0],i=s[1],[offsetSegment(r,e),offsetSegment(a,e),offsetSegment(i,e)]}function OffsetPathModifier(){}function getFontProperties(t){for(var e=t.fStyle?t.fStyle.split(" "):[],r="normal",i="normal",s=e.length,a=0;a0;)r-=1,this._elements.unshift(e[r]);this.dynamicProperties.length?this.k=!0:this.getValue(!0)},RepeaterModifier.prototype.resetElements=function(t){var e,r=t.length;for(e=0;e0?Math.floor(f):Math.ceil(f),m=this.pMatrix.props,y=this.rMatrix.props,g=this.sMatrix.props;this.pMatrix.reset(),this.rMatrix.reset(),this.sMatrix.reset(),this.tMatrix.reset(),this.matrix.reset();var v,b,_=0;if(f>0){for(;_d;)this.applyTransforms(this.pMatrix,this.rMatrix,this.sMatrix,this.tr,1,!0),_-=1;u&&(this.applyTransforms(this.pMatrix,this.rMatrix,this.sMatrix,this.tr,-u,!0),_-=u)}for(i=1===this.data.m?0:this._currentCopies-1,s=1===this.data.m?1:-1,a=this._currentCopies;a;){if(b=(r=(e=this.elemsData[i].it)[e.length-1].transform.mProps.v.props).length,e[e.length-1].transform.mProps._mdf=!0,e[e.length-1].transform.op._mdf=!0,e[e.length-1].transform.op.v=1===this._currentCopies?this.so.v:this.so.v+(this.eo.v-this.so.v)*(i/(this._currentCopies-1)),0!==_){for((0!==i&&1===s||i!==this._currentCopies-1&&-1===s)&&this.applyTransforms(this.pMatrix,this.rMatrix,this.sMatrix,this.tr,1,!1),this.matrix.transform(y[0],y[1],y[2],y[3],y[4],y[5],y[6],y[7],y[8],y[9],y[10],y[11],y[12],y[13],y[14],y[15]),this.matrix.transform(g[0],g[1],g[2],g[3],g[4],g[5],g[6],g[7],g[8],g[9],g[10],g[11],g[12],g[13],g[14],g[15]),this.matrix.transform(m[0],m[1],m[2],m[3],m[4],m[5],m[6],m[7],m[8],m[9],m[10],m[11],m[12],m[13],m[14],m[15]),v=0;v0&&i<1?[e]:[]:[e-i,e+i].filter((function(t){return t>0&&t<1}))},PolynomialBezier.prototype.split=function(t){if(t<=0)return[singlePoint(this.points[0]),this];if(t>=1)return[this,singlePoint(this.points[this.points.length-1])];var e=lerpPoint(this.points[0],this.points[1],t),r=lerpPoint(this.points[1],this.points[2],t),i=lerpPoint(this.points[2],this.points[3],t),s=lerpPoint(e,r,t),a=lerpPoint(r,i,t),n=lerpPoint(s,a,t);return[new PolynomialBezier(this.points[0],e,s,n,!0),new PolynomialBezier(n,a,i,this.points[3],!0)]},PolynomialBezier.prototype.bounds=function(){return{x:extrema(this,0),y:extrema(this,1)}},PolynomialBezier.prototype.boundingBox=function(){var t=this.bounds();return{left:t.x.min,right:t.x.max,top:t.y.min,bottom:t.y.max,width:t.x.max-t.x.min,height:t.y.max-t.y.min,cx:(t.x.max+t.x.min)/2,cy:(t.y.max+t.y.min)/2}},PolynomialBezier.prototype.intersections=function(t,e,r){void 0===e&&(e=2),void 0===r&&(r=7);var i=[];return intersectsImpl(intersectData(this,0,1),intersectData(t,0,1),0,e,i,r),i},PolynomialBezier.shapeSegment=function(t,e){var r=(e+1)%t.length();return new PolynomialBezier(t.v[e],t.o[e],t.i[r],t.v[r],!0)},PolynomialBezier.shapeSegmentInverted=function(t,e){var r=(e+1)%t.length();return new PolynomialBezier(t.v[r],t.i[r],t.o[e],t.v[e],!0)},extendPrototype([ShapeModifier],ZigZagModifier),ZigZagModifier.prototype.initModifierProperties=function(t,e){this.getValue=this.processKeys,this.amplitude=PropertyFactory.getProp(t,e.s,0,null,this),this.frequency=PropertyFactory.getProp(t,e.r,0,null,this),this.pointsType=PropertyFactory.getProp(t,e.pt,0,null,this),this._isAnimated=0!==this.amplitude.effectsSequence.length||0!==this.frequency.effectsSequence.length||0!==this.pointsType.effectsSequence.length},ZigZagModifier.prototype.processPath=function(t,e,r,i){var s=t._length,a=shapePool.newElement();if(a.c=t.c,t.c||(s-=1),0===s)return a;var n=-1,o=PolynomialBezier.shapeSegment(t,0);zigZagCorner(a,t,0,e,r,i,n);for(var h=0;h=0;a-=1)o=PolynomialBezier.shapeSegmentInverted(t,a),l.push(offsetSegmentSplit(o,e));l=pruneIntersections(l);var p=null,c=null;for(a=0;a=55296&&r<=56319){var i=t.charCodeAt(1);i>=56320&&i<=57343&&(e=1024*(r-55296)+i-56320+65536)}return e}function o(t){var e=n(t);return e>=127462&&e<=127487}var h=function(){this.fonts=[],this.chars=null,this.typekitLoaded=0,this.isLoaded=!1,this._warned=!1,this.initTime=Date.now(),this.setIsLoadedBinded=this.setIsLoaded.bind(this),this.checkLoadedFontsBinded=this.checkLoadedFonts.bind(this)};h.isModifier=function(t,e){var r=t.toString(16)+e.toString(16);return-1!==i.indexOf(r)},h.isZeroWidthJoiner=function(t){return 8205===t},h.isFlagEmoji=function(t){return o(t.substr(0,2))&&o(t.substr(2,2))},h.isRegionalCode=o,h.isCombinedCharacter=function(t){return-1!==e.indexOf(t)},h.isRegionalFlag=function(t,e){var i=n(t.substr(e,2));if(i!==r)return!1;var s=0;for(e+=2;s<5;){if((i=n(t.substr(e,2)))<917601||i>917626)return!1;s+=1,e+=2}return 917631===n(t.substr(e,2))},h.isVariationSelector=function(t){return 65039===t},h.BLACK_FLAG_CODE_POINT=r;var l={addChars:function(t){if(t){var e;this.chars||(this.chars=[]);var r,i,s=t.length,a=this.chars.length;for(e=0;e0&&(p=!1),p){var c=createTag("style");c.setAttribute("f-forigin",i[r].fOrigin),c.setAttribute("f-origin",i[r].origin),c.setAttribute("f-family",i[r].fFamily),c.type="text/css",c.innerText="@font-face {font-family: "+i[r].fFamily+"; font-style: normal; src: url('"+i[r].fPath+"');}",e.appendChild(c)}}else if("g"===i[r].fOrigin||1===i[r].origin){for(h=document.querySelectorAll('link[f-forigin="g"], link[f-origin="1"]'),l=0;lt?!0!==this.isInRange&&(this.globalData._mdf=!0,this._mdf=!0,this.isInRange=!0,this.show()):!1!==this.isInRange&&(this.globalData._mdf=!0,this.isInRange=!1,this.hide())},renderRenderable:function(){var t,e=this.renderableComponents.length;for(t=0;t.1)&&this.audio.seek(this._currentTime/this.globalData.frameRate):(this.audio.play(),this.audio.seek(this._currentTime/this.globalData.frameRate),this._isPlaying=!0))},AudioElement.prototype.show=function(){},AudioElement.prototype.hide=function(){this.audio.pause(),this._isPlaying=!1},AudioElement.prototype.pause=function(){this.audio.pause(),this._isPlaying=!1,this._canPlay=!1},AudioElement.prototype.resume=function(){this._canPlay=!0},AudioElement.prototype.setRate=function(t){this.audio.rate(t)},AudioElement.prototype.volume=function(t){this._volumeMultiplier=t,this._previousVolume=t*this._volume,this.audio.volume(this._previousVolume)},AudioElement.prototype.getBaseElement=function(){return null},AudioElement.prototype.destroy=function(){},AudioElement.prototype.sourceRectAtTime=function(){},AudioElement.prototype.initExpressions=function(){},BaseRenderer.prototype.checkLayers=function(t){var e,r,i=this.layers.length;for(this.completeLayers=!0,e=i-1;e>=0;e-=1)this.elements[e]||(r=this.layers[e]).ip-r.st<=t-this.layers[e].st&&r.op-r.st>t-this.layers[e].st&&this.buildItem(e),this.completeLayers=!!this.elements[e]&&this.completeLayers;this.checkPendingElements()},BaseRenderer.prototype.createItem=function(t){switch(t.ty){case 2:return this.createImage(t);case 0:return this.createComp(t);case 1:return this.createSolid(t);case 3:default:return this.createNull(t);case 4:return this.createShape(t);case 5:return this.createText(t);case 6:return this.createAudio(t);case 13:return this.createCamera(t);case 15:return this.createFootage(t)}},BaseRenderer.prototype.createCamera=function(){throw new Error("You're using a 3d camera. Try the html renderer.")},BaseRenderer.prototype.createAudio=function(t){return new AudioElement(t,this.globalData,this)},BaseRenderer.prototype.createFootage=function(t){return new FootageElement(t,this.globalData,this)},BaseRenderer.prototype.buildAllItems=function(){var t,e=this.layers.length;for(t=0;t0&&(this.maskElement.setAttribute("id",y),this.element.maskedElement.setAttribute(v,"url("+getLocationHref()+"#"+y+")"),a.appendChild(this.maskElement)),this.viewData.length&&this.element.addRenderableComponent(this)}TransformElement.prototype={initTransform:function(){var t=new Matrix;this.finalTransform={mProp:this.data.ks?TransformPropertyFactory.getTransformProperty(this,this.data.ks,this):{o:0},_matMdf:!1,_localMatMdf:!1,_opMdf:!1,mat:t,localMat:t,localOpacity:1},this.data.ao&&(this.finalTransform.mProp.autoOriented=!0),this.data.ty},renderTransform:function(){if(this.finalTransform._opMdf=this.finalTransform.mProp.o._mdf||this._isFirstFrame,this.finalTransform._matMdf=this.finalTransform.mProp._mdf||this._isFirstFrame,this.hierarchy){var t,e=this.finalTransform.mat,r=0,i=this.hierarchy.length;if(!this.finalTransform._matMdf)for(;r1&&(a+=" C"+e.o[i-1][0]+","+e.o[i-1][1]+" "+e.i[0][0]+","+e.i[0][1]+" "+e.v[0][0]+","+e.v[0][1]),r.lastPath!==a){var n="";r.elem&&(e.c&&(n=t.inv?this.solidPath+a:a),r.elem.setAttribute("d",n)),r.lastPath=a}},MaskElement.prototype.destroy=function(){this.element=null,this.globalData=null,this.maskElement=null,this.data=null,this.masksProperties=null};var filtersFactory=function(){var t={createFilter:function(t,e){var r=createNS("filter");return r.setAttribute("id",t),!0!==e&&(r.setAttribute("filterUnits","objectBoundingBox"),r.setAttribute("x","0%"),r.setAttribute("y","0%"),r.setAttribute("width","100%"),r.setAttribute("height","100%")),r},createAlphaToLuminanceFilter:function(){var t=createNS("feColorMatrix");return t.setAttribute("type","matrix"),t.setAttribute("color-interpolation-filters","sRGB"),t.setAttribute("values","0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 1"),t}};return t}(),featureSupport=function(){var t={maskType:!0,svgLumaHidden:!0,offscreenCanvas:"undefined"!=typeof OffscreenCanvas};return(/MSIE 10/i.test(navigator.userAgent)||/MSIE 9/i.test(navigator.userAgent)||/rv:11.0/i.test(navigator.userAgent)||/Edge\/\d./i.test(navigator.userAgent))&&(t.maskType=!1),/firefox/i.test(navigator.userAgent)&&(t.svgLumaHidden=!1),t}(),registeredEffects$1={},idPrefix="filter_result_";function SVGEffects(t){var e,r,i="SourceGraphic",s=t.data.ef?t.data.ef.length:0,a=createElementID(),n=filtersFactory.createFilter(a,!0),o=0;for(this.filters=[],e=0;e=0&&!this.shapeModifiers[t].processShapes(this._isFirstFrame);t-=1);}},searchProcessedElement:function(t){for(var e=this.processedElements,r=0,i=e.length;r.01)return!1;r+=1}return!0},GradientProperty.prototype.checkCollapsable=function(){if(this.o.length/2!=this.c.length/4)return!1;if(this.data.k.k[0].s)for(var t=0,e=this.data.k.k.length;t0;)h=i.transformers[d].mProps._mdf||h,u-=1,d-=1;if(h)for(u=y-i.styles[p].lvl,d=i.transformers.length-1;u>0;)f.multiply(i.transformers[d].mProps.v),u-=1,d-=1}else f=t;if(n=(c=i.sh.paths)._length,h){for(o="",a=0;a=1?v=.99:v<=-1&&(v=-.99);var b=o*v,_=Math.cos(g+e.a.v)*b+p[0],P=Math.sin(g+e.a.v)*b+p[1];h.setAttribute("fx",_),h.setAttribute("fy",P),l&&!e.g._collapsable&&(e.of.setAttribute("fx",_),e.of.setAttribute("fy",P))}}function h(t,e,r){var i=e.style,s=e.d;s&&(s._mdf||r)&&s.dashStr&&(i.pElem.setAttribute("stroke-dasharray",s.dashStr),i.pElem.setAttribute("stroke-dashoffset",s.dashoffset[0])),e.c&&(e.c._mdf||r)&&i.pElem.setAttribute("stroke","rgb("+bmFloor(e.c.v[0])+","+bmFloor(e.c.v[1])+","+bmFloor(e.c.v[2])+")"),(e.o._mdf||r)&&i.pElem.setAttribute("stroke-opacity",e.o.v),(e.w._mdf||r)&&(i.pElem.setAttribute("stroke-width",e.w.v),i.msElem&&i.msElem.setAttribute("stroke-width",e.w.v))}return{createRenderFunction:function(t){switch(t.ty){case"fl":return a;case"gf":return o;case"gs":return n;case"st":return h;case"sh":case"el":case"rc":case"sr":return s;case"tr":return r;case"no":return i;default:return null}}}}();function SVGShapeElement(t,e,r){this.shapes=[],this.shapesData=t.shapes,this.stylesList=[],this.shapeModifiers=[],this.itemsData=[],this.processedElements=[],this.animatedContents=[],this.initElement(t,e,r),this.prevViewData=[]}function LetterProps(t,e,r,i,s,a){this.o=t,this.sw=e,this.sc=r,this.fc=i,this.m=s,this.p=a,this._mdf={o:!0,sw:!!e,sc:!!r,fc:!!i,m:!0,p:!0}}function TextProperty(t,e){this._frameId=initialDefaultFrame,this.pv="",this.v="",this.kf=!1,this._isFirstFrame=!0,this._mdf=!1,e.d&&e.d.sid&&(e.d=t.globalData.slotManager.getProp(e.d)),this.data=e,this.elem=t,this.comp=this.elem.comp,this.keysIndex=0,this.canResize=!1,this.minimumFontSize=1,this.effectsSequence=[],this.currentData={ascent:0,boxWidth:this.defaultBoxWidth,f:"",fStyle:"",fWeight:"",fc:"",j:"",justifyOffset:"",l:[],lh:0,lineWidths:[],ls:"",of:"",s:"",sc:"",sw:0,t:0,tr:0,sz:0,ps:null,fillColorAnim:!1,strokeColorAnim:!1,strokeWidthAnim:!1,yOffset:0,finalSize:0,finalText:[],finalLineHeight:0,__complete:!1},this.copyData(this.currentData,this.data.d.k[0].s),this.searchProperty()||this.completeTextData(this.currentData)}extendPrototype([BaseElement,TransformElement,SVGBaseElement,IShapeElement,HierarchyElement,FrameElement,RenderableDOMElement],SVGShapeElement),SVGShapeElement.prototype.initSecondaryElement=function(){},SVGShapeElement.prototype.identityMatrix=new Matrix,SVGShapeElement.prototype.buildExpressionInterface=function(){},SVGShapeElement.prototype.createContent=function(){this.searchShapes(this.shapesData,this.itemsData,this.prevViewData,this.layerElement,0,[],!0),this.filterUniqueShapes()},SVGShapeElement.prototype.filterUniqueShapes=function(){var t,e,r,i,s=this.shapes.length,a=this.stylesList.length,n=[],o=!1;for(r=0;r1&&o&&this.setShapesAsAnimated(n)}},SVGShapeElement.prototype.setShapesAsAnimated=function(t){var e,r=t.length;for(e=0;e=0;o-=1){if((f=this.searchProcessedElement(t[o]))?e[o]=r[f-1]:t[o]._render=n,"fl"===t[o].ty||"st"===t[o].ty||"gf"===t[o].ty||"gs"===t[o].ty||"no"===t[o].ty)f?e[o].style.closed=!1:e[o]=this.createStyleElement(t[o],s),t[o]._render&&e[o].style.pElem.parentNode!==i&&i.appendChild(e[o].style.pElem),m.push(e[o].style);else if("gr"===t[o].ty){if(f)for(l=e[o].it.length,h=0;h1,this.kf&&this.addEffect(this.getKeyframeValue.bind(this)),this.kf},TextProperty.prototype.addEffect=function(t){this.effectsSequence.push(t),this.elem.addDynamicProperty(this)},TextProperty.prototype.getValue=function(t){if(this.elem.globalData.frameId!==this.frameId&&this.effectsSequence.length||t){this.currentData.t=this.data.d.k[this.keysIndex].s.t;var e=this.currentData,r=this.keysIndex;if(this.lock)this.setCurrentData(this.currentData);else{var i;this.lock=!0,this._mdf=!1;var s=this.effectsSequence.length,a=t||this.data.d.k[this.keysIndex].s;for(i=0;ie);)r+=1;return this.keysIndex!==r&&(this.keysIndex=r),this.data.d.k[this.keysIndex].s},TextProperty.prototype.buildFinalText=function(t){for(var e,r,i=[],s=0,a=t.length,n=!1,o=!1,h="";s=55296&&e<=56319?FontManager.isRegionalFlag(t,s)?h=t.substr(s,14):(r=t.charCodeAt(s+1))>=56320&&r<=57343&&(FontManager.isModifier(e,r)?(h=t.substr(s,2),n=!0):h=FontManager.isFlagEmoji(t.substr(s,4))?t.substr(s,4):t.substr(s,2)):e>56319?(r=t.charCodeAt(s+1),FontManager.isVariationSelector(e)&&(n=!0)):FontManager.isZeroWidthJoiner(e)&&(n=!0,o=!0),n?(i[i.length-1]+=h,n=!1):i.push(h),s+=h.length;return i},TextProperty.prototype.completeTextData=function(t){t.__complete=!0;var e,r,i,s,a,n,o,h=this.elem.globalData.fontManager,l=this.data,p=[],c=0,f=l.m.g,u=0,d=0,m=0,y=[],g=0,v=0,b=h.getFontByName(t.f),_=0,P=getFontProperties(b);t.fWeight=P.weight,t.fStyle=P.style,t.finalSize=t.s,t.finalText=this.buildFinalText(t.t),r=t.finalText.length,t.finalLineHeight=t.lh;var S,E=t.tr/1e3*t.finalSize;if(t.sz)for(var x,C,A=!0,w=t.sz[0],k=t.sz[1];A;){x=0,g=0,r=(C=this.buildFinalText(t.t)).length,E=t.tr/1e3*t.finalSize;var T=-1;for(e=0;ew&&" "!==C[e]?(-1===T?r+=1:e=T,x+=t.finalLineHeight||1.2*t.finalSize,C.splice(e,T===e?1:0,"\r"),T=-1,g=0):(g+=_,g+=E);x+=b.ascent*t.finalSize/100,this.canResize&&t.finalSize>this.minimumFontSize&&kv?g:v,g=-2*E,s="",i=!0,m+=1):s=M,h.chars?(o=h.getCharData(M,b.fStyle,h.getFontByName(t.f).fFamily),_=i?0:o.w*t.finalSize/100):_=h.measureText(s,t.f,t.finalSize)," "===M?D+=_+E:(g+=_+E+D,D=0),p.push({l:_,an:_,add:u,n:i,anIndexes:[],val:s,line:m,animatorJustifyOffset:0}),2==f){if(u+=_,""===s||" "===s||e===r-1){for(""!==s&&" "!==s||(u-=_);d<=e;)p[d].an=u,p[d].ind=c,p[d].extra=_,d+=1;c+=1,u=0}}else if(3==f){if(u+=_,""===s||e===r-1){for(""===s&&(u-=_);d<=e;)p[d].an=u,p[d].ind=c,p[d].extra=_,d+=1;u=0,c+=1}}else p[c].ind=c,p[c].extra=0,c+=1;if(t.l=p,v=g>v?g:v,y.push(g),t.sz)t.boxWidth=t.sz[0],t.justifyOffset=0;else switch(t.boxWidth=v,t.j){case 1:t.justifyOffset=-t.boxWidth;break;case 2:t.justifyOffset=-t.boxWidth/2;break;default:t.justifyOffset=0}t.lineWidths=y;var F,I,R,L,V=l.a;n=V.length;var B=[];for(a=0;a0?s=this.ne.v/100:a=-this.ne.v/100,this.xe.v>0?n=1-this.xe.v/100:o=1+this.xe.v/100;var h=BezierFactory.getBezierEasing(s,a,n,o).get,l=0,p=this.finalS,c=this.finalE,f=this.data.sh;if(2===f)l=h(l=c===p?i>=c?1:0:t(0,e(.5/(c-p)+(i-p)/(c-p),1)));else if(3===f)l=h(l=c===p?i>=c?0:1:1-t(0,e(.5/(c-p)+(i-p)/(c-p),1)));else if(4===f)c===p?l=0:(l=t(0,e(.5/(c-p)+(i-p)/(c-p),1)))<.5?l*=2:l=1-2*(l-.5),l=h(l);else if(5===f){if(c===p)l=0;else{var u=c-p,d=-u/2+(i=e(t(0,i+.5-p),c-p)),m=u/2;l=Math.sqrt(1-d*d/(m*m))}l=h(l)}else 6===f?(c===p?l=0:(i=e(t(0,i+.5-p),c-p),l=(1+Math.cos(Math.PI+2*Math.PI*i/(c-p)))/2),l=h(l)):(i>=r(p)&&(l=t(0,e(i-p<0?e(c,1)-(p-i):c-i,1))),l=h(l));if(100!==this.sm.v){var y=.01*this.sm.v;0===y&&(y=1e-8);var g=.5-.5*y;l1&&(l=1)}return l*this.a.v},getValue:function(t){this.iterateDynamicProperties(),this._mdf=t||this._mdf,this._currentTextLength=this.elem.textProperty.currentData.l.length||0,t&&2===this.data.r&&(this.e.v=this._currentTextLength);var e=2===this.data.r?1:100/this.data.totalChars,r=this.o.v/e,i=this.s.v/e+r,s=this.e.v/e+r;if(i>s){var a=i;i=s,s=a}this.finalS=i,this.finalE=s}},extendPrototype([DynamicPropertyContainer],i),{getTextSelectorProp:function(t,e,r){return new i(t,e,r)}}}();function TextAnimatorDataProperty(t,e,r){var i={propType:!1},s=PropertyFactory.getProp,a=e.a;this.a={r:a.r?s(t,a.r,0,degToRads,r):i,rx:a.rx?s(t,a.rx,0,degToRads,r):i,ry:a.ry?s(t,a.ry,0,degToRads,r):i,sk:a.sk?s(t,a.sk,0,degToRads,r):i,sa:a.sa?s(t,a.sa,0,degToRads,r):i,s:a.s?s(t,a.s,1,.01,r):i,a:a.a?s(t,a.a,1,0,r):i,o:a.o?s(t,a.o,0,.01,r):i,p:a.p?s(t,a.p,1,0,r):i,sw:a.sw?s(t,a.sw,0,0,r):i,sc:a.sc?s(t,a.sc,1,0,r):i,fc:a.fc?s(t,a.fc,1,0,r):i,fh:a.fh?s(t,a.fh,0,0,r):i,fs:a.fs?s(t,a.fs,0,.01,r):i,fb:a.fb?s(t,a.fb,0,.01,r):i,t:a.t?s(t,a.t,0,0,r):i},this.s=TextSelectorProp.getTextSelectorProp(t,e.s,r),this.s.t=e.s.t}function TextAnimatorProperty(t,e,r){this._isFirstFrame=!0,this._hasMaskedPath=!1,this._frameId=-1,this._textData=t,this._renderType=e,this._elem=r,this._animatorsData=createSizedArray(this._textData.a.length),this._pathData={},this._moreOptions={alignment:{}},this.renderedLetters=[],this.lettersChangedFlag=!1,this.initDynamicPropertyContainer(r)}function ITextElement(){}TextAnimatorProperty.prototype.searchProperties=function(){var t,e,r=this._textData.a.length,i=PropertyFactory.getProp;for(t=0;t=o+ot||!d?(v=(o+ot-l)/h.partialLength,O=u.point[0]+(h.point[0]-u.point[0])*v,$=u.point[1]+(h.point[1]-u.point[1])*v,x.translate(-P[0]*w[s].an*.005,-P[1]*L*.01),p=!1):d&&(l+=h.partialLength,(c+=1)>=d.length&&(c=0,m[f+=1]?d=m[f].points:_.v.c?(c=0,d=m[f=0].points):(l-=h.partialLength,d=null)),d&&(u=h,y=(h=d[c]).partialLength));B=w[s].an/2-w[s].add,x.translate(-B,0,0)}else B=w[s].an/2-w[s].add,x.translate(-B,0,0),x.translate(-P[0]*w[s].an*.005,-P[1]*L*.01,0);for(D=0;Dt?this.textSpans[t].span:createNS(h?"g":"text"),y<=t){if(n.setAttribute("stroke-linecap","butt"),n.setAttribute("stroke-linejoin","round"),n.setAttribute("stroke-miterlimit","4"),this.textSpans[t].span=n,h){var g=createNS("g");n.appendChild(g),this.textSpans[t].childSpan=g}this.textSpans[t].span=n,this.layerElement.appendChild(n)}n.style.display="inherit"}if(l.reset(),p&&(o[t].n&&(c=-d,f+=r.yOffset,f+=u?1:0,u=!1),this.applyTextPropertiesToMatrix(r,l,o[t].line,c,f),c+=o[t].l||0,c+=d),h){var v;if(1===(m=this.globalData.fontManager.getCharData(r.finalText[t],i.fStyle,this.globalData.fontManager.getFontByName(r.f).fFamily)).t)v=new SVGCompElement(m.data,this.globalData,this);else{var b=emptyShapeData;m.data&&m.data.shapes&&(b=this.buildShapeData(m.data,r.finalSize)),v=new SVGShapeElement(b,this.globalData,this)}if(this.textSpans[t].glyph){var _=this.textSpans[t].glyph;this.textSpans[t].childSpan.removeChild(_.layerElement),_.destroy()}this.textSpans[t].glyph=v,v._debug=!0,v.prepareFrame(0),v.renderFrame(),this.textSpans[t].childSpan.appendChild(v.layerElement),1===m.t&&this.textSpans[t].childSpan.setAttribute("transform","scale("+r.finalSize/100+","+r.finalSize/100+")")}else p&&n.setAttribute("transform","translate("+l.props[12]+","+l.props[13]+")"),n.textContent=o[t].val,n.setAttributeNS("http://www.w3.org/XML/1998/namespace","xml:space","preserve")}p&&n&&n.setAttribute("d","")}else{var P=this.textContainer,S="start";switch(r.j){case 1:S="end";break;case 2:S="middle";break;default:S="start"}P.setAttribute("text-anchor",S),P.setAttribute("letter-spacing",d);var E=this.buildTextContents(r.finalText);for(e=E.length,f=r.ps?r.ps[1]+r.ascent:0,t=0;t=0;e-=1)(this.completeLayers||this.elements[e])&&this.elements[e].prepareFrame(t-this.layers[e].st);if(this.globalData._mdf)for(e=0;e=0;r-=1)(this.completeLayers||this.elements[r])&&(this.elements[r].prepareFrame(this.renderedFrame-this.layers[r].st),this.elements[r]._mdf&&(this._mdf=!0))}},ICompElement.prototype.renderInnerContent=function(){var t,e=this.layers.length;for(t=0;t=0;r-=1)t.finalTransform.multiply(t.transforms[r].transform.mProps.v);t._mdf=s},processSequences:function(t){var e,r=this.sequenceList.length;for(e=0;e=1){this.buffers=[];var t=this.globalData.canvasContext,e=assetLoader.createCanvas(t.canvas.width,t.canvas.height);this.buffers.push(e);var r=assetLoader.createCanvas(t.canvas.width,t.canvas.height);this.buffers.push(r),this.data.tt>=3&&!document._isProxy&&assetLoader.loadLumaCanvas()}this.canvasContext=this.globalData.canvasContext,this.transformCanvas=this.globalData.transformCanvas,this.renderableEffectsManager=new CVEffects(this),this.searchEffectTransforms()},createContent:function(){},setBlendMode:function(){var t=this.globalData;if(t.blendMode!==this.data.bm){t.blendMode=this.data.bm;var e=getBlendMode(this.data.bm);t.canvasContext.globalCompositeOperation=e}},createRenderableComponents:function(){this.maskManager=new CVMaskElement(this.data,this),this.transformEffects=this.renderableEffectsManager.getEffects(effectTypes.TRANSFORM_EFFECT)},hideElement:function(){this.hidden||this.isInRange&&!this.isTransparent||(this.hidden=!0)},showElement:function(){this.isInRange&&!this.isTransparent&&(this.hidden=!1,this._isFirstFrame=!0,this.maskManager._isFirstFrame=!0)},clearCanvas:function(t){t.clearRect(this.transformCanvas.tx,this.transformCanvas.ty,this.transformCanvas.w*this.transformCanvas.sx,this.transformCanvas.h*this.transformCanvas.sy)},prepareLayer:function(){if(this.data.tt>=1){var t=this.buffers[0].getContext("2d");this.clearCanvas(t),t.drawImage(this.canvasContext.canvas,0,0),this.currentTransform=this.canvasContext.getTransform(),this.canvasContext.setTransform(1,0,0,1,0,0),this.clearCanvas(this.canvasContext),this.canvasContext.setTransform(this.currentTransform)}},exitLayer:function(){if(this.data.tt>=1){var t=this.buffers[1],e=t.getContext("2d");if(this.clearCanvas(e),e.drawImage(this.canvasContext.canvas,0,0),this.canvasContext.setTransform(1,0,0,1,0,0),this.clearCanvas(this.canvasContext),this.canvasContext.setTransform(this.currentTransform),this.comp.getElementById("tp"in this.data?this.data.tp:this.data.ind-1).renderFrame(!0),this.canvasContext.setTransform(1,0,0,1,0,0),this.data.tt>=3&&!document._isProxy){var r=assetLoader.getLumaCanvas(this.canvasContext.canvas);r.getContext("2d").drawImage(this.canvasContext.canvas,0,0),this.clearCanvas(this.canvasContext),this.canvasContext.drawImage(r,0,0)}this.canvasContext.globalCompositeOperation=operationsMap[this.data.tt],this.canvasContext.drawImage(t,0,0),this.canvasContext.globalCompositeOperation="destination-over",this.canvasContext.drawImage(this.buffers[0],0,0),this.canvasContext.setTransform(this.currentTransform),this.canvasContext.globalCompositeOperation="source-over"}},renderFrame:function(t){if(!this.hidden&&!this.data.hd&&(1!==this.data.td||t)){this.renderTransform(),this.renderRenderable(),this.renderLocalTransform(),this.setBlendMode();var e=0===this.data.ty;this.prepareLayer(),this.globalData.renderer.save(e),this.globalData.renderer.ctxTransform(this.finalTransform.localMat.props),this.globalData.renderer.ctxOpacity(this.finalTransform.localOpacity),this.renderInnerContent(),this.globalData.renderer.restore(e),this.exitLayer(),this.maskManager.hasMasks&&this.globalData.renderer.restore(!0),this._isFirstFrame&&(this._isFirstFrame=!1)}},destroy:function(){this.canvasContext=null,this.data=null,this.globalData=null,this.maskManager.destroy()},mHelper:new Matrix},CVBaseElement.prototype.hide=CVBaseElement.prototype.hideElement,CVBaseElement.prototype.show=CVBaseElement.prototype.showElement,CVShapeData.prototype.setAsAnimated=SVGShapeData.prototype.setAsAnimated,extendPrototype([BaseElement,TransformElement,CVBaseElement,IShapeElement,HierarchyElement,FrameElement,RenderableElement],CVShapeElement),CVShapeElement.prototype.initElement=RenderableDOMElement.prototype.initElement,CVShapeElement.prototype.transformHelper={opacity:1,_opMdf:!1},CVShapeElement.prototype.dashResetter=[],CVShapeElement.prototype.createContent=function(){this.searchShapes(this.shapesData,this.itemsData,this.prevViewData,!0,[])},CVShapeElement.prototype.createStyleElement=function(t,e){var r={data:t,type:t.ty,preTransforms:this.transformsManager.addTransformSequence(e),transforms:[],elements:[],closed:!0===t.hd},i={};if("fl"===t.ty||"st"===t.ty?(i.c=PropertyFactory.getProp(this,t.c,1,255,this),i.c.k||(r.co="rgb("+bmFloor(i.c.v[0])+","+bmFloor(i.c.v[1])+","+bmFloor(i.c.v[2])+")")):"gf"!==t.ty&&"gs"!==t.ty||(i.s=PropertyFactory.getProp(this,t.s,1,null,this),i.e=PropertyFactory.getProp(this,t.e,1,null,this),i.h=PropertyFactory.getProp(this,t.h||{k:0},0,.01,this),i.a=PropertyFactory.getProp(this,t.a||{k:0},0,degToRads,this),i.g=new GradientProperty(this,t.g,this)),i.o=PropertyFactory.getProp(this,t.o,0,.01,this),"st"===t.ty||"gs"===t.ty){if(r.lc=lineCapEnum[t.lc||2],r.lj=lineJoinEnum[t.lj||2],1==t.lj&&(r.ml=t.ml),i.w=PropertyFactory.getProp(this,t.w,0,null,this),i.w.k||(r.wi=i.w.v),t.d){var s=new DashProperty(this,t.d,"canvas",this);i.d=s,i.d.k||(r.da=i.d.dashArray,r.do=i.d.dashoffset[0])}}else r.r=2===t.r?"evenodd":"nonzero";return this.stylesList.push(r),i.style=r,i},CVShapeElement.prototype.createGroupElement=function(){return{it:[],prevViewData:[]}},CVShapeElement.prototype.createTransformElement=function(t){return{transform:{opacity:1,_opMdf:!1,key:this.transformsManager.getNewKey(),op:PropertyFactory.getProp(this,t.o,0,.01,this),mProps:TransformPropertyFactory.getTransformProperty(this,t,this)}}},CVShapeElement.prototype.createShapeElement=function(t){var e=new CVShapeData(this,t,this.stylesList,this.transformsManager);return this.shapes.push(e),this.addShapeToModifiers(e),e},CVShapeElement.prototype.reloadShapes=function(){var t;this._isFirstFrame=!0;var e=this.itemsData.length;for(t=0;t=0;a-=1){if((h=this.searchProcessedElement(t[a]))?e[a]=r[h-1]:t[a]._shouldRender=i,"fl"===t[a].ty||"st"===t[a].ty||"gf"===t[a].ty||"gs"===t[a].ty)h?e[a].style.closed=!1:e[a]=this.createStyleElement(t[a],d),f.push(e[a].style);else if("gr"===t[a].ty){if(h)for(o=e[a].it.length,n=0;n=0;s-=1)"tr"===e[s].ty?(a=r[s].transform,this.renderShapeTransform(t,a)):"sh"===e[s].ty||"el"===e[s].ty||"rc"===e[s].ty||"sr"===e[s].ty?this.renderPath(e[s],r[s]):"fl"===e[s].ty?this.renderFill(e[s],r[s],a):"st"===e[s].ty?this.renderStroke(e[s],r[s],a):"gf"===e[s].ty||"gs"===e[s].ty?this.renderGradientFill(e[s],r[s],a):"gr"===e[s].ty?this.renderShape(a,e[s].it,r[s].it):e[s].ty;i&&this.drawLayer()},CVShapeElement.prototype.renderStyledShape=function(t,e){if(this._isFirstFrame||e._mdf||t.transforms._mdf){var r,i,s,a=t.trNodes,n=e.paths,o=n._length;a.length=0;var h=t.transforms.finalTransform;for(s=0;s=1?c=.99:c<=-1&&(c=-.99);var f=l*c,u=Math.cos(p+e.a.v)*f+o[0],d=Math.sin(p+e.a.v)*f+o[1];i=n.createRadialGradient(u,d,0,o[0],o[1],l)}var m=t.g.p,y=e.g.c,g=1;for(a=0;ao&&"xMidYMid slice"===h||ns&&"meet"===o||as&&"slice"===o)?(r-this.transformCanvas.w*(i/this.transformCanvas.h))/2*this.renderConfig.dpr:"xMax"===l&&(as&&"slice"===o)?(r-this.transformCanvas.w*(i/this.transformCanvas.h))*this.renderConfig.dpr:0,this.transformCanvas.ty="YMid"===p&&(a>s&&"meet"===o||as&&"meet"===o||a=0;t-=1)this.elements[t]&&this.elements[t].destroy&&this.elements[t].destroy();this.elements.length=0,this.globalData.canvasContext=null,this.animationItem.container=null,this.destroyed=!0},CanvasRendererBase.prototype.renderFrame=function(t,e){if((this.renderedFrame!==t||!0!==this.renderConfig.clearCanvas||e)&&!this.destroyed&&-1!==t){var r;this.renderedFrame=t,this.globalData.frameNum=t-this.animationItem._isFirstFrame,this.globalData.frameId+=1,this.globalData._mdf=!this.renderConfig.clearCanvas||e,this.globalData.projectInterface.currentFrame=t;var i=this.layers.length;for(this.completeLayers||this.checkLayers(t),r=i-1;r>=0;r-=1)(this.completeLayers||this.elements[r])&&this.elements[r].prepareFrame(t-this.layers[r].st);if(this.globalData._mdf){for(!0===this.renderConfig.clearCanvas?this.canvasContext.clearRect(0,0,this.transformCanvas.w,this.transformCanvas.h):this.save(),r=i-1;r>=0;r-=1)(this.completeLayers||this.elements[r])&&this.elements[r].renderFrame();!0!==this.renderConfig.clearCanvas&&this.restore()}}},CanvasRendererBase.prototype.buildItem=function(t){var e=this.elements;if(!e[t]&&99!==this.layers[t].ty){var r=this.createItem(this.layers[t],this,this.globalData);e[t]=r,r.initExpressions()}},CanvasRendererBase.prototype.checkPendingElements=function(){for(;this.pendingElements.length;)this.pendingElements.pop().checkParenting()},CanvasRendererBase.prototype.hide=function(){this.animationItem.container.style.display="none"},CanvasRendererBase.prototype.show=function(){this.animationItem.container.style.display="block"},CVContextData.prototype.duplicate=function(){var t=2*this._length,e=0;for(e=this._length;e=0;t-=1)(this.completeLayers||this.elements[t])&&this.elements[t].renderFrame()},CVCompElement.prototype.destroy=function(){var t;for(t=this.layers.length-1;t>=0;t-=1)this.elements[t]&&this.elements[t].destroy();this.layers=null,this.elements=null},CVCompElement.prototype.createComp=function(t){return new CVCompElement(t,this.globalData,this)},extendPrototype([CanvasRendererBase],CanvasRenderer),CanvasRenderer.prototype.createComp=function(t){return new CVCompElement(t,this.globalData,this)},HBaseElement.prototype={checkBlendMode:function(){},initRendererElement:function(){this.baseElement=createTag(this.data.tg||"div"),this.data.hasMask?(this.svgElement=createNS("svg"),this.layerElement=createNS("g"),this.maskedElement=this.layerElement,this.svgElement.appendChild(this.layerElement),this.baseElement.appendChild(this.svgElement)):this.layerElement=this.baseElement,styleDiv(this.baseElement)},createContainerElements:function(){this.renderableEffectsManager=new CVEffects(this),this.transformedElement=this.baseElement,this.maskedElement=this.layerElement,this.data.ln&&this.layerElement.setAttribute("id",this.data.ln),this.data.cl&&this.layerElement.setAttribute("class",this.data.cl),0!==this.data.bm&&this.setBlendMode()},renderElement:function(){var t=this.transformedElement?this.transformedElement.style:{};if(this.finalTransform._matMdf){var e=this.finalTransform.mat.toCSS();t.transform=e,t.webkitTransform=e}this.finalTransform._opMdf&&(t.opacity=this.finalTransform.mProp.o.v)},renderFrame:function(){this.data.hd||this.hidden||(this.renderTransform(),this.renderRenderable(),this.renderElement(),this.renderInnerContent(),this._isFirstFrame&&(this._isFirstFrame=!1))},destroy:function(){this.layerElement=null,this.transformedElement=null,this.matteElement&&(this.matteElement=null),this.maskManager&&(this.maskManager.destroy(),this.maskManager=null)},createRenderableComponents:function(){this.maskManager=new MaskElement(this.data,this,this.globalData)},addEffects:function(){},setMatte:function(){}},HBaseElement.prototype.getBaseElement=SVGBaseElement.prototype.getBaseElement,HBaseElement.prototype.destroyBaseElement=HBaseElement.prototype.destroy,HBaseElement.prototype.buildElementParenting=BaseRenderer.prototype.buildElementParenting,extendPrototype([BaseElement,TransformElement,HBaseElement,HierarchyElement,FrameElement,RenderableDOMElement],HSolidElement),HSolidElement.prototype.createContent=function(){var t;this.data.hasMask?((t=createNS("rect")).setAttribute("width",this.data.sw),t.setAttribute("height",this.data.sh),t.setAttribute("fill",this.data.sc),this.svgElement.setAttribute("width",this.data.sw),this.svgElement.setAttribute("height",this.data.sh)):((t=createTag("div")).style.width=this.data.sw+"px",t.style.height=this.data.sh+"px",t.style.backgroundColor=this.data.sc),this.layerElement.appendChild(t)},extendPrototype([BaseElement,TransformElement,HSolidElement,SVGShapeElement,HBaseElement,HierarchyElement,FrameElement,RenderableElement],HShapeElement),HShapeElement.prototype._renderShapeFrame=HShapeElement.prototype.renderInnerContent,HShapeElement.prototype.createContent=function(){var t;if(this.baseElement.style.fontSize=0,this.data.hasMask)this.layerElement.appendChild(this.shapesContainer),t=this.svgElement;else{t=createNS("svg");var e=this.comp.data?this.comp.data:this.globalData.compSize;t.setAttribute("width",e.w),t.setAttribute("height",e.h),t.appendChild(this.shapesContainer),this.layerElement.appendChild(t)}this.searchShapes(this.shapesData,this.itemsData,this.prevViewData,this.shapesContainer,0,[],!0),this.filterUniqueShapes(),this.shapeCont=t},HShapeElement.prototype.getTransformedPoint=function(t,e){var r,i=t.length;for(r=0;r0&&o<1&&c[f].push(this.calculateF(o,t,e,r,i,f)):(h=a*a-4*n*s)>=0&&((l=(-a+bmSqrt(h))/(2*s))>0&&l<1&&c[f].push(this.calculateF(l,t,e,r,i,f)),(p=(-a-bmSqrt(h))/(2*s))>0&&p<1&&c[f].push(this.calculateF(p,t,e,r,i,f))));this.shapeBoundingBox.left=bmMin.apply(null,c[0]),this.shapeBoundingBox.top=bmMin.apply(null,c[1]),this.shapeBoundingBox.right=bmMax.apply(null,c[0]),this.shapeBoundingBox.bottom=bmMax.apply(null,c[1])},HShapeElement.prototype.calculateF=function(t,e,r,i,s,a){return bmPow(1-t,3)*e[a]+3*bmPow(1-t,2)*t*r[a]+3*(1-t)*bmPow(t,2)*i[a]+bmPow(t,3)*s[a]},HShapeElement.prototype.calculateBoundingBox=function(t,e){var r,i=t.length;for(r=0;rr&&(r=s)}r*=t.mult}else r=t.v*t.mult;e.x-=r,e.xMax+=r,e.y-=r,e.yMax+=r},HShapeElement.prototype.currentBoxContains=function(t){return this.currentBBox.x<=t.x&&this.currentBBox.y<=t.y&&this.currentBBox.width+this.currentBBox.x>=t.x+t.width&&this.currentBBox.height+this.currentBBox.y>=t.y+t.height},HShapeElement.prototype.renderInnerContent=function(){if(this._renderShapeFrame(),!this.hidden&&(this._isFirstFrame||this._mdf)){var t=this.tempBoundingBox,e=999999;if(t.x=e,t.xMax=-e,t.y=e,t.yMax=-e,this.calculateBoundingBox(this.itemsData,t),t.width=t.xMax=0;t-=1){var i=this.hierarchy[t].finalTransform.mProp;this.mat.translate(-i.p.v[0],-i.p.v[1],i.p.v[2]),this.mat.rotateX(-i.or.v[0]).rotateY(-i.or.v[1]).rotateZ(i.or.v[2]),this.mat.rotateX(-i.rx.v).rotateY(-i.ry.v).rotateZ(i.rz.v),this.mat.scale(1/i.s.v[0],1/i.s.v[1],1/i.s.v[2]),this.mat.translate(i.a.v[0],i.a.v[1],i.a.v[2])}if(this.p?this.mat.translate(-this.p.v[0],-this.p.v[1],this.p.v[2]):this.mat.translate(-this.px.v,-this.py.v,this.pz.v),this.a){var s;s=this.p?[this.p.v[0]-this.a.v[0],this.p.v[1]-this.a.v[1],this.p.v[2]-this.a.v[2]]:[this.px.v-this.a.v[0],this.py.v-this.a.v[1],this.pz.v-this.a.v[2]];var a=Math.sqrt(Math.pow(s[0],2)+Math.pow(s[1],2)+Math.pow(s[2],2)),n=[s[0]/a,s[1]/a,s[2]/a],o=Math.sqrt(n[2]*n[2]+n[0]*n[0]),h=Math.atan2(n[1],o),l=Math.atan2(n[0],-n[2]);this.mat.rotateY(l).rotateX(-h)}this.mat.rotateX(-this.rx.v).rotateY(-this.ry.v).rotateZ(this.rz.v),this.mat.rotateX(-this.or.v[0]).rotateY(-this.or.v[1]).rotateZ(this.or.v[2]),this.mat.translate(this.globalData.compSize.w/2,this.globalData.compSize.h/2,0),this.mat.translate(0,0,this.pe.v);var p=!this._prevMat.equals(this.mat);if((p||this.pe._mdf)&&this.comp.threeDElements){var c,f,u;for(e=this.comp.threeDElements.length,t=0;t=t)return this.threeDElements[e].perspectiveElem;e+=1}return null},HybridRendererBase.prototype.createThreeDContainer=function(t,e){var r,i,s=createTag("div");styleDiv(s);var a=createTag("div");if(styleDiv(a),"3d"===e){(r=s.style).width=this.globalData.compSize.w+"px",r.height=this.globalData.compSize.h+"px";var n="50% 50%";r.webkitTransformOrigin=n,r.mozTransformOrigin=n,r.transformOrigin=n;var o="matrix3d(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)";(i=a.style).transform=o,i.webkitTransform=o}s.appendChild(a);var h={container:a,perspectiveElem:s,startPos:t,endPos:t,type:e};return this.threeDElements.push(h),h},HybridRendererBase.prototype.build3dContainers=function(){var t,e,r=this.layers.length,i="";for(t=0;t=0;t-=1)this.resizerElem.appendChild(this.threeDElements[t].perspectiveElem)},HybridRendererBase.prototype.addTo3dContainer=function(t,e){for(var r=0,i=this.threeDElements.length;rn?(t=s/this.globalData.compSize.w,e=s/this.globalData.compSize.w,r=0,i=(a-this.globalData.compSize.h*(s/this.globalData.compSize.w))/2):(t=a/this.globalData.compSize.h,e=a/this.globalData.compSize.h,r=(s-this.globalData.compSize.w*(a/this.globalData.compSize.h))/2,i=0);var o=this.resizerElem.style;o.webkitTransform="matrix3d("+t+",0,0,0,0,"+e+",0,0,0,0,1,0,"+r+","+i+",0,1)",o.transform=o.webkitTransform},HybridRendererBase.prototype.renderFrame=SVGRenderer.prototype.renderFrame,HybridRendererBase.prototype.hide=function(){this.resizerElem.style.display="none"},HybridRendererBase.prototype.show=function(){this.resizerElem.style.display="block"},HybridRendererBase.prototype.initItems=function(){if(this.buildAllItems(),this.camera)this.camera.setup();else{var t,e=this.globalData.compSize.w,r=this.globalData.compSize.h,i=this.threeDElements.length;for(t=0;t=n;)t/=2,e/=2,r>>>=1;return(t+r)/e};return v.int32=function(){return 0|g.g(4)},v.quick=function(){return g.g(4)/4294967296},v.double=v,c(f(g.S),t),(u.pass||d||function(t,r,i,s){return s&&(s.S&&l(s,g),t.state=function(){return l(g,{})}),i?(e.random=t,r):t})(v,y,"global"in u?u.global:this==e,u.state)},c(e.random(),t)}function initialize$2(t){seedRandom([],t)}var propTypes={SHAPE:"shape"};function _typeof$1(t){return _typeof$1="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},_typeof$1(t)}var ExpressionManager=function(){var ob={},Math=BMMath,window=null,document=null,XMLHttpRequest=null,fetch=null,frames=null,_lottieGlobal={};function resetFrame(){_lottieGlobal={}}function $bm_isInstanceOfArray(t){return t.constructor===Array||t.constructor===Float32Array}function isNumerable(t,e){return"number"===t||e instanceof Number||"boolean"===t||"string"===t}function $bm_neg(t){var e=_typeof$1(t);if("number"===e||t instanceof Number||"boolean"===e)return-t;if($bm_isInstanceOfArray(t)){var r,i=t.length,s=[];for(r=0;rr){var i=r;r=e,e=i}return Math.min(Math.max(t,e),r)}function radiansToDegrees(t){return t/degToRads}var radians_to_degrees=radiansToDegrees;function degreesToRadians(t){return t*degToRads}var degrees_to_radians=radiansToDegrees,helperLengthArray=[0,0,0,0,0,0];function length(t,e){if("number"==typeof t||t instanceof Number)return e=e||0,Math.abs(t-e);var r;e||(e=helperLengthArray);var i=Math.min(t.length,e.length),s=0;for(r=0;r.5?l/(2-n-o):l/(n+o),n){case i:e=(s-a)/l+(s1&&(r-=1),r<1/6?t+6*(e-t)*r:r<.5?e:r<2/3?t+(e-t)*(2/3-r)*6:t}function hslToRgb(t){var e,r,i,s=t[0],a=t[1],n=t[2];if(0===a)e=n,i=n,r=n;else{var o=n<.5?n*(1+a):n+a-n*a,h=2*n-o;e=hue2rgb(h,o,s+1/3),r=hue2rgb(h,o,s),i=hue2rgb(h,o,s-1/3)}return[e,r,i,t[3]]}function linear(t,e,r,i,s){if(void 0!==i&&void 0!==s||(i=e,s=r,e=0,r=1),r=r)return s;var n,o=r===e?0:(t-e)/(r-e);if(!i.length)return i+(s-i)*o;var h=i.length,l=createTypedArray("float32",h);for(n=0;n1){for(i=0;i1?e=1:e<0&&(e=0);var n=t(e);if($bm_isInstanceOfArray(s)){var o,h=s.length,l=createTypedArray("float32",h);for(o=0;odata.k[e].t&&tdata.k[e+1].t-t?(r=e+2,i=data.k[e+1].t):(r=e+1,i=data.k[e].t);break}}-1===r&&(r=e+1,i=data.k[e].t)}else r=0,i=0;var a={};return a.index=r,a.time=i/elem.comp.globalData.frameRate,a}function key(t){var e,r,i;if(!data.k.length||"number"==typeof data.k[0])throw new Error("The property has no keyframe at index "+t);t-=1,e={time:data.k[t].t/elem.comp.globalData.frameRate,value:[]};var s=Object.prototype.hasOwnProperty.call(data.k[t],"s")?data.k[t].s:data.k[t-1].e;for(i=s.length,r=0;rl.length-1)&&(e=l.length-1),i=p-(s=l[l.length-1-e].t)),"pingpong"===t){if(Math.floor((h-s)/i)%2!=0)return this.getValueAtTime((i-(h-s)%i+s)/this.comp.globalData.frameRate,0)}else{if("offset"===t){var c=this.getValueAtTime(s/this.comp.globalData.frameRate,0),f=this.getValueAtTime(p/this.comp.globalData.frameRate,0),u=this.getValueAtTime(((h-s)%i+s)/this.comp.globalData.frameRate,0),d=Math.floor((h-s)/i);if(this.pv.length){for(n=(o=new Array(c.length)).length,a=0;a=p)return this.pv;if(r?s=p+(i=e?Math.abs(this.elem.comp.globalData.frameRate*e):Math.max(0,this.elem.data.op-p)):((!e||e>l.length-1)&&(e=l.length-1),i=(s=l[e].t)-p),"pingpong"===t){if(Math.floor((p-h)/i)%2==0)return this.getValueAtTime(((p-h)%i+p)/this.comp.globalData.frameRate,0)}else{if("offset"===t){var c=this.getValueAtTime(p/this.comp.globalData.frameRate,0),f=this.getValueAtTime(s/this.comp.globalData.frameRate,0),u=this.getValueAtTime((i-(p-h)%i+p)/this.comp.globalData.frameRate,0),d=Math.floor((p-h)/i)+1;if(this.pv.length){for(n=(o=new Array(c.length)).length,a=0;a1?(s+t-a)/(e-1):1,o=0,h=0;for(r=this.pv.length?createTypedArray("float32",this.pv.length):0;on){var p=o,c=r.c&&o===h-1?0:o+1,f=(n-l)/a[o].addedLength;i=bez.getPointInSegment(r.v[p],r.v[c],r.o[p],r.i[c],f,a[o]);break}l+=a[o].addedLength,o+=1}return i||(i=r.c?[r.v[0][0],r.v[0][1]]:[r.v[r._length-1][0],r.v[r._length-1][1]]),i},vectorOnPath:function(t,e,r){1==t?t=this.v.c:0==t&&(t=.999);var i=this.pointOnPath(t,e),s=this.pointOnPath(t+.001,e),a=s[0]-i[0],n=s[1]-i[1],o=Math.sqrt(Math.pow(a,2)+Math.pow(n,2));return 0===o?[0,0]:"tangent"===r?[a/o,n/o]:[-n/o,a/o]},tangentOnPath:function(t,e){return this.vectorOnPath(t,e,"tangent")},normalOnPath:function(t,e){return this.vectorOnPath(t,e,"normal")},setGroupProperty:expressionHelpers.setGroupProperty,getValueAtTime:expressionHelpers.getStaticValueAtTime},extendPrototype([l],o),extendPrototype([l],h),h.prototype.getValueAtTime=function(t){return this._cachingAtTime||(this._cachingAtTime={shapeValue:shapePool.clone(this.pv),lastIndex:0,lastTime:initialDefaultFrame}),t*=this.elem.globalData.frameRate,(t-=this.offsetTime)!==this._cachingAtTime.lastTime&&(this._cachingAtTime.lastIndex=this._cachingAtTime.lastTime=l?u<0?i:s:i+f*Math.pow((a-t)/u,1/r),p[c]=n,c+=1,o+=256/255;return p.join(" ")},SVGProLevelsFilter.prototype.renderFrame=function(t){if(t||this.filterManager._mdf){var e,r=this.filterManager.effectElements;this.feFuncRComposed&&(t||r[3].p._mdf||r[4].p._mdf||r[5].p._mdf||r[6].p._mdf||r[7].p._mdf)&&(e=this.getTableValue(r[3].p.v,r[4].p.v,r[5].p.v,r[6].p.v,r[7].p.v),this.feFuncRComposed.setAttribute("tableValues",e),this.feFuncGComposed.setAttribute("tableValues",e),this.feFuncBComposed.setAttribute("tableValues",e)),this.feFuncR&&(t||r[10].p._mdf||r[11].p._mdf||r[12].p._mdf||r[13].p._mdf||r[14].p._mdf)&&(e=this.getTableValue(r[10].p.v,r[11].p.v,r[12].p.v,r[13].p.v,r[14].p.v),this.feFuncR.setAttribute("tableValues",e)),this.feFuncG&&(t||r[17].p._mdf||r[18].p._mdf||r[19].p._mdf||r[20].p._mdf||r[21].p._mdf)&&(e=this.getTableValue(r[17].p.v,r[18].p.v,r[19].p.v,r[20].p.v,r[21].p.v),this.feFuncG.setAttribute("tableValues",e)),this.feFuncB&&(t||r[24].p._mdf||r[25].p._mdf||r[26].p._mdf||r[27].p._mdf||r[28].p._mdf)&&(e=this.getTableValue(r[24].p.v,r[25].p.v,r[26].p.v,r[27].p.v,r[28].p.v),this.feFuncB.setAttribute("tableValues",e)),this.feFuncA&&(t||r[31].p._mdf||r[32].p._mdf||r[33].p._mdf||r[34].p._mdf||r[35].p._mdf)&&(e=this.getTableValue(r[31].p.v,r[32].p.v,r[33].p.v,r[34].p.v,r[35].p.v),this.feFuncA.setAttribute("tableValues",e))}},extendPrototype([SVGComposableEffect],SVGDropShadowEffect),SVGDropShadowEffect.prototype.renderFrame=function(t){if(t||this.filterManager._mdf){if((t||this.filterManager.effectElements[4].p._mdf)&&this.feGaussianBlur.setAttribute("stdDeviation",this.filterManager.effectElements[4].p.v/4),t||this.filterManager.effectElements[0].p._mdf){var e=this.filterManager.effectElements[0].p.v;this.feFlood.setAttribute("flood-color",rgbToHex(Math.round(255*e[0]),Math.round(255*e[1]),Math.round(255*e[2])))}if((t||this.filterManager.effectElements[1].p._mdf)&&this.feFlood.setAttribute("flood-opacity",this.filterManager.effectElements[1].p.v/255),t||this.filterManager.effectElements[2].p._mdf||this.filterManager.effectElements[3].p._mdf){var r=this.filterManager.effectElements[3].p.v,i=(this.filterManager.effectElements[2].p.v-90)*degToRads,s=r*Math.cos(i),a=r*Math.sin(i);this.feOffset.setAttribute("dx",s),this.feOffset.setAttribute("dy",a)}}};var _svgMatteSymbols=[];function SVGMatte3Effect(t,e,r){this.initialized=!1,this.filterManager=e,this.filterElem=t,this.elem=r,r.matteElement=createNS("g"),r.matteElement.appendChild(r.layerElement),r.matteElement.appendChild(r.transformedElement),r.baseElement=r.matteElement}function SVGGaussianBlurEffect(t,e,r,i){t.setAttribute("x","-100%"),t.setAttribute("y","-100%"),t.setAttribute("width","300%"),t.setAttribute("height","300%"),this.filterManager=e;var s=createNS("feGaussianBlur");s.setAttribute("result",i),t.appendChild(s),this.feGaussianBlur=s}function TransformEffect(){}function SVGTransformEffect(t,e){this.init(e)}function CVTransformEffect(t){this.init(t)}return SVGMatte3Effect.prototype.findSymbol=function(t){for(var e=0,r=_svgMatteSymbols.length;eObject.prototype.hasOwnProperty.call(t,e)))}function fromURL(t){return _fromURL.apply(this,arguments)}function _fromURL(){return(_fromURL=_asyncToGenerator((function*(t){if("string"!=typeof t)throw new Error("The url value must be a string");var e;try{var r=new URL(t),i=yield fetch(r.toString());e=yield i.json()}catch(t){throw new Error("An error occurred while trying to load the Lottie file from URL")}return e}))).apply(this,arguments)}exports.PlayerState=void 0,PlayerState=exports.PlayerState||(exports.PlayerState={}),PlayerState.Destroyed="destroyed",PlayerState.Error="error",PlayerState.Frozen="frozen",PlayerState.Loading="loading",PlayerState.Paused="paused",PlayerState.Playing="playing",PlayerState.Stopped="stopped",exports.PlayMode=void 0,PlayMode=exports.PlayMode||(exports.PlayMode={}),PlayMode.Bounce="bounce",PlayMode.Normal="normal",exports.PlayerEvents=void 0,PlayerEvents=exports.PlayerEvents||(exports.PlayerEvents={}),PlayerEvents.Complete="complete",PlayerEvents.Destroyed="destroyed",PlayerEvents.Error="error",PlayerEvents.Frame="frame",PlayerEvents.Freeze="freeze",PlayerEvents.Load="load",PlayerEvents.Loop="loop",PlayerEvents.Pause="pause",PlayerEvents.Play="play",PlayerEvents.Ready="ready",PlayerEvents.Rendered="rendered",PlayerEvents.Stop="stop",exports.LottiePlayer=class extends s{constructor(){super(...arguments),this.autoplay=!1,this.background="transparent",this.controls=!1,this.currentState=exports.PlayerState.Loading,this.description="Lottie animation",this.direction=1,this.disableCheck=!1,this.disableShadowDOM=!1,this.hover=!1,this.intermission=1,this.loop=!1,this.mode=exports.PlayMode.Normal,this.preserveAspectRatio="xMidYMid meet",this.renderer="svg",this.speed=1,this._io=void 0,this._counter=1,this._onVisibilityChange=()=>{!0===document.hidden&&this.currentState===exports.PlayerState.Playing?this.freeze():this.currentState===exports.PlayerState.Frozen&&this.play()}}load(t){var e=this;return _asyncToGenerator((function*(){var r={container:e.container,loop:!1,autoplay:!1,renderer:e.renderer,rendererSettings:Object.assign({preserveAspectRatio:e.preserveAspectRatio,clearCanvas:!1,progressiveLoad:!0,hideOnTransparent:!0},e.viewBoxSize&&{viewBoxSize:e.viewBoxSize})};try{var i=parseSrc(t),s={},a="string"==typeof i?"path":"animationData";e._lottie&&e._lottie.destroy(),e.webworkers&&lottie$1.exports.useWebWorker(!0),e._lottie=lottie$1.exports.loadAnimation(Object.assign(Object.assign({},r),{[a]:i})),e._attachEventListeners(),e.disableCheck||("path"===a?(s=yield fromURL(i),a="animationData"):s=i,isLottie(s)||(e.currentState=exports.PlayerState.Error,e.dispatchEvent(new CustomEvent(exports.PlayerEvents.Error))))}catch(t){e.currentState=exports.PlayerState.Error,e.dispatchEvent(new CustomEvent(exports.PlayerEvents.Error))}}))()}getLottie(){return this._lottie}getVersions(){return{lottieWebVersion:LOTTIE_WEB_VERSION,lottiePlayerVersion:LOTTIE_PLAYER_VERSION}}play(){this._lottie&&(this._lottie.play(),this.currentState=exports.PlayerState.Playing,this.dispatchEvent(new CustomEvent(exports.PlayerEvents.Play)))}pause(){this._lottie&&(this._lottie.pause(),this.currentState=exports.PlayerState.Paused,this.dispatchEvent(new CustomEvent(exports.PlayerEvents.Pause)))}stop(){this._lottie&&(this._counter=1,this._lottie.stop(),this.currentState=exports.PlayerState.Stopped,this.dispatchEvent(new CustomEvent(exports.PlayerEvents.Stop)))}destroy(){this._lottie&&(this._lottie.destroy(),this._lottie=null,this.currentState=exports.PlayerState.Destroyed,this.dispatchEvent(new CustomEvent(exports.PlayerEvents.Destroyed)),this.remove())}seek(t){if(this._lottie){var e=/^(\d+)(%?)$/.exec(t.toString());if(e){var r="%"===e[2]?this._lottie.totalFrames*Number(e[1])/100:Number(e[1]);this.seeker=r,this.currentState===exports.PlayerState.Playing?this._lottie.goToAndPlay(r,!0):(this._lottie.goToAndStop(r,!0),this._lottie.pause())}}}snapshot(){var t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];if(this.shadowRoot){var e=this.shadowRoot.querySelector(".animation svg"),r=(new XMLSerializer).serializeToString(e);if(t){var i=document.createElement("a");i.href="data:image/svg+xml;charset=utf-8,".concat(encodeURIComponent(r)),i.download="download_".concat(this.seeker,".svg"),document.body.appendChild(i),i.click(),document.body.removeChild(i)}return r}}setSpeed(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1;this._lottie&&this._lottie.setSpeed(t)}setDirection(t){this._lottie&&this._lottie.setDirection(t)}setLooping(t){this._lottie&&(this.loop=t,this._lottie.loop=t)}togglePlay(){return this.currentState===exports.PlayerState.Playing?this.pause():this.play()}toggleLooping(){this.setLooping(!this.loop)}resize(){this._lottie&&this._lottie.resize()}static get styles(){return styles}disconnectedCallback(){this.isConnected||(this._io&&(this._io.disconnect(),this._io=void 0),document.removeEventListener("visibilitychange",this._onVisibilityChange),this.destroy())}render(){var t=this.controls?"main controls":"main",e=this.controls?"animation controls":"animation";return $(_templateObject||(_templateObject=_taggedTemplateLiteral([' \n \n ',"\n \n ","\n "])),t,this.description,e,this.background,this.currentState===exports.PlayerState.Error?$(_templateObject2||(_templateObject2=_taggedTemplateLiteral(['
⚠️
']))):void 0,this.controls&&!this.disableShadowDOM?this.renderControls():void 0)}createRenderRoot(){return this.disableShadowDOM&&(this.style.display="block"),this.disableShadowDOM?this:super.createRenderRoot()}firstUpdated(){"IntersectionObserver"in window&&(this._io=new IntersectionObserver((t=>{t[0].isIntersecting?this.currentState===exports.PlayerState.Frozen&&this.play():this.currentState===exports.PlayerState.Playing&&this.freeze()})),this._io.observe(this.container)),void 0!==document.hidden&&document.addEventListener("visibilitychange",this._onVisibilityChange),this.src&&this.load(this.src),this.dispatchEvent(new CustomEvent(exports.PlayerEvents.Rendered))}renderControls(){var t=this.currentState===exports.PlayerState.Playing,e=this.currentState===exports.PlayerState.Paused,r=this.currentState===exports.PlayerState.Stopped;return $(_templateObject3||(_templateObject3=_taggedTemplateLiteral(['\n \n \n ','\n \n \n \n \n \n \n \n \n \n '])),this.togglePlay,t||e?"active":"",$(t?_templateObject4||(_templateObject4=_taggedTemplateLiteral(['