diff --git a/docs/tutorials/complete_applications/scenario_management_overview/index.md b/docs/tutorials/complete_applications/scenario_management_overview/index.md index be9b38a89..883e3bcd9 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/index.md +++ b/docs/tutorials/complete_applications/scenario_management_overview/index.md @@ -1,24 +1,18 @@ -# Getting Started with Taipy Core - !!! important "Supported Python versions" Taipy requires **Python 3.8** or newer. -Welcome to the **Getting Started Core** guide for Taipy Core. This tour shows you how to use Taipy Core. - +Welcome to the **Tutorial** guide for scenario management. -# Taipy Core +Taipy facilitates pipeline orchestration. There are a lot of reasons for using Taipy backend: -Taipy Core is one of the components of Taipy to facilitate pipeline orchestration. There are a lot of reasons for using Taipy Core: +- Taipy efficiently manages the execution of your functions/pipelines. -- Taipy Core efficiently manages the execution of your functions/pipelines. +- Taipy manages data sources and monitors KPIs. -- Taipy Core manages data sources and monitors KPIs. +- Taipy provides easy management of multiple pipelines and end-user scenarios, which comes in handy in the context of Machine Learning or Mathematical optimization. -- Taipy Core provides easy management of multiple pipelines and end-user scenarios, which comes in handy in the context of Machine Learning or Mathematical optimization. - -Each step of the **"Getting Started Core"** will focus on basic concepts of *Taipy Core*. Note that every step is dependent on the code of the previous one. After completing the last step, you will have the skills to develop your own Taipy -application. +Each step of the **"Tutorial"** will focus on basic concepts of *Taipy Core*. ## Before we begin @@ -36,34 +30,31 @@ $ pip install taipy [Python installation guide](http://docs.python-guide.org/en/latest/starting/installation/) can guide you through the process. -## Using Notebooks - -This **Getting Started** is for Python scripts (*.py*) only. If you want to use **Jupyter Notebooks**, download this [notebook](https://docs.taipy.io/en/latest/getting_started/getting-started-core/getting_started.ipynb). ## Taipy Studio -There are two ways to configure Taipy Core, either by Python code or with Taipy Studio. We strongly recommend using Taipy Studio. +There are two ways to configure Taipy backend (Taipy Core), either by Python code or with Taipy Studio. We strongly recommend using Taipy Studio. Taipy Studio is a VS Code extension that provides a graphical editor to describe pipelines. The configuration of Taipy Core can be done more easily and quickly through Taipy Studio. So, without further delay, let's begin to code! -## Steps +## Concepts -1. [Configuration and execution](step_01/ReadMe.md) +1. [Configuration and execution](step_01/step_01.md) -2. [Basic functions](step_02/ReadMe.md) +2. [Basic functions](step_02/step_02.md) -3. [Data Node types](step_03/ReadMe.md) +3. [Data Node types](step_03/step_03.md) -4. [Cycles](step_04/ReadMe.md) +4. [Cycles](step_04/step_04.md) -5. [Scopes](step_05/ReadMe.md) +5. [Scopes](step_05/step_05.md) -6. [Skipping tasks](step_06/ReadMe.md) +6. [Skipping tasks](step_06/step_06.md) -7. [Execution modes](step_07/ReadMe.md) +7. [Execution modes](step_07/step_07.md) -8. [Scenario comparison](step_08/ReadMe.md) +8. [Scenario comparison](step_08/step_08.md) -9. [Scenario subscription](step_09/ReadMe.md) +9. [Scenario subscription](step_09/step_09.md) diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/config_01.toml b/docs/tutorials/complete_applications/scenario_management_overview/src/config_01.toml index 1f9f1649a..2d81bccff 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/config_01.toml +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/config_01.toml @@ -1,22 +1,21 @@ [TAIPY] -[DATA_NODE.input] -scope = "SCENARIO:SCOPE" -default_data = "21:int" +[DATA_NODE.historical_temperature] -[DATA_NODE.output] -scope = "SCENARIO:SCOPE" +[DATA_NODE.date_to_forecast] -[TASK.double] -inputs = [ "input:SECTION",] -function = "__main__.double:function" -outputs = [ "output:SECTION",] -skippable = "False:bool" +[DATA_NODE.predictions] -[PIPELINE.my_pipeline] -tasks = [ "double:SECTION",] +[TASK.predict] +function = "__main__.predict:function" +inputs = [ "historical_temperature:SECTION", "date_to_forecast:SECTION",] +outputs = [ "predictions:SECTION",] +skippable = "False:bool" [SCENARIO.my_scenario] -pipelines = [ "my_pipeline:SECTION",] +tasks = [ "predict:SECTION",] +additional_data_nodes = [] [SCENARIO.my_scenario.comparators] + +[SCENARIO.my_scenario.sequences] diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/config_02.toml b/docs/tutorials/complete_applications/scenario_management_overview/src/config_02.toml index 1f9f1649a..d69d91a6e 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/config_02.toml +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/config_02.toml @@ -1,22 +1,20 @@ [TAIPY] [DATA_NODE.input] -scope = "SCENARIO:SCOPE" default_data = "21:int" [DATA_NODE.output] -scope = "SCENARIO:SCOPE" [TASK.double] -inputs = [ "input:SECTION",] function = "__main__.double:function" +inputs = [ "input:SECTION",] outputs = [ "output:SECTION",] skippable = "False:bool" -[PIPELINE.my_pipeline] -tasks = [ "double:SECTION",] - [SCENARIO.my_scenario] -pipelines = [ "my_pipeline:SECTION",] +tasks = [ "double:SECTION",] +additional_data_nodes = [] [SCENARIO.my_scenario.comparators] + +[SCENARIO.my_scenario.sequences] diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/config_03.toml b/docs/tutorials/complete_applications/scenario_management_overview/src/config_03.toml index dcd65f46f..b99b227a8 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/config_03.toml +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/config_03.toml @@ -2,33 +2,28 @@ [DATA_NODE.historical_data] storage_type = "csv" -scope = "SCENARIO:SCOPE" -default_path = "src/time_series.csv" -has_header = "True:bool" -exposed_type = "pandas" +default_path = "time_series.csv" [DATA_NODE.month_data] -scope = "SCENARIO:SCOPE" [DATA_NODE.nb_of_values] -scope = "SCENARIO:SCOPE" [TASK.filter_current] -inputs = [ "historical_data:SECTION",] function = "__main__.filter_current:function" +inputs = [ "historical_data:SECTION",] outputs = [ "month_data:SECTION",] skippable = "False:bool" [TASK.count_values] -inputs = [ "month_data:SECTION",] function = "__main__.count_values:function" +inputs = [ "month_data:SECTION",] outputs = [ "nb_of_values:SECTION",] skippable = "False:bool" -[PIPELINE.my_pipeline] -tasks = [ "filter_current:SECTION", "count_values:SECTION",] - [SCENARIO.my_scenario] -pipelines = [ "my_pipeline:SECTION",] +tasks = [ "filter_current:SECTION", "count_values:SECTION",] +additional_data_nodes = [] [SCENARIO.my_scenario.comparators] + +[SCENARIO.my_scenario.sequences] diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/config_04.toml b/docs/tutorials/complete_applications/scenario_management_overview/src/config_04.toml index 01a93a747..06236f880 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/config_04.toml +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/config_04.toml @@ -2,37 +2,31 @@ [DATA_NODE.historical_data] storage_type = "csv" -scope = "SCENARIO:SCOPE" default_path = "time_series.csv" -has_header = "True:bool" -exposed_type = "pandas" [DATA_NODE.month] -scope = "SCENARIO:SCOPE" [DATA_NODE.month_data] -scope = "SCENARIO:SCOPE" [DATA_NODE.nb_of_values] -scope = "SCENARIO:SCOPE" [TASK.filter_by_month] -inputs = [ "historical_data:SECTION", "month:SECTION",] function = "__main__.filter_by_month:function" +inputs = [ "historical_data:SECTION", "month:SECTION",] outputs = [ "month_data:SECTION",] skippable = "False:bool" [TASK.count_values] -inputs = [ "month_data:SECTION",] function = "__main__.count_values:function" +inputs = [ "month_data:SECTION",] outputs = [ "nb_of_values:SECTION",] skippable = "False:bool" -[PIPELINE.my_pipeline] -tasks = [ "filter_by_month:SECTION", "count_values:SECTION",] - [SCENARIO.my_scenario] -pipelines = [ "my_pipeline:SECTION",] +tasks = [ "filter_by_month:SECTION", "count_values:SECTION",] +additional_data_nodes = [] frequency = "MONTHLY:FREQUENCY" [SCENARIO.my_scenario.comparators] + +[SCENARIO.my_scenario.sequences] diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/config_05.toml b/docs/tutorials/complete_applications/scenario_management_overview/src/config_05.toml index 517a5bff9..444613590 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/config_05.toml +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/config_05.toml @@ -4,8 +4,6 @@ storage_type = "csv" scope = "GLOBAL:SCOPE" default_path = "time_series.csv" -has_header = "True:bool" -exposed_type = "pandas" [DATA_NODE.month] scope = "CYCLE:SCOPE" @@ -14,25 +12,24 @@ scope = "CYCLE:SCOPE" scope = "CYCLE:SCOPE" [DATA_NODE.nb_of_values] -scope = "SCENARIO:SCOPE" [TASK.filter_by_month] -inputs = [ "historical_data:SECTION", "month:SECTION",] function = "__main__.filter_by_month:function" +inputs = [ "historical_data:SECTION", "month:SECTION",] outputs = [ "month_data:SECTION",] skippable = "False:bool" [TASK.count_values] -inputs = [ "month_data:SECTION",] function = "__main__.count_values:function" +inputs = [ "month_data:SECTION",] outputs = [ "nb_of_values:SECTION",] skippable = "False:bool" -[PIPELINE.my_pipeline] -tasks = [ "filter_by_month:SECTION", "count_values:SECTION",] - [SCENARIO.my_scenario] -pipelines = [ "my_pipeline:SECTION",] +tasks = [ "filter_by_month:SECTION", "count_values:SECTION",] +additional_data_nodes = [] frequency = "MONTHLY:FREQUENCY" [SCENARIO.my_scenario.comparators] + +[SCENARIO.my_scenario.sequences] diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/config_06.toml b/docs/tutorials/complete_applications/scenario_management_overview/src/config_06.toml index edf5a17d0..95d1ee73d 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/config_06.toml +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/config_06.toml @@ -4,37 +4,32 @@ storage_type = "csv" scope = "GLOBAL:SCOPE" default_path = "time_series.csv" -has_header = "True:bool" -exposed_type = "pandas" [DATA_NODE.month] scope = "CYCLE:SCOPE" [DATA_NODE.month_data] scope = "CYCLE:SCOPE" -cacheable = "True:bool" [DATA_NODE.nb_of_values] -scope = "SCENARIO:SCOPE" -cacheable = "True:bool" [TASK.filter_by_month] -inputs = [ "historical_data:SECTION", "month:SECTION",] function = "__main__.filter_by_month:function" +inputs = [ "historical_data:SECTION", "month:SECTION",] outputs = [ "month_data:SECTION",] skippable = "True:bool" [TASK.count_values] -inputs = [ "month_data:SECTION",] function = "__main__.count_values:function" +inputs = [ "month_data:SECTION",] outputs = [ "nb_of_values:SECTION",] skippable = "True:bool" -[PIPELINE.my_pipeline] -tasks = [ "filter_by_month:SECTION", "count_values:SECTION",] - [SCENARIO.my_scenario] -pipelines = [ "my_pipeline:SECTION",] +tasks = [ "filter_by_month:SECTION", "count_values:SECTION",] +additional_data_nodes = [] frequency = "MONTHLY:FREQUENCY" [SCENARIO.my_scenario.comparators] + +[SCENARIO.my_scenario.sequences] diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/config_07.toml b/docs/tutorials/complete_applications/scenario_management_overview/src/config_07.toml index da3cf604b..52e409034 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/config_07.toml +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/config_07.toml @@ -5,32 +5,29 @@ mode = "standalone" max_nb_of_workers = "2:int" [DATA_NODE.input] -scope = "SCENARIO:SCOPE" default_data = "21:int" [DATA_NODE.intermediate] -scope = "SCENARIO:SCOPE" default_data = "21:int" [DATA_NODE.output] -scope = "SCENARIO:SCOPE" [TASK.double] -inputs = [ "input:SECTION",] function = "__mp_main__.double:function" +inputs = [ "input:SECTION",] outputs = [ "intermediate:SECTION",] skippable = "False:bool" [TASK.add] -inputs = [ "intermediate:SECTION",] function = "__mp_main__.add:function" +inputs = [ "intermediate:SECTION",] outputs = [ "output:SECTION",] skippable = "False:bool" -[PIPELINE.my_pipeline] -tasks = [ "double:SECTION", "add:SECTION",] - [SCENARIO.my_scenario] -pipelines = [ "my_pipeline:SECTION",] +tasks = [ "double:SECTION", "add:SECTION",] +additional_data_nodes = [] [SCENARIO.my_scenario.comparators] + +[SCENARIO.my_scenario.sequences] diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/config_08.toml b/docs/tutorials/complete_applications/scenario_management_overview/src/config_08.toml index fb304ae67..999c3f4c4 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/config_08.toml +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/config_08.toml @@ -1,34 +1,30 @@ [TAIPY] [DATA_NODE.input] -scope = "SCENARIO:SCOPE" default_data = "21:int" [DATA_NODE.intermediate] -scope = "SCENARIO:SCOPE" [DATA_NODE.output] -scope = "SCENARIO:SCOPE" [TASK.double] -inputs = [ "input:SECTION",] function = "__main__.double:function" +inputs = [ "input:SECTION",] outputs = [ "intermediate:SECTION",] skippable = "False:bool" [TASK.add] -inputs = [ "intermediate:SECTION",] function = "__main__.add:function" +inputs = [ "intermediate:SECTION",] outputs = [ "output:SECTION",] skippable = "False:bool" -[PIPELINE.my_pipeline] -tasks = [ "double:SECTION", "add:SECTION",] - [SCENARIO.multiply_scenario] -pipelines = [ "my_pipeline:SECTION",] -frequency = "MONTHLY:FREQUENCY" +tasks = [ "double:SECTION", "add:SECTION",] +additional_data_nodes = [] name = "my_scenario" [SCENARIO.multiply_scenario.comparators] output = [ "__main__.compare_function:function",] + +[SCENARIO.multiply_scenario.sequences] diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/daily-min-temperatures.csv b/docs/tutorials/complete_applications/scenario_management_overview/src/daily-min-temperatures.csv new file mode 100644 index 000000000..276df43c4 --- /dev/null +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/daily-min-temperatures.csv @@ -0,0 +1,3651 @@ +"Date","Temp" +"1981-01-01",20.7 +"1981-01-02",17.9 +"1981-01-03",18.8 +"1981-01-04",14.6 +"1981-01-05",15.8 +"1981-01-06",15.8 +"1981-01-07",15.8 +"1981-01-08",17.4 +"1981-01-09",21.8 +"1981-01-10",20.0 +"1981-01-11",16.2 +"1981-01-12",13.3 +"1981-01-13",16.7 +"1981-01-14",21.5 +"1981-01-15",25.0 +"1981-01-16",20.7 +"1981-01-17",20.6 +"1981-01-18",24.8 +"1981-01-19",17.7 +"1981-01-20",15.5 +"1981-01-21",18.2 +"1981-01-22",12.1 +"1981-01-23",14.4 +"1981-01-24",16.0 +"1981-01-25",16.5 +"1981-01-26",18.7 +"1981-01-27",19.4 +"1981-01-28",17.2 +"1981-01-29",15.5 +"1981-01-30",15.1 +"1981-01-31",15.4 +"1981-02-01",15.3 +"1981-02-02",18.8 +"1981-02-03",21.9 +"1981-02-04",19.9 +"1981-02-05",16.6 +"1981-02-06",16.8 +"1981-02-07",14.6 +"1981-02-08",17.1 +"1981-02-09",25.0 +"1981-02-10",15.0 +"1981-02-11",13.7 +"1981-02-12",13.9 +"1981-02-13",18.3 +"1981-02-14",22.0 +"1981-02-15",22.1 +"1981-02-16",21.2 +"1981-02-17",18.4 +"1981-02-18",16.6 +"1981-02-19",16.1 +"1981-02-20",15.7 +"1981-02-21",16.6 +"1981-02-22",16.5 +"1981-02-23",14.4 +"1981-02-24",14.4 +"1981-02-25",18.5 +"1981-02-26",16.9 +"1981-02-27",17.5 +"1981-02-28",21.2 +"1981-03-01",17.8 +"1981-03-02",18.6 +"1981-03-03",17.0 +"1981-03-04",16.0 +"1981-03-05",13.3 +"1981-03-06",14.3 +"1981-03-07",11.4 +"1981-03-08",16.3 +"1981-03-09",16.1 +"1981-03-10",11.8 +"1981-03-11",12.2 +"1981-03-12",14.7 +"1981-03-13",11.8 +"1981-03-14",11.3 +"1981-03-15",10.6 +"1981-03-16",11.7 +"1981-03-17",14.2 +"1981-03-18",11.2 +"1981-03-19",16.9 +"1981-03-20",16.7 +"1981-03-21",8.1 +"1981-03-22",8.0 +"1981-03-23",8.8 +"1981-03-24",13.4 +"1981-03-25",10.9 +"1981-03-26",13.4 +"1981-03-27",11.0 +"1981-03-28",15.0 +"1981-03-29",15.7 +"1981-03-30",14.5 +"1981-03-31",15.8 +"1981-04-01",16.7 +"1981-04-02",16.8 +"1981-04-03",17.5 +"1981-04-04",17.1 +"1981-04-05",18.1 +"1981-04-06",16.6 +"1981-04-07",10.0 +"1981-04-08",14.9 +"1981-04-09",15.9 +"1981-04-10",13.0 +"1981-04-11",7.6 +"1981-04-12",11.5 +"1981-04-13",13.5 +"1981-04-14",13.0 +"1981-04-15",13.3 +"1981-04-16",12.1 +"1981-04-17",12.4 +"1981-04-18",13.2 +"1981-04-19",13.8 +"1981-04-20",10.6 +"1981-04-21",9.0 +"1981-04-22",10.0 +"1981-04-23",9.8 +"1981-04-24",11.5 +"1981-04-25",8.9 +"1981-04-26",7.4 +"1981-04-27",9.9 +"1981-04-28",9.3 +"1981-04-29",9.9 +"1981-04-30",7.4 +"1981-05-01",8.6 +"1981-05-02",11.9 +"1981-05-03",14.0 +"1981-05-04",8.6 +"1981-05-05",10.0 +"1981-05-06",13.5 +"1981-05-07",12.0 +"1981-05-08",10.5 +"1981-05-09",10.7 +"1981-05-10",8.1 +"1981-05-11",10.1 +"1981-05-12",10.6 +"1981-05-13",5.3 +"1981-05-14",6.6 +"1981-05-15",8.5 +"1981-05-16",11.2 +"1981-05-17",9.8 +"1981-05-18",5.9 +"1981-05-19",3.2 +"1981-05-20",2.1 +"1981-05-21",3.4 +"1981-05-22",5.4 +"1981-05-23",9.6 +"1981-05-24",11.5 +"1981-05-25",12.3 +"1981-05-26",12.6 +"1981-05-27",11.0 +"1981-05-28",11.2 +"1981-05-29",11.4 +"1981-05-30",11.8 +"1981-05-31",12.8 +"1981-06-01",11.6 +"1981-06-02",10.6 +"1981-06-03",9.8 +"1981-06-04",11.2 +"1981-06-05",5.7 +"1981-06-06",7.1 +"1981-06-07",2.5 +"1981-06-08",3.5 +"1981-06-09",4.6 +"1981-06-10",11.0 +"1981-06-11",5.7 +"1981-06-12",7.7 +"1981-06-13",10.4 +"1981-06-14",11.4 +"1981-06-15",9.2 +"1981-06-16",6.1 +"1981-06-17",2.7 +"1981-06-18",4.3 +"1981-06-19",6.3 +"1981-06-20",3.8 +"1981-06-21",4.4 +"1981-06-22",7.1 +"1981-06-23",4.8 +"1981-06-24",5.8 +"1981-06-25",6.2 +"1981-06-26",7.3 +"1981-06-27",9.2 +"1981-06-28",10.2 +"1981-06-29",9.5 +"1981-06-30",9.5 +"1981-07-01",10.7 +"1981-07-02",10.0 +"1981-07-03",6.5 +"1981-07-04",7.0 +"1981-07-05",7.4 +"1981-07-06",8.1 +"1981-07-07",6.6 +"1981-07-08",8.3 +"1981-07-09",8.9 +"1981-07-10",4.6 +"1981-07-11",6.8 +"1981-07-12",5.7 +"1981-07-13",6.1 +"1981-07-14",7.0 +"1981-07-15",7.2 +"1981-07-16",6.3 +"1981-07-17",8.8 +"1981-07-18",5.0 +"1981-07-19",7.4 +"1981-07-20",10.1 +"1981-07-21",12.0 +"1981-07-22",9.0 +"1981-07-23",8.9 +"1981-07-24",9.8 +"1981-07-25",9.0 +"1981-07-26",9.2 +"1981-07-27",7.7 +"1981-07-28",8.0 +"1981-07-29",6.1 +"1981-07-30",3.5 +"1981-07-31",3.2 +"1981-08-01",5.7 +"1981-08-02",7.7 +"1981-08-03",9.0 +"1981-08-04",10.0 +"1981-08-05",6.2 +"1981-08-06",6.9 +"1981-08-07",6.5 +"1981-08-08",6.8 +"1981-08-09",7.0 +"1981-08-10",5.2 +"1981-08-11",3.0 +"1981-08-12",5.6 +"1981-08-13",7.9 +"1981-08-14",9.0 +"1981-08-15",8.6 +"1981-08-16",10.3 +"1981-08-17",10.5 +"1981-08-18",7.6 +"1981-08-19",9.7 +"1981-08-20",12.5 +"1981-08-21",7.4 +"1981-08-22",7.9 +"1981-08-23",3.9 +"1981-08-24",6.6 +"1981-08-25",4.6 +"1981-08-26",7.0 +"1981-08-27",6.0 +"1981-08-28",5.5 +"1981-08-29",8.1 +"1981-08-30",5.5 +"1981-08-31",6.2 +"1981-09-01",8.0 +"1981-09-02",10.3 +"1981-09-03",9.8 +"1981-09-04",9.6 +"1981-09-05",8.5 +"1981-09-06",7.5 +"1981-09-07",11.2 +"1981-09-08",14.6 +"1981-09-09",11.7 +"1981-09-10",7.8 +"1981-09-11",12.3 +"1981-09-12",10.1 +"1981-09-13",11.5 +"1981-09-14",7.3 +"1981-09-15",10.9 +"1981-09-16",14.1 +"1981-09-17",10.7 +"1981-09-18",16.9 +"1981-09-19",10.5 +"1981-09-20",6.5 +"1981-09-21",11.0 +"1981-09-22",6.3 +"1981-09-23",10.5 +"1981-09-24",7.2 +"1981-09-25",7.6 +"1981-09-26",10.7 +"1981-09-27",7.8 +"1981-09-28",9.6 +"1981-09-29",11.4 +"1981-09-30",12.4 +"1981-10-01",8.9 +"1981-10-02",13.2 +"1981-10-03",8.6 +"1981-10-04",6.2 +"1981-10-05",11.4 +"1981-10-06",13.2 +"1981-10-07",14.3 +"1981-10-08",7.3 +"1981-10-09",12.9 +"1981-10-10",7.8 +"1981-10-11",6.2 +"1981-10-12",5.6 +"1981-10-13",10.0 +"1981-10-14",13.3 +"1981-10-15",8.3 +"1981-10-16",10.2 +"1981-10-17",8.6 +"1981-10-18",7.3 +"1981-10-19",10.4 +"1981-10-20",11.2 +"1981-10-21",13.2 +"1981-10-22",11.4 +"1981-10-23",9.1 +"1981-10-24",6.6 +"1981-10-25",8.4 +"1981-10-26",9.7 +"1981-10-27",13.2 +"1981-10-28",12.5 +"1981-10-29",11.0 +"1981-10-30",11.0 +"1981-10-31",11.7 +"1981-11-01",9.2 +"1981-11-02",11.5 +"1981-11-03",13.6 +"1981-11-04",13.7 +"1981-11-05",10.4 +"1981-11-06",11.5 +"1981-11-07",7.6 +"1981-11-08",9.6 +"1981-11-09",14.2 +"1981-11-10",15.7 +"1981-11-11",10.5 +"1981-11-12",10.5 +"1981-11-13",9.7 +"1981-11-14",9.5 +"1981-11-15",11.3 +"1981-11-16",8.9 +"1981-11-17",9.4 +"1981-11-18",11.9 +"1981-11-19",11.7 +"1981-11-20",13.4 +"1981-11-21",12.6 +"1981-11-22",10.1 +"1981-11-23",15.8 +"1981-11-24",13.6 +"1981-11-25",11.9 +"1981-11-26",9.9 +"1981-11-27",12.6 +"1981-11-28",17.8 +"1981-11-29",15.0 +"1981-11-30",13.6 +"1981-12-01",13.4 +"1981-12-02",10.5 +"1981-12-03",14.2 +"1981-12-04",11.5 +"1981-12-05",13.0 +"1981-12-06",15.0 +"1981-12-07",14.7 +"1981-12-08",12.6 +"1981-12-09",12.5 +"1981-12-10",13.5 +"1981-12-11",14.8 +"1981-12-12",17.2 +"1981-12-13",9.7 +"1981-12-14",12.1 +"1981-12-15",12.8 +"1981-12-16",11.2 +"1981-12-17",16.4 +"1981-12-18",15.6 +"1981-12-19",13.3 +"1981-12-20",11.0 +"1981-12-21",11.1 +"1981-12-22",15.0 +"1981-12-23",12.8 +"1981-12-24",15.0 +"1981-12-25",14.2 +"1981-12-26",14.0 +"1981-12-27",15.5 +"1981-12-28",13.3 +"1981-12-29",15.6 +"1981-12-30",15.2 +"1981-12-31",17.4 +"1982-01-01",17.0 +"1982-01-02",15.0 +"1982-01-03",13.5 +"1982-01-04",15.2 +"1982-01-05",13.0 +"1982-01-06",12.5 +"1982-01-07",14.1 +"1982-01-08",14.8 +"1982-01-09",16.2 +"1982-01-10",15.8 +"1982-01-11",19.1 +"1982-01-12",22.2 +"1982-01-13",15.9 +"1982-01-14",13.0 +"1982-01-15",14.1 +"1982-01-16",15.8 +"1982-01-17",24.0 +"1982-01-18",18.0 +"1982-01-19",19.7 +"1982-01-20",25.2 +"1982-01-21",20.5 +"1982-01-22",19.3 +"1982-01-23",15.8 +"1982-01-24",17.0 +"1982-01-25",18.4 +"1982-01-26",13.3 +"1982-01-27",14.6 +"1982-01-28",12.5 +"1982-01-29",17.0 +"1982-01-30",17.1 +"1982-01-31",14.0 +"1982-02-01",14.6 +"1982-02-02",13.3 +"1982-02-03",14.8 +"1982-02-04",15.1 +"1982-02-05",13.1 +"1982-02-06",13.6 +"1982-02-07",19.5 +"1982-02-08",22.7 +"1982-02-09",17.2 +"1982-02-10",13.5 +"1982-02-11",15.4 +"1982-02-12",17.0 +"1982-02-13",19.2 +"1982-02-14",22.8 +"1982-02-15",26.3 +"1982-02-16",18.2 +"1982-02-17",17.0 +"1982-02-18",14.8 +"1982-02-19",12.8 +"1982-02-20",15.5 +"1982-02-21",15.6 +"1982-02-22",13.1 +"1982-02-23",15.2 +"1982-02-24",14.1 +"1982-02-25",12.5 +"1982-02-26",14.6 +"1982-02-27",10.4 +"1982-02-28",13.9 +"1982-03-01",11.9 +"1982-03-02",13.5 +"1982-03-03",9.8 +"1982-03-04",14.0 +"1982-03-05",21.5 +"1982-03-06",19.5 +"1982-03-07",16.7 +"1982-03-08",19.1 +"1982-03-09",11.0 +"1982-03-10",9.0 +"1982-03-11",10.0 +"1982-03-12",14.6 +"1982-03-13",12.5 +"1982-03-14",17.2 +"1982-03-15",19.2 +"1982-03-16",22.2 +"1982-03-17",15.7 +"1982-03-18",14.2 +"1982-03-19",9.8 +"1982-03-20",14.0 +"1982-03-21",17.5 +"1982-03-22",20.7 +"1982-03-23",15.6 +"1982-03-24",13.2 +"1982-03-25",14.5 +"1982-03-26",16.8 +"1982-03-27",17.2 +"1982-03-28",13.4 +"1982-03-29",14.2 +"1982-03-30",14.3 +"1982-03-31",10.2 +"1982-04-01",10.4 +"1982-04-02",12.3 +"1982-04-03",11.9 +"1982-04-04",11.2 +"1982-04-05",8.5 +"1982-04-06",12.0 +"1982-04-07",12.4 +"1982-04-08",12.9 +"1982-04-09",10.1 +"1982-04-10",15.0 +"1982-04-11",13.6 +"1982-04-12",12.4 +"1982-04-13",13.6 +"1982-04-14",16.1 +"1982-04-15",19.5 +"1982-04-16",14.2 +"1982-04-17",9.3 +"1982-04-18",10.1 +"1982-04-19",7.4 +"1982-04-20",8.6 +"1982-04-21",7.8 +"1982-04-22",9.1 +"1982-04-23",13.0 +"1982-04-24",16.5 +"1982-04-25",12.9 +"1982-04-26",6.9 +"1982-04-27",6.9 +"1982-04-28",8.7 +"1982-04-29",10.0 +"1982-04-30",10.8 +"1982-05-01",7.5 +"1982-05-02",6.3 +"1982-05-03",11.9 +"1982-05-04",13.8 +"1982-05-05",11.8 +"1982-05-06",11.0 +"1982-05-07",10.1 +"1982-05-08",8.5 +"1982-05-09",5.5 +"1982-05-10",7.6 +"1982-05-11",8.7 +"1982-05-12",10.8 +"1982-05-13",11.2 +"1982-05-14",9.1 +"1982-05-15",3.7 +"1982-05-16",4.6 +"1982-05-17",6.6 +"1982-05-18",13.2 +"1982-05-19",15.2 +"1982-05-20",7.6 +"1982-05-21",8.4 +"1982-05-22",6.0 +"1982-05-23",8.3 +"1982-05-24",8.6 +"1982-05-25",11.1 +"1982-05-26",12.1 +"1982-05-27",12.9 +"1982-05-28",14.0 +"1982-05-29",12.5 +"1982-05-30",11.5 +"1982-05-31",7.0 +"1982-06-01",7.1 +"1982-06-02",9.0 +"1982-06-03",3.1 +"1982-06-04",2.5 +"1982-06-05",0.0 +"1982-06-06",1.6 +"1982-06-07",2.6 +"1982-06-08",5.7 +"1982-06-09",2.3 +"1982-06-10",4.5 +"1982-06-11",8.2 +"1982-06-12",6.9 +"1982-06-13",7.3 +"1982-06-14",6.0 +"1982-06-15",7.3 +"1982-06-16",7.6 +"1982-06-17",8.0 +"1982-06-18",8.0 +"1982-06-19",6.8 +"1982-06-20",7.3 +"1982-06-21",6.2 +"1982-06-22",6.9 +"1982-06-23",8.9 +"1982-06-24",4.0 +"1982-06-25",1.3 +"1982-06-26",0.8 +"1982-06-27",4.3 +"1982-06-28",7.3 +"1982-06-29",7.7 +"1982-06-30",9.0 +"1982-07-01",4.2 +"1982-07-02",1.6 +"1982-07-03",2.6 +"1982-07-04",3.4 +"1982-07-05",3.9 +"1982-07-06",7.0 +"1982-07-07",7.8 +"1982-07-08",5.3 +"1982-07-09",2.4 +"1982-07-10",2.8 +"1982-07-11",4.0 +"1982-07-12",7.5 +"1982-07-13",7.8 +"1982-07-14",5.6 +"1982-07-15",3.3 +"1982-07-16",5.0 +"1982-07-17",3.7 +"1982-07-18",3.9 +"1982-07-19",5.2 +"1982-07-20",0.2 +"1982-07-21",0.8 +"1982-07-22",0.9 +"1982-07-23",3.5 +"1982-07-24",6.6 +"1982-07-25",9.5 +"1982-07-26",9.0 +"1982-07-27",3.5 +"1982-07-28",4.5 +"1982-07-29",5.7 +"1982-07-30",5.6 +"1982-07-31",7.1 +"1982-08-01",9.7 +"1982-08-02",8.3 +"1982-08-03",9.1 +"1982-08-04",2.8 +"1982-08-05",2.2 +"1982-08-06",4.5 +"1982-08-07",3.8 +"1982-08-08",3.8 +"1982-08-09",6.2 +"1982-08-10",11.5 +"1982-08-11",10.2 +"1982-08-12",7.9 +"1982-08-13",9.0 +"1982-08-14",9.5 +"1982-08-15",6.0 +"1982-08-16",8.2 +"1982-08-17",9.2 +"1982-08-18",4.3 +"1982-08-19",6.6 +"1982-08-20",9.4 +"1982-08-21",13.2 +"1982-08-22",6.6 +"1982-08-23",5.1 +"1982-08-24",12.1 +"1982-08-25",11.2 +"1982-08-26",8.5 +"1982-08-27",4.6 +"1982-08-28",7.0 +"1982-08-29",14.2 +"1982-08-30",12.7 +"1982-08-31",7.6 +"1982-09-01",4.0 +"1982-09-02",10.0 +"1982-09-03",10.5 +"1982-09-04",5.0 +"1982-09-05",4.5 +"1982-09-06",8.2 +"1982-09-07",4.3 +"1982-09-08",9.8 +"1982-09-09",5.8 +"1982-09-10",5.0 +"1982-09-11",8.5 +"1982-09-12",9.0 +"1982-09-13",3.6 +"1982-09-14",6.7 +"1982-09-15",6.7 +"1982-09-16",10.1 +"1982-09-17",15.0 +"1982-09-18",8.9 +"1982-09-19",5.7 +"1982-09-20",4.2 +"1982-09-21",4.0 +"1982-09-22",5.3 +"1982-09-23",6.3 +"1982-09-24",8.5 +"1982-09-25",11.5 +"1982-09-26",7.7 +"1982-09-27",9.2 +"1982-09-28",7.8 +"1982-09-29",6.3 +"1982-09-30",6.3 +"1982-10-01",8.6 +"1982-10-02",6.1 +"1982-10-03",13.2 +"1982-10-04",9.9 +"1982-10-05",4.7 +"1982-10-06",5.8 +"1982-10-07",14.9 +"1982-10-08",10.7 +"1982-10-09",8.6 +"1982-10-10",9.4 +"1982-10-11",5.7 +"1982-10-12",10.9 +"1982-10-13",13.1 +"1982-10-14",10.4 +"1982-10-15",8.2 +"1982-10-16",9.8 +"1982-10-17",7.5 +"1982-10-18",5.8 +"1982-10-19",9.8 +"1982-10-20",7.9 +"1982-10-21",8.7 +"1982-10-22",10.0 +"1982-10-23",10.6 +"1982-10-24",8.0 +"1982-10-25",10.2 +"1982-10-26",15.1 +"1982-10-27",13.9 +"1982-10-28",9.2 +"1982-10-29",9.0 +"1982-10-30",13.2 +"1982-10-31",7.0 +"1982-11-01",10.6 +"1982-11-02",6.9 +"1982-11-03",9.5 +"1982-11-04",12.5 +"1982-11-05",13.6 +"1982-11-06",17.7 +"1982-11-07",16.0 +"1982-11-08",11.3 +"1982-11-09",10.5 +"1982-11-10",14.4 +"1982-11-11",10.3 +"1982-11-12",9.0 +"1982-11-13",11.1 +"1982-11-14",14.5 +"1982-11-15",18.0 +"1982-11-16",12.8 +"1982-11-17",10.7 +"1982-11-18",9.1 +"1982-11-19",8.7 +"1982-11-20",12.4 +"1982-11-21",12.6 +"1982-11-22",10.3 +"1982-11-23",13.7 +"1982-11-24",16.0 +"1982-11-25",15.8 +"1982-11-26",12.1 +"1982-11-27",12.5 +"1982-11-28",12.2 +"1982-11-29",13.7 +"1982-11-30",16.1 +"1982-12-01",15.5 +"1982-12-02",10.3 +"1982-12-03",10.5 +"1982-12-04",11.0 +"1982-12-05",11.9 +"1982-12-06",13.0 +"1982-12-07",12.2 +"1982-12-08",10.6 +"1982-12-09",13.0 +"1982-12-10",13.0 +"1982-12-11",12.2 +"1982-12-12",12.6 +"1982-12-13",18.7 +"1982-12-14",15.2 +"1982-12-15",15.3 +"1982-12-16",13.9 +"1982-12-17",15.8 +"1982-12-18",13.0 +"1982-12-19",13.0 +"1982-12-20",13.7 +"1982-12-21",12.0 +"1982-12-22",10.8 +"1982-12-23",15.6 +"1982-12-24",15.3 +"1982-12-25",13.9 +"1982-12-26",13.0 +"1982-12-27",15.3 +"1982-12-28",16.3 +"1982-12-29",15.8 +"1982-12-30",17.7 +"1982-12-31",16.3 +"1983-01-01",18.4 +"1983-01-02",15.0 +"1983-01-03",10.9 +"1983-01-04",11.4 +"1983-01-05",14.8 +"1983-01-06",12.1 +"1983-01-07",12.8 +"1983-01-08",16.2 +"1983-01-09",15.5 +"1983-01-10",13.0 +"1983-01-11",10.5 +"1983-01-12",9.1 +"1983-01-13",10.5 +"1983-01-14",11.8 +"1983-01-15",12.7 +"1983-01-16",12.7 +"1983-01-17",11.5 +"1983-01-18",13.8 +"1983-01-19",13.3 +"1983-01-20",11.6 +"1983-01-21",15.4 +"1983-01-22",12.4 +"1983-01-23",16.9 +"1983-01-24",14.7 +"1983-01-25",10.6 +"1983-01-26",15.6 +"1983-01-27",10.7 +"1983-01-28",12.6 +"1983-01-29",13.8 +"1983-01-30",14.3 +"1983-01-31",14.0 +"1983-02-01",18.1 +"1983-02-02",17.3 +"1983-02-03",13.0 +"1983-02-04",16.0 +"1983-02-05",14.9 +"1983-02-06",16.2 +"1983-02-07",20.3 +"1983-02-08",22.5 +"1983-02-09",17.2 +"1983-02-10",15.9 +"1983-02-11",16.8 +"1983-02-12",13.8 +"1983-02-13",12.8 +"1983-02-14",14.0 +"1983-02-15",17.5 +"1983-02-16",21.5 +"1983-02-17",16.8 +"1983-02-18",13.6 +"1983-02-19",14.5 +"1983-02-20",14.2 +"1983-02-21",15.7 +"1983-02-22",19.7 +"1983-02-23",17.4 +"1983-02-24",14.4 +"1983-02-25",16.9 +"1983-02-26",19.1 +"1983-02-27",20.4 +"1983-02-28",20.1 +"1983-03-01",19.9 +"1983-03-02",22.0 +"1983-03-03",20.5 +"1983-03-04",22.1 +"1983-03-05",20.6 +"1983-03-06",15.0 +"1983-03-07",20.6 +"1983-03-08",21.5 +"1983-03-09",16.2 +"1983-03-10",14.1 +"1983-03-11",14.5 +"1983-03-12",21.1 +"1983-03-13",15.9 +"1983-03-14",15.2 +"1983-03-15",13.1 +"1983-03-16",13.2 +"1983-03-17",12.5 +"1983-03-18",15.2 +"1983-03-19",17.6 +"1983-03-20",15.5 +"1983-03-21",16.7 +"1983-03-22",16.3 +"1983-03-23",15.1 +"1983-03-24",12.7 +"1983-03-25",10.0 +"1983-03-26",11.4 +"1983-03-27",12.6 +"1983-03-28",10.7 +"1983-03-29",10.0 +"1983-03-30",13.9 +"1983-03-31",13.4 +"1983-04-01",12.5 +"1983-04-02",12.8 +"1983-04-03",7.8 +"1983-04-04",11.1 +"1983-04-05",10.7 +"1983-04-06",7.1 +"1983-04-07",6.7 +"1983-04-08",5.7 +"1983-04-09",9.1 +"1983-04-10",15.2 +"1983-04-11",15.5 +"1983-04-12",11.1 +"1983-04-13",11.7 +"1983-04-14",11.5 +"1983-04-15",9.8 +"1983-04-16",6.2 +"1983-04-17",6.7 +"1983-04-18",7.5 +"1983-04-19",8.8 +"1983-04-20",8.0 +"1983-04-21",10.4 +"1983-04-22",14.5 +"1983-04-23",16.5 +"1983-04-24",14.1 +"1983-04-25",10.5 +"1983-04-26",12.6 +"1983-04-27",13.0 +"1983-04-28",8.7 +"1983-04-29",10.1 +"1983-04-30",12.0 +"1983-05-01",12.5 +"1983-05-02",13.5 +"1983-05-03",13.7 +"1983-05-04",13.5 +"1983-05-05",10.7 +"1983-05-06",13.0 +"1983-05-07",11.6 +"1983-05-08",13.0 +"1983-05-09",11.2 +"1983-05-10",13.5 +"1983-05-11",12.9 +"1983-05-12",6.8 +"1983-05-13",10.0 +"1983-05-14",14.5 +"1983-05-15",11.7 +"1983-05-16",6.7 +"1983-05-17",4.6 +"1983-05-18",4.9 +"1983-05-19",7.4 +"1983-05-20",8.3 +"1983-05-21",7.5 +"1983-05-22",6.2 +"1983-05-23",7.8 +"1983-05-24",13.2 +"1983-05-25",11.9 +"1983-05-26",6.5 +"1983-05-27",8.3 +"1983-05-28",12.1 +"1983-05-29",9.3 +"1983-05-30",7.5 +"1983-05-31",9.3 +"1983-06-01",11.0 +"1983-06-02",10.8 +"1983-06-03",5.3 +"1983-06-04",7.6 +"1983-06-05",5.6 +"1983-06-06",7.2 +"1983-06-07",9.6 +"1983-06-08",7.0 +"1983-06-09",8.3 +"1983-06-10",7.8 +"1983-06-11",4.7 +"1983-06-12",6.8 +"1983-06-13",7.2 +"1983-06-14",8.3 +"1983-06-15",9.5 +"1983-06-16",4.7 +"1983-06-17",3.0 +"1983-06-18",1.5 +"1983-06-19",2.5 +"1983-06-20",6.2 +"1983-06-21",11.6 +"1983-06-22",6.6 +"1983-06-23",6.6 +"1983-06-24",8.0 +"1983-06-25",7.9 +"1983-06-26",3.3 +"1983-06-27",3.9 +"1983-06-28",6.0 +"1983-06-29",4.0 +"1983-06-30",5.5 +"1983-07-01",8.5 +"1983-07-02",9.8 +"1983-07-03",9.5 +"1983-07-04",7.2 +"1983-07-05",8.1 +"1983-07-06",8.0 +"1983-07-07",8.5 +"1983-07-08",8.8 +"1983-07-09",8.3 +"1983-07-10",2.4 +"1983-07-11",4.9 +"1983-07-12",5.9 +"1983-07-13",6.7 +"1983-07-14",8.4 +"1983-07-15",6.5 +"1983-07-16",7.9 +"1983-07-17",4.1 +"1983-07-18",5.4 +"1983-07-19",7.5 +"1983-07-20",3.9 +"1983-07-21",2.5 +"1983-07-22",5.3 +"1983-07-23",6.6 +"1983-07-24",0.0 +"1983-07-25",0.7 +"1983-07-26",7.6 +"1983-07-27",12.3 +"1983-07-28",9.2 +"1983-07-29",9.6 +"1983-07-30",9.5 +"1983-07-31",10.0 +"1983-08-01",7.7 +"1983-08-02",8.0 +"1983-08-03",8.3 +"1983-08-04",8.3 +"1983-08-05",4.5 +"1983-08-06",6.5 +"1983-08-07",9.4 +"1983-08-08",9.4 +"1983-08-09",10.5 +"1983-08-10",10.7 +"1983-08-11",9.9 +"1983-08-12",7.6 +"1983-08-13",5.8 +"1983-08-14",8.5 +"1983-08-15",13.8 +"1983-08-16",14.3 +"1983-08-17",8.3 +"1983-08-18",5.3 +"1983-08-19",3.0 +"1983-08-20",5.2 +"1983-08-21",10.3 +"1983-08-22",11.1 +"1983-08-23",10.5 +"1983-08-24",9.0 +"1983-08-25",13.0 +"1983-08-26",6.4 +"1983-08-27",8.4 +"1983-08-28",6.7 +"1983-08-29",8.3 +"1983-08-30",11.2 +"1983-08-31",10.0 +"1983-09-01",10.1 +"1983-09-02",10.6 +"1983-09-03",10.9 +"1983-09-04",5.7 +"1983-09-05",9.5 +"1983-09-06",10.4 +"1983-09-07",11.1 +"1983-09-08",12.2 +"1983-09-09",10.6 +"1983-09-10",8.8 +"1983-09-11",9.2 +"1983-09-12",5.5 +"1983-09-13",7.1 +"1983-09-14",6.5 +"1983-09-15",4.3 +"1983-09-16",5.0 +"1983-09-17",11.2 +"1983-09-18",7.5 +"1983-09-19",12.0 +"1983-09-20",13.6 +"1983-09-21",8.3 +"1983-09-22",8.5 +"1983-09-23",12.9 +"1983-09-24",7.7 +"1983-09-25",7.6 +"1983-09-26",3.5 +"1983-09-27",10.4 +"1983-09-28",15.4 +"1983-09-29",10.6 +"1983-09-30",9.6 +"1983-10-01",9.3 +"1983-10-02",13.9 +"1983-10-03",7.7 +"1983-10-04",9.5 +"1983-10-05",7.6 +"1983-10-06",6.9 +"1983-10-07",6.8 +"1983-10-08",5.8 +"1983-10-09",6.0 +"1983-10-10",8.3 +"1983-10-11",9.1 +"1983-10-12",12.5 +"1983-10-13",13.2 +"1983-10-14",16.2 +"1983-10-15",12.5 +"1983-10-16",11.8 +"1983-10-17",10.6 +"1983-10-18",10.0 +"1983-10-19",12.2 +"1983-10-20",8.9 +"1983-10-21",10.3 +"1983-10-22",7.5 +"1983-10-23",11.6 +"1983-10-24",12.6 +"1983-10-25",12.9 +"1983-10-26",11.7 +"1983-10-27",14.0 +"1983-10-28",12.3 +"1983-10-29",9.0 +"1983-10-30",9.2 +"1983-10-31",9.8 +"1983-11-01",11.8 +"1983-11-02",10.6 +"1983-11-03",12.6 +"1983-11-04",11.0 +"1983-11-05",8.2 +"1983-11-06",7.5 +"1983-11-07",13.6 +"1983-11-08",14.8 +"1983-11-09",10.9 +"1983-11-10",7.7 +"1983-11-11",10.2 +"1983-11-12",10.8 +"1983-11-13",10.8 +"1983-11-14",12.5 +"1983-11-15",13.2 +"1983-11-16",8.7 +"1983-11-17",5.7 +"1983-11-18",9.8 +"1983-11-19",7.3 +"1983-11-20",10.8 +"1983-11-21",10.0 +"1983-11-22",16.2 +"1983-11-23",15.0 +"1983-11-24",14.5 +"1983-11-25",15.9 +"1983-11-26",14.9 +"1983-11-27",14.2 +"1983-11-28",15.8 +"1983-11-29",17.2 +"1983-11-30",17.6 +"1983-12-01",12.1 +"1983-12-02",11.4 +"1983-12-03",13.0 +"1983-12-04",13.2 +"1983-12-05",12.0 +"1983-12-06",15.3 +"1983-12-07",12.7 +"1983-12-08",12.1 +"1983-12-09",13.8 +"1983-12-10",10.9 +"1983-12-11",12.0 +"1983-12-12",16.5 +"1983-12-13",15.0 +"1983-12-14",11.2 +"1983-12-15",13.9 +"1983-12-16",15.0 +"1983-12-17",14.8 +"1983-12-18",15.0 +"1983-12-19",13.3 +"1983-12-20",20.4 +"1983-12-21",18.0 +"1983-12-22",12.2 +"1983-12-23",16.7 +"1983-12-24",13.8 +"1983-12-25",17.5 +"1983-12-26",15.0 +"1983-12-27",13.9 +"1983-12-28",11.1 +"1983-12-29",16.1 +"1983-12-30",20.4 +"1983-12-31",18.0 +"1984-01-01",19.5 +"1984-01-02",17.1 +"1984-01-03",17.1 +"1984-01-04",12.0 +"1984-01-05",11.0 +"1984-01-06",16.3 +"1984-01-07",16.1 +"1984-01-08",13.0 +"1984-01-09",13.4 +"1984-01-10",15.2 +"1984-01-11",12.5 +"1984-01-12",14.3 +"1984-01-13",16.5 +"1984-01-14",18.6 +"1984-01-15",18.0 +"1984-01-16",18.2 +"1984-01-17",11.4 +"1984-01-18",11.9 +"1984-01-19",12.2 +"1984-01-20",14.8 +"1984-01-21",13.1 +"1984-01-22",12.7 +"1984-01-23",10.5 +"1984-01-24",13.8 +"1984-01-25",18.8 +"1984-01-26",13.9 +"1984-01-27",11.2 +"1984-01-28",10.6 +"1984-01-29",14.7 +"1984-01-30",13.1 +"1984-01-31",12.1 +"1984-02-01",14.7 +"1984-02-02",11.1 +"1984-02-03",13.0 +"1984-02-04",15.6 +"1984-02-05",14.2 +"1984-02-06",15.5 +"1984-02-07",18.0 +"1984-02-08",15.0 +"1984-02-09",15.9 +"1984-02-10",15.5 +"1984-02-11",15.8 +"1984-02-12",16.6 +"1984-02-13",13.6 +"1984-02-14",13.8 +"1984-02-15",14.6 +"1984-02-16",15.6 +"1984-02-17",16.6 +"1984-02-18",14.3 +"1984-02-19",16.3 +"1984-02-20",18.9 +"1984-02-21",18.7 +"1984-02-22",14.5 +"1984-02-23",16.5 +"1984-02-24",14.1 +"1984-02-25",13.5 +"1984-02-26",11.7 +"1984-02-27",15.1 +"1984-02-28",11.2 +"1984-02-29",13.5 +"1984-03-01",12.6 +"1984-03-02",8.8 +"1984-03-03",10.5 +"1984-03-04",12.1 +"1984-03-05",14.5 +"1984-03-06",19.5 +"1984-03-07",14.0 +"1984-03-08",13.8 +"1984-03-09",10.5 +"1984-03-10",13.8 +"1984-03-11",11.4 +"1984-03-12",15.6 +"1984-03-13",11.1 +"1984-03-14",12.1 +"1984-03-15",14.2 +"1984-03-16",10.9 +"1984-03-17",14.2 +"1984-03-18",13.8 +"1984-03-19",15.1 +"1984-03-20",14.0 +"1984-03-21",12.1 +"1984-03-22",13.8 +"1984-03-23",16.6 +"1984-03-24",17.8 +"1984-03-25",9.4 +"1984-03-26",10.2 +"1984-03-27",7.4 +"1984-03-28",8.7 +"1984-03-29",14.0 +"1984-03-30",15.3 +"1984-03-31",11.1 +"1984-04-01",9.7 +"1984-04-02",10.3 +"1984-04-03",9.2 +"1984-04-04",8.2 +"1984-04-05",9.7 +"1984-04-06",12.4 +"1984-04-07",12.5 +"1984-04-08",9.0 +"1984-04-09",9.7 +"1984-04-10",10.1 +"1984-04-11",11.2 +"1984-04-12",12.0 +"1984-04-13",11.1 +"1984-04-14",10.8 +"1984-04-15",12.8 +"1984-04-16",9.8 +"1984-04-17",13.7 +"1984-04-18",11.0 +"1984-04-19",13.2 +"1984-04-20",13.0 +"1984-04-21",10.2 +"1984-04-22",13.2 +"1984-04-23",9.3 +"1984-04-24",11.1 +"1984-04-25",10.3 +"1984-04-26",8.7 +"1984-04-27",11.7 +"1984-04-28",12.5 +"1984-04-29",6.5 +"1984-04-30",9.6 +"1984-05-01",13.8 +"1984-05-02",14.7 +"1984-05-03",9.1 +"1984-05-04",4.8 +"1984-05-05",3.3 +"1984-05-06",3.5 +"1984-05-07",5.7 +"1984-05-08",5.5 +"1984-05-09",7.0 +"1984-05-10",9.5 +"1984-05-11",9.9 +"1984-05-12",4.9 +"1984-05-13",6.3 +"1984-05-14",4.8 +"1984-05-15",6.2 +"1984-05-16",7.1 +"1984-05-17",7.5 +"1984-05-18",9.4 +"1984-05-19",8.7 +"1984-05-20",9.5 +"1984-05-21",12.1 +"1984-05-22",9.5 +"1984-05-23",9.3 +"1984-05-24",8.5 +"1984-05-25",8.0 +"1984-05-26",9.8 +"1984-05-27",6.2 +"1984-05-28",7.3 +"1984-05-29",10.9 +"1984-05-30",10.0 +"1984-05-31",8.7 +"1984-06-01",9.0 +"1984-06-02",10.8 +"1984-06-03",12.4 +"1984-06-04",7.2 +"1984-06-05",7.2 +"1984-06-06",11.1 +"1984-06-07",9.3 +"1984-06-08",10.1 +"1984-06-09",3.9 +"1984-06-10",5.0 +"1984-06-11",8.2 +"1984-06-12",2.8 +"1984-06-13",4.3 +"1984-06-14",8.1 +"1984-06-15",11.1 +"1984-06-16",4.7 +"1984-06-17",5.3 +"1984-06-18",10.0 +"1984-06-19",5.6 +"1984-06-20",2.2 +"1984-06-21",7.1 +"1984-06-22",8.3 +"1984-06-23",8.6 +"1984-06-24",10.1 +"1984-06-25",8.3 +"1984-06-26",7.2 +"1984-06-27",7.7 +"1984-06-28",7.8 +"1984-06-29",9.1 +"1984-06-30",9.4 +"1984-07-01",7.8 +"1984-07-02",2.6 +"1984-07-03",2.4 +"1984-07-04",3.9 +"1984-07-05",1.3 +"1984-07-06",2.1 +"1984-07-07",7.4 +"1984-07-08",7.2 +"1984-07-09",8.8 +"1984-07-10",8.9 +"1984-07-11",8.8 +"1984-07-12",8.0 +"1984-07-13",0.7 +"1984-07-14",0.1 +"1984-07-15",0.9 +"1984-07-16",7.8 +"1984-07-17",7.2 +"1984-07-18",8.0 +"1984-07-19",4.6 +"1984-07-20",5.2 +"1984-07-21",5.8 +"1984-07-22",6.8 +"1984-07-23",8.1 +"1984-07-24",7.5 +"1984-07-25",5.4 +"1984-07-26",4.6 +"1984-07-27",6.4 +"1984-07-28",9.7 +"1984-07-29",7.0 +"1984-07-30",10.0 +"1984-07-31",10.6 +"1984-08-01",11.5 +"1984-08-02",10.2 +"1984-08-03",11.1 +"1984-08-04",11.0 +"1984-08-05",8.9 +"1984-08-06",9.9 +"1984-08-07",11.7 +"1984-08-08",11.6 +"1984-08-09",9.0 +"1984-08-10",6.3 +"1984-08-11",8.7 +"1984-08-12",8.5 +"1984-08-13",8.5 +"1984-08-14",8.0 +"1984-08-15",6.0 +"1984-08-16",8.0 +"1984-08-17",8.5 +"1984-08-18",7.7 +"1984-08-19",8.4 +"1984-08-20",9.0 +"1984-08-21",8.3 +"1984-08-22",6.8 +"1984-08-23",9.3 +"1984-08-24",6.7 +"1984-08-25",9.0 +"1984-08-26",7.3 +"1984-08-27",6.3 +"1984-08-28",7.9 +"1984-08-29",5.2 +"1984-08-30",9.0 +"1984-08-31",11.3 +"1984-09-01",9.2 +"1984-09-02",11.3 +"1984-09-03",7.0 +"1984-09-04",8.0 +"1984-09-05",4.6 +"1984-09-06",8.5 +"1984-09-07",9.5 +"1984-09-08",9.4 +"1984-09-09",10.5 +"1984-09-10",9.7 +"1984-09-11",4.9 +"1984-09-12",8.0 +"1984-09-13",5.8 +"1984-09-14",5.5 +"1984-09-15",10.9 +"1984-09-16",11.7 +"1984-09-17",9.2 +"1984-09-18",8.9 +"1984-09-19",11.3 +"1984-09-20",8.6 +"1984-09-21",6.2 +"1984-09-22",6.6 +"1984-09-23",9.1 +"1984-09-24",6.1 +"1984-09-25",7.5 +"1984-09-26",10.7 +"1984-09-27",6.3 +"1984-09-28",5.5 +"1984-09-29",6.7 +"1984-09-30",4.2 +"1984-10-01",11.3 +"1984-10-02",16.3 +"1984-10-03",10.5 +"1984-10-04",10.3 +"1984-10-05",7.9 +"1984-10-06",7.7 +"1984-10-07",16.0 +"1984-10-08",14.6 +"1984-10-09",12.5 +"1984-10-10",8.1 +"1984-10-11",12.2 +"1984-10-12",17.2 +"1984-10-13",9.4 +"1984-10-14",8.7 +"1984-10-15",5.9 +"1984-10-16",4.8 +"1984-10-17",7.4 +"1984-10-18",9.4 +"1984-10-19",9.7 +"1984-10-20",9.9 +"1984-10-21",6.5 +"1984-10-22",9.8 +"1984-10-23",18.2 +"1984-10-24",11.3 +"1984-10-25",9.1 +"1984-10-26",9.6 +"1984-10-27",13.5 +"1984-10-28",10.7 +"1984-10-29",10.0 +"1984-10-30",8.5 +"1984-10-31",12.6 +"1984-11-01",16.6 +"1984-11-02",11.6 +"1984-11-03",12.2 +"1984-11-04",11.2 +"1984-11-05",9.2 +"1984-11-06",9.9 +"1984-11-07",11.9 +"1984-11-08",15.6 +"1984-11-09",19.0 +"1984-11-10",12.8 +"1984-11-11",12.2 +"1984-11-12",12.0 +"1984-11-13",11.1 +"1984-11-14",11.8 +"1984-11-15",7.6 +"1984-11-16",13.0 +"1984-11-17",12.7 +"1984-11-18",16.0 +"1984-11-19",14.8 +"1984-11-20",14.2 +"1984-11-21",10.0 +"1984-11-22",8.8 +"1984-11-23",11.6 +"1984-11-24",8.6 +"1984-11-25",14.6 +"1984-11-26",24.3 +"1984-11-27",11.6 +"1984-11-28",10.8 +"1984-11-29",12.0 +"1984-11-30",11.0 +"1984-12-01",12.6 +"1984-12-02",10.8 +"1984-12-03",9.1 +"1984-12-04",11.0 +"1984-12-05",13.0 +"1984-12-06",12.8 +"1984-12-07",9.9 +"1984-12-08",11.6 +"1984-12-09",10.5 +"1984-12-10",15.9 +"1984-12-11",12.2 +"1984-12-12",13.0 +"1984-12-13",12.5 +"1984-12-14",12.5 +"1984-12-15",11.4 +"1984-12-16",12.1 +"1984-12-17",16.8 +"1984-12-18",12.1 +"1984-12-19",11.3 +"1984-12-20",10.4 +"1984-12-21",14.2 +"1984-12-22",11.4 +"1984-12-23",13.7 +"1984-12-24",16.5 +"1984-12-25",12.8 +"1984-12-26",12.2 +"1984-12-27",12.0 +"1984-12-28",12.6 +"1984-12-29",16.0 +"1984-12-30",16.4 +"1985-01-01",13.3 +"1985-01-02",15.2 +"1985-01-03",13.1 +"1985-01-04",12.7 +"1985-01-05",14.6 +"1985-01-06",11.0 +"1985-01-07",13.2 +"1985-01-08",12.2 +"1985-01-09",14.4 +"1985-01-10",13.7 +"1985-01-11",14.5 +"1985-01-12",14.1 +"1985-01-13",14.4 +"1985-01-14",19.7 +"1985-01-15",16.5 +"1985-01-16",15.9 +"1985-01-17",11.8 +"1985-01-18",12.0 +"1985-01-19",11.4 +"1985-01-20",14.4 +"1985-01-21",12.4 +"1985-01-22",15.1 +"1985-01-23",15.6 +"1985-01-24",15.2 +"1985-01-25",12.8 +"1985-01-26",13.3 +"1985-01-27",17.5 +"1985-01-28",15.4 +"1985-01-29",13.5 +"1985-01-30",16.7 +"1985-01-31",15.2 +"1985-02-01",14.9 +"1985-02-02",10.2 +"1985-02-03",13.6 +"1985-02-04",19.0 +"1985-02-05",15.7 +"1985-02-06",18.0 +"1985-02-07",14.8 +"1985-02-08",13.9 +"1985-02-09",13.0 +"1985-02-10",15.3 +"1985-02-11",14.3 +"1985-02-12",15.6 +"1985-02-13",16.0 +"1985-02-14",14.9 +"1985-02-15",11.1 +"1985-02-16",14.8 +"1985-02-17",13.0 +"1985-02-18",12.2 +"1985-02-19",10.9 +"1985-02-20",14.6 +"1985-02-21",16.6 +"1985-02-22",18.1 +"1985-02-23",13.4 +"1985-02-24",10.3 +"1985-02-25",13.6 +"1985-02-26",13.8 +"1985-02-27",10.3 +"1985-02-28",11.0 +"1985-03-01",14.3 +"1985-03-02",15.5 +"1985-03-03",14.7 +"1985-03-04",12.7 +"1985-03-05",10.7 +"1985-03-06",12.6 +"1985-03-07",9.8 +"1985-03-08",13.2 +"1985-03-09",15.2 +"1985-03-10",16.6 +"1985-03-11",21.0 +"1985-03-12",22.4 +"1985-03-13",17.0 +"1985-03-14",21.7 +"1985-03-15",21.4 +"1985-03-16",18.6 +"1985-03-17",16.2 +"1985-03-18",16.8 +"1985-03-19",17.0 +"1985-03-20",18.4 +"1985-03-21",17.2 +"1985-03-22",18.4 +"1985-03-23",18.8 +"1985-03-24",16.5 +"1985-03-25",13.3 +"1985-03-26",12.2 +"1985-03-27",11.3 +"1985-03-28",13.8 +"1985-03-29",16.6 +"1985-03-30",14.0 +"1985-03-31",14.3 +"1985-04-01",16.4 +"1985-04-02",11.9 +"1985-04-03",15.7 +"1985-04-04",17.6 +"1985-04-05",17.5 +"1985-04-06",15.9 +"1985-04-07",16.2 +"1985-04-08",16.0 +"1985-04-09",15.9 +"1985-04-10",16.2 +"1985-04-11",16.2 +"1985-04-12",19.5 +"1985-04-13",18.2 +"1985-04-14",21.8 +"1985-04-15",15.1 +"1985-04-16",11.0 +"1985-04-17",8.1 +"1985-04-18",9.5 +"1985-04-19",9.3 +"1985-04-20",10.6 +"1985-04-21",6.3 +"1985-04-22",8.6 +"1985-04-23",6.8 +"1985-04-24",8.7 +"1985-04-25",8.4 +"1985-04-26",9.3 +"1985-04-27",10.0 +"1985-04-28",10.5 +"1985-04-29",12.0 +"1985-04-30",10.1 +"1985-05-01",9.4 +"1985-05-02",10.1 +"1985-05-03",8.0 +"1985-05-04",10.6 +"1985-05-05",13.6 +"1985-05-06",15.4 +"1985-05-07",9.0 +"1985-05-08",10.4 +"1985-05-09",11.0 +"1985-05-10",12.1 +"1985-05-11",13.4 +"1985-05-12",11.3 +"1985-05-13",6.7 +"1985-05-14",9.8 +"1985-05-15",10.8 +"1985-05-16",7.8 +"1985-05-17",4.5 +"1985-05-18",7.6 +"1985-05-19",6.9 +"1985-05-20",7.5 +"1985-05-21",8.5 +"1985-05-22",5.5 +"1985-05-23",9.5 +"1985-05-24",7.3 +"1985-05-25",5.4 +"1985-05-26",5.5 +"1985-05-27",8.1 +"1985-05-28",11.2 +"1985-05-29",13.4 +"1985-05-30",11.6 +"1985-05-31",10.1 +"1985-06-01",4.3 +"1985-06-02",5.5 +"1985-06-03",4.4 +"1985-06-04",5.9 +"1985-06-05",5.7 +"1985-06-06",8.2 +"1985-06-07",8.2 +"1985-06-08",4.2 +"1985-06-09",6.5 +"1985-06-10",10.0 +"1985-06-11",8.8 +"1985-06-12",6.6 +"1985-06-13",7.8 +"1985-06-14",10.1 +"1985-06-15",7.1 +"1985-06-16",7.7 +"1985-06-17",8.5 +"1985-06-18",7.3 +"1985-06-19",6.9 +"1985-06-20",8.4 +"1985-06-21",7.1 +"1985-06-22",6.3 +"1985-06-23",0.6 +"1985-06-24",1.6 +"1985-06-25",7.0 +"1985-06-26",8.3 +"1985-06-27",8.0 +"1985-06-28",10.2 +"1985-06-29",10.6 +"1985-06-30",10.4 +"1985-07-01",11.6 +"1985-07-02",11.0 +"1985-07-03",10.7 +"1985-07-04",7.3 +"1985-07-05",4.2 +"1985-07-06",4.7 +"1985-07-07",5.6 +"1985-07-08",7.7 +"1985-07-09",7.5 +"1985-07-10",4.9 +"1985-07-11",5.9 +"1985-07-12",7.8 +"1985-07-13",5.8 +"1985-07-14",7.0 +"1985-07-15",8.4 +"1985-07-16",6.2 +"1985-07-17",7.5 +"1985-07-18",4.8 +"1985-07-19",3.3 +"1985-07-20",3.2 +"1985-07-21",7.0 +"1985-07-22",8.4 +"1985-07-23",0.3 +"1985-07-24",0.3 +"1985-07-25",2.1 +"1985-07-26",8.5 +"1985-07-27",1.4 +"1985-07-28",4.1 +"1985-07-29",10.3 +"1985-07-30",6.6 +"1985-07-31",6.1 +"1985-08-01",7.0 +"1985-08-02",5.1 +"1985-08-03",6.3 +"1985-08-04",6.9 +"1985-08-05",11.4 +"1985-08-06",10.4 +"1985-08-07",10.3 +"1985-08-08",9.2 +"1985-08-09",7.2 +"1985-08-10",7.5 +"1985-08-11",4.0 +"1985-08-12",5.6 +"1985-08-13",6.7 +"1985-08-14",8.4 +"1985-08-15",11.0 +"1985-08-16",8.4 +"1985-08-17",8.8 +"1985-08-18",8.6 +"1985-08-19",8.3 +"1985-08-20",4.0 +"1985-08-21",3.6 +"1985-08-22",5.7 +"1985-08-23",10.6 +"1985-08-24",6.9 +"1985-08-25",10.0 +"1985-08-26",9.8 +"1985-08-27",7.2 +"1985-08-28",10.5 +"1985-08-29",3.6 +"1985-08-30",5.3 +"1985-08-31",8.4 +"1985-09-01",10.3 +"1985-09-02",7.9 +"1985-09-03",8.5 +"1985-09-04",7.9 +"1985-09-05",8.0 +"1985-09-06",9.8 +"1985-09-07",6.7 +"1985-09-08",4.8 +"1985-09-09",9.9 +"1985-09-10",12.8 +"1985-09-11",10.9 +"1985-09-12",11.7 +"1985-09-13",11.7 +"1985-09-14",11.0 +"1985-09-15",8.2 +"1985-09-16",7.5 +"1985-09-17",5.4 +"1985-09-18",7.2 +"1985-09-19",9.7 +"1985-09-20",8.4 +"1985-09-21",9.0 +"1985-09-22",8.7 +"1985-09-23",6.6 +"1985-09-24",11.6 +"1985-09-25",13.1 +"1985-09-26",6.7 +"1985-09-27",6.5 +"1985-09-28",7.7 +"1985-09-29",8.7 +"1985-09-30",7.2 +"1985-10-01",10.5 +"1985-10-02",8.6 +"1985-10-03",7.2 +"1985-10-04",11.4 +"1985-10-05",16.2 +"1985-10-06",6.1 +"1985-10-07",9.6 +"1985-10-08",11.1 +"1985-10-09",13.6 +"1985-10-10",10.7 +"1985-10-11",14.7 +"1985-10-12",11.6 +"1985-10-13",7.3 +"1985-10-14",8.0 +"1985-10-15",9.6 +"1985-10-16",16.0 +"1985-10-17",15.1 +"1985-10-18",12.8 +"1985-10-19",6.2 +"1985-10-20",7.1 +"1985-10-21",8.4 +"1985-10-22",10.0 +"1985-10-23",12.7 +"1985-10-24",10.0 +"1985-10-25",10.2 +"1985-10-26",6.5 +"1985-10-27",9.2 +"1985-10-28",11.9 +"1985-10-29",14.7 +"1985-10-30",11.4 +"1985-10-31",6.8 +"1985-11-01",7.4 +"1985-11-02",11.2 +"1985-11-03",9.2 +"1985-11-04",12.6 +"1985-11-05",16.0 +"1985-11-06",17.1 +"1985-11-07",15.3 +"1985-11-08",13.3 +"1985-11-09",15.4 +"1985-11-10",13.2 +"1985-11-11",14.4 +"1985-11-12",14.0 +"1985-11-13",15.5 +"1985-11-14",21.0 +"1985-11-15",10.0 +"1985-11-16",9.6 +"1985-11-17",12.0 +"1985-11-18",12.2 +"1985-11-19",11.3 +"1985-11-20",13.2 +"1985-11-21",10.5 +"1985-11-22",10.1 +"1985-11-23",8.8 +"1985-11-24",13.7 +"1985-11-25",16.2 +"1985-11-26",16.0 +"1985-11-27",14.0 +"1985-11-28",13.7 +"1985-11-29",12.5 +"1985-11-30",12.8 +"1985-12-01",12.3 +"1985-12-02",15.2 +"1985-12-03",15.0 +"1985-12-04",16.4 +"1985-12-05",16.1 +"1985-12-06",14.6 +"1985-12-07",18.2 +"1985-12-08",16.4 +"1985-12-09",16.6 +"1985-12-10",14.7 +"1985-12-11",15.8 +"1985-12-12",14.1 +"1985-12-13",13.5 +"1985-12-14",13.6 +"1985-12-15",13.7 +"1985-12-16",13.6 +"1985-12-17",12.1 +"1985-12-18",12.7 +"1985-12-19",13.3 +"1985-12-20",14.2 +"1985-12-21",15.0 +"1985-12-22",13.7 +"1985-12-23",12.0 +"1985-12-24",13.1 +"1985-12-25",13.2 +"1985-12-26",13.3 +"1985-12-27",11.5 +"1985-12-28",10.8 +"1985-12-29",12.0 +"1985-12-30",16.3 +"1985-12-31",14.4 +"1986-01-01",12.9 +"1986-01-02",13.8 +"1986-01-03",10.6 +"1986-01-04",12.6 +"1986-01-05",13.7 +"1986-01-06",12.6 +"1986-01-07",13.1 +"1986-01-08",15.4 +"1986-01-09",11.9 +"1986-01-10",13.8 +"1986-01-11",14.4 +"1986-01-12",15.2 +"1986-01-13",12.5 +"1986-01-14",12.2 +"1986-01-15",16.1 +"1986-01-16",14.6 +"1986-01-17",11.6 +"1986-01-18",13.1 +"1986-01-19",12.8 +"1986-01-20",15.2 +"1986-01-21",13.8 +"1986-01-22",15.0 +"1986-01-23",13.5 +"1986-01-24",11.8 +"1986-01-25",15.3 +"1986-01-26",13.5 +"1986-01-27",15.3 +"1986-01-28",13.8 +"1986-01-29",15.8 +"1986-01-30",17.4 +"1986-01-31",15.3 +"1986-02-01",14.6 +"1986-02-02",14.8 +"1986-02-03",10.7 +"1986-02-04",11.6 +"1986-02-05",13.6 +"1986-02-06",14.4 +"1986-02-07",11.8 +"1986-02-08",15.8 +"1986-02-09",16.0 +"1986-02-10",11.8 +"1986-02-11",14.5 +"1986-02-12",10.7 +"1986-02-13",14.2 +"1986-02-14",19.5 +"1986-02-15",21.4 +"1986-02-16",17.9 +"1986-02-17",17.4 +"1986-02-18",12.7 +"1986-02-19",13.8 +"1986-02-20",14.0 +"1986-02-21",15.0 +"1986-02-22",14.5 +"1986-02-23",13.1 +"1986-02-24",11.4 +"1986-02-25",12.5 +"1986-02-26",12.0 +"1986-02-27",13.4 +"1986-02-28",14.4 +"1986-03-01",17.7 +"1986-03-02",13.9 +"1986-03-03",13.3 +"1986-03-04",14.6 +"1986-03-05",16.4 +"1986-03-06",16.8 +"1986-03-07",20.0 +"1986-03-08",12.5 +"1986-03-09",12.7 +"1986-03-10",11.7 +"1986-03-11",12.7 +"1986-03-12",8.6 +"1986-03-13",11.9 +"1986-03-14",16.0 +"1986-03-15",15.2 +"1986-03-16",13.4 +"1986-03-17",11.6 +"1986-03-18",11.1 +"1986-03-19",15.6 +"1986-03-20",17.0 +"1986-03-21",18.5 +"1986-03-22",17.4 +"1986-03-23",16.5 +"1986-03-24",16.2 +"1986-03-25",16.1 +"1986-03-26",13.2 +"1986-03-27",18.0 +"1986-03-28",12.8 +"1986-03-29",11.7 +"1986-03-30",16.7 +"1986-03-31",15.6 +"1986-04-01",10.2 +"1986-04-02",10.3 +"1986-04-03",15.0 +"1986-04-04",18.0 +"1986-04-05",13.8 +"1986-04-06",10.5 +"1986-04-07",11.8 +"1986-04-08",7.2 +"1986-04-09",11.6 +"1986-04-10",7.4 +"1986-04-11",14.2 +"1986-04-12",12.2 +"1986-04-13",9.0 +"1986-04-14",12.3 +"1986-04-15",19.7 +"1986-04-16",12.8 +"1986-04-17",12.4 +"1986-04-18",12.0 +"1986-04-19",12.0 +"1986-04-20",11.1 +"1986-04-21",12.7 +"1986-04-22",14.2 +"1986-04-23",11.6 +"1986-04-24",12.0 +"1986-04-25",11.5 +"1986-04-26",8.3 +"1986-04-27",10.5 +"1986-04-28",9.0 +"1986-04-29",6.9 +"1986-04-30",9.4 +"1986-05-01",11.1 +"1986-05-02",9.1 +"1986-05-03",7.7 +"1986-05-04",10.0 +"1986-05-05",10.4 +"1986-05-06",8.0 +"1986-05-07",9.8 +"1986-05-08",12.4 +"1986-05-09",12.9 +"1986-05-10",12.3 +"1986-05-11",6.9 +"1986-05-12",10.5 +"1986-05-13",11.0 +"1986-05-14",9.7 +"1986-05-15",11.1 +"1986-05-16",11.5 +"1986-05-17",13.4 +"1986-05-18",10.9 +"1986-05-19",12.0 +"1986-05-20",12.1 +"1986-05-21",10.4 +"1986-05-22",10.0 +"1986-05-23",9.6 +"1986-05-24",11.3 +"1986-05-25",8.5 +"1986-05-26",6.3 +"1986-05-27",8.2 +"1986-05-28",10.7 +"1986-05-29",10.3 +"1986-05-30",9.5 +"1986-05-31",10.9 +"1986-06-01",10.9 +"1986-06-02",4.3 +"1986-06-03",5.2 +"1986-06-04",11.0 +"1986-06-05",11.6 +"1986-06-06",10.6 +"1986-06-07",9.4 +"1986-06-08",10.0 +"1986-06-09",9.6 +"1986-06-10",9.5 +"1986-06-11",9.7 +"1986-06-12",9.6 +"1986-06-13",7.0 +"1986-06-14",7.0 +"1986-06-15",6.8 +"1986-06-16",6.9 +"1986-06-17",8.0 +"1986-06-18",7.6 +"1986-06-19",8.6 +"1986-06-20",5.7 +"1986-06-21",5.5 +"1986-06-22",5.7 +"1986-06-23",5.7 +"1986-06-24",6.6 +"1986-06-25",6.0 +"1986-06-26",6.9 +"1986-06-27",7.7 +"1986-06-28",8.0 +"1986-06-29",3.9 +"1986-06-30",0.8 +"1986-07-01",2.8 +"1986-07-02",8.0 +"1986-07-03",9.8 +"1986-07-04",11.4 +"1986-07-05",8.6 +"1986-07-06",5.2 +"1986-07-07",6.6 +"1986-07-08",5.7 +"1986-07-09",4.6 +"1986-07-10",5.8 +"1986-07-11",7.0 +"1986-07-12",4.8 +"1986-07-13",4.4 +"1986-07-14",4.4 +"1986-07-15",7.9 +"1986-07-16",10.6 +"1986-07-17",5.0 +"1986-07-18",7.6 +"1986-07-19",9.2 +"1986-07-20",9.7 +"1986-07-21",8.8 +"1986-07-22",6.8 +"1986-07-23",9.4 +"1986-07-24",11.0 +"1986-07-25",2.5 +"1986-07-26",2.1 +"1986-07-27",5.4 +"1986-07-28",6.2 +"1986-07-29",7.8 +"1986-07-30",7.4 +"1986-07-31",9.3 +"1986-08-01",9.3 +"1986-08-02",9.5 +"1986-08-03",8.5 +"1986-08-04",10.0 +"1986-08-05",7.7 +"1986-08-06",9.3 +"1986-08-07",9.1 +"1986-08-08",3.5 +"1986-08-09",3.6 +"1986-08-10",2.5 +"1986-08-11",1.7 +"1986-08-12",2.7 +"1986-08-13",2.9 +"1986-08-14",5.3 +"1986-08-15",7.7 +"1986-08-16",9.1 +"1986-08-17",9.4 +"1986-08-18",7.3 +"1986-08-19",8.4 +"1986-08-20",9.2 +"1986-08-21",6.6 +"1986-08-22",9.7 +"1986-08-23",12.4 +"1986-08-24",10.2 +"1986-08-25",5.9 +"1986-08-26",7.1 +"1986-08-27",7.5 +"1986-08-28",9.7 +"1986-08-29",12.2 +"1986-08-30",5.6 +"1986-08-31",5.4 +"1986-09-01",8.3 +"1986-09-02",10.6 +"1986-09-03",9.1 +"1986-09-04",11.3 +"1986-09-05",10.9 +"1986-09-06",8.9 +"1986-09-07",6.3 +"1986-09-08",9.0 +"1986-09-09",6.1 +"1986-09-10",9.1 +"1986-09-11",9.6 +"1986-09-12",6.0 +"1986-09-13",10.0 +"1986-09-14",11.0 +"1986-09-15",6.2 +"1986-09-16",8.3 +"1986-09-17",11.3 +"1986-09-18",11.3 +"1986-09-19",6.7 +"1986-09-20",6.6 +"1986-09-21",11.4 +"1986-09-22",6.9 +"1986-09-23",10.6 +"1986-09-24",8.6 +"1986-09-25",11.3 +"1986-09-26",12.5 +"1986-09-27",9.9 +"1986-09-28",6.9 +"1986-09-29",5.5 +"1986-09-30",7.8 +"1986-10-01",11.0 +"1986-10-02",16.2 +"1986-10-03",9.9 +"1986-10-04",8.7 +"1986-10-05",10.5 +"1986-10-06",12.2 +"1986-10-07",10.6 +"1986-10-08",8.3 +"1986-10-09",5.5 +"1986-10-10",9.0 +"1986-10-11",6.4 +"1986-10-12",7.2 +"1986-10-13",12.9 +"1986-10-14",12.0 +"1986-10-15",7.3 +"1986-10-16",9.7 +"1986-10-17",8.4 +"1986-10-18",14.7 +"1986-10-19",9.5 +"1986-10-20",7.9 +"1986-10-21",6.8 +"1986-10-22",12.6 +"1986-10-23",5.2 +"1986-10-24",7.5 +"1986-10-25",8.7 +"1986-10-26",7.6 +"1986-10-27",9.0 +"1986-10-28",7.2 +"1986-10-29",10.7 +"1986-10-30",13.1 +"1986-10-31",13.9 +"1986-11-01",10.8 +"1986-11-02",10.4 +"1986-11-03",9.1 +"1986-11-04",16.0 +"1986-11-05",21.0 +"1986-11-06",16.2 +"1986-11-07",8.6 +"1986-11-08",9.2 +"1986-11-09",12.5 +"1986-11-10",9.7 +"1986-11-11",12.5 +"1986-11-12",10.3 +"1986-11-13",12.0 +"1986-11-14",11.0 +"1986-11-15",14.8 +"1986-11-16",15.0 +"1986-11-17",15.3 +"1986-11-18",10.3 +"1986-11-19",10.7 +"1986-11-20",10.5 +"1986-11-21",8.9 +"1986-11-22",8.1 +"1986-11-23",11.5 +"1986-11-24",12.8 +"1986-11-25",9.1 +"1986-11-26",14.6 +"1986-11-27",11.6 +"1986-11-28",11.2 +"1986-11-29",12.6 +"1986-11-30",7.5 +"1986-12-01",11.0 +"1986-12-02",14.5 +"1986-12-03",18.5 +"1986-12-04",15.4 +"1986-12-05",13.1 +"1986-12-06",16.3 +"1986-12-07",20.2 +"1986-12-08",11.5 +"1986-12-09",12.4 +"1986-12-10",10.9 +"1986-12-11",12.7 +"1986-12-12",12.2 +"1986-12-13",12.4 +"1986-12-14",9.8 +"1986-12-15",8.5 +"1986-12-16",14.7 +"1986-12-17",12.0 +"1986-12-18",10.3 +"1986-12-19",11.0 +"1986-12-20",10.2 +"1986-12-21",12.6 +"1986-12-22",11.6 +"1986-12-23",9.7 +"1986-12-24",13.4 +"1986-12-25",10.5 +"1986-12-26",14.7 +"1986-12-27",14.6 +"1986-12-28",14.2 +"1986-12-29",13.2 +"1986-12-30",11.7 +"1986-12-31",17.2 +"1987-01-01",12.3 +"1987-01-02",13.8 +"1987-01-03",15.3 +"1987-01-04",15.6 +"1987-01-05",16.2 +"1987-01-06",16.3 +"1987-01-07",16.8 +"1987-01-08",11.0 +"1987-01-09",8.5 +"1987-01-10",13.2 +"1987-01-11",13.0 +"1987-01-12",12.4 +"1987-01-13",13.0 +"1987-01-14",16.6 +"1987-01-15",12.0 +"1987-01-16",12.4 +"1987-01-17",15.0 +"1987-01-18",11.8 +"1987-01-19",11.6 +"1987-01-20",12.2 +"1987-01-21",13.7 +"1987-01-22",11.2 +"1987-01-23",12.4 +"1987-01-24",11.5 +"1987-01-25",13.8 +"1987-01-26",15.7 +"1987-01-27",12.9 +"1987-01-28",11.5 +"1987-01-29",11.0 +"1987-01-30",12.7 +"1987-01-31",14.9 +"1987-02-01",16.5 +"1987-02-02",12.8 +"1987-02-03",12.7 +"1987-02-04",12.7 +"1987-02-05",11.6 +"1987-02-06",13.3 +"1987-02-07",15.2 +"1987-02-08",16.4 +"1987-02-09",11.9 +"1987-02-10",15.1 +"1987-02-11",10.6 +"1987-02-12",13.6 +"1987-02-13",12.1 +"1987-02-14",16.0 +"1987-02-15",16.8 +"1987-02-16",16.6 +"1987-02-17",15.6 +"1987-02-18",15.2 +"1987-02-19",17.7 +"1987-02-20",21.0 +"1987-02-21",13.4 +"1987-02-22",10.5 +"1987-02-23",9.5 +"1987-02-24",12.0 +"1987-02-25",10.4 +"1987-02-26",11.5 +"1987-02-27",13.2 +"1987-02-28",15.0 +"1987-03-01",14.1 +"1987-03-02",12.4 +"1987-03-03",13.4 +"1987-03-04",12.5 +"1987-03-05",14.3 +"1987-03-06",17.6 +"1987-03-07",10.4 +"1987-03-08",9.9 +"1987-03-09",10.2 +"1987-03-10",11.3 +"1987-03-11",9.5 +"1987-03-12",11.8 +"1987-03-13",11.5 +"1987-03-14",10.5 +"1987-03-15",10.8 +"1987-03-16",13.0 +"1987-03-17",18.5 +"1987-03-18",18.7 +"1987-03-19",15.0 +"1987-03-20",13.0 +"1987-03-21",11.3 +"1987-03-22",13.0 +"1987-03-23",13.3 +"1987-03-24",11.0 +"1987-03-25",10.3 +"1987-03-26",13.0 +"1987-03-27",12.3 +"1987-03-28",15.6 +"1987-03-29",10.2 +"1987-03-30",10.8 +"1987-03-31",12.0 +"1987-04-01",13.3 +"1987-04-02",11.7 +"1987-04-03",12.5 +"1987-04-04",13.7 +"1987-04-05",14.9 +"1987-04-06",20.2 +"1987-04-07",16.3 +"1987-04-08",13.9 +"1987-04-09",10.1 +"1987-04-10",7.3 +"1987-04-11",14.0 +"1987-04-12",17.7 +"1987-04-13",16.3 +"1987-04-14",10.6 +"1987-04-15",9.7 +"1987-04-16",7.8 +"1987-04-17",10.4 +"1987-04-18",10.4 +"1987-04-19",14.1 +"1987-04-20",7.1 +"1987-04-21",8.1 +"1987-04-22",7.8 +"1987-04-23",10.6 +"1987-04-24",9.1 +"1987-04-25",9.0 +"1987-04-26",11.9 +"1987-04-27",17.1 +"1987-04-28",16.8 +"1987-04-29",13.5 +"1987-04-30",11.6 +"1987-05-01",7.0 +"1987-05-02",9.7 +"1987-05-03",9.9 +"1987-05-04",11.2 +"1987-05-05",11.3 +"1987-05-06",11.8 +"1987-05-07",9.9 +"1987-05-08",7.1 +"1987-05-09",9.6 +"1987-05-10",9.8 +"1987-05-11",10.6 +"1987-05-12",12.8 +"1987-05-13",16.5 +"1987-05-14",11.7 +"1987-05-15",12.3 +"1987-05-16",12.2 +"1987-05-17",11.8 +"1987-05-18",10.7 +"1987-05-19",10.2 +"1987-05-20",10.0 +"1987-05-21",8.3 +"1987-05-22",6.6 +"1987-05-23",9.5 +"1987-05-24",12.3 +"1987-05-25",7.6 +"1987-05-26",9.3 +"1987-05-27",5.0 +"1987-05-28",4.3 +"1987-05-29",6.4 +"1987-05-30",10.8 +"1987-05-31",7.8 +"1987-06-01",8.5 +"1987-06-02",9.7 +"1987-06-03",10.0 +"1987-06-04",11.0 +"1987-06-05",10.2 +"1987-06-06",6.6 +"1987-06-07",6.1 +"1987-06-08",5.9 +"1987-06-09",8.9 +"1987-06-10",13.0 +"1987-06-11",12.6 +"1987-06-12",5.4 +"1987-06-13",6.0 +"1987-06-14",7.8 +"1987-06-15",9.0 +"1987-06-16",4.2 +"1987-06-17",3.0 +"1987-06-18",4.5 +"1987-06-19",6.2 +"1987-06-20",11.9 +"1987-06-21",11.8 +"1987-06-22",9.4 +"1987-06-23",9.6 +"1987-06-24",9.4 +"1987-06-25",7.0 +"1987-06-26",8.9 +"1987-06-27",9.3 +"1987-06-28",6.8 +"1987-06-29",7.5 +"1987-06-30",8.0 +"1987-07-01",8.3 +"1987-07-02",2.7 +"1987-07-03",3.9 +"1987-07-04",4.1 +"1987-07-05",5.0 +"1987-07-06",5.8 +"1987-07-07",4.4 +"1987-07-08",4.1 +"1987-07-09",5.8 +"1987-07-10",9.1 +"1987-07-11",7.9 +"1987-07-12",5.0 +"1987-07-13",2.8 +"1987-07-14",4.7 +"1987-07-15",8.9 +"1987-07-16",5.4 +"1987-07-17",7.1 +"1987-07-18",9.0 +"1987-07-19",9.4 +"1987-07-20",6.3 +"1987-07-21",7.0 +"1987-07-22",6.4 +"1987-07-23",6.7 +"1987-07-24",1.5 +"1987-07-25",2.9 +"1987-07-26",4.8 +"1987-07-27",6.3 +"1987-07-28",5.7 +"1987-07-29",7.0 +"1987-07-30",8.8 +"1987-07-31",8.7 +"1987-08-01",9.0 +"1987-08-02",9.6 +"1987-08-03",8.0 +"1987-08-04",8.4 +"1987-08-05",8.1 +"1987-08-06",9.0 +"1987-08-07",5.3 +"1987-08-08",8.9 +"1987-08-09",8.7 +"1987-08-10",4.9 +"1987-08-11",7.0 +"1987-08-12",7.5 +"1987-08-13",7.0 +"1987-08-14",9.1 +"1987-08-15",11.8 +"1987-08-16",9.9 +"1987-08-17",5.6 +"1987-08-18",4.2 +"1987-08-19",4.3 +"1987-08-20",8.0 +"1987-08-21",5.1 +"1987-08-22",9.4 +"1987-08-23",9.1 +"1987-08-24",9.7 +"1987-08-25",10.6 +"1987-08-26",8.6 +"1987-08-27",10.1 +"1987-08-28",11.0 +"1987-08-29",9.7 +"1987-08-30",5.0 +"1987-08-31",6.1 +"1987-09-01",5.4 +"1987-09-02",5.8 +"1987-09-03",7.3 +"1987-09-04",6.3 +"1987-09-05",4.8 +"1987-09-06",7.6 +"1987-09-07",8.1 +"1987-09-08",9.5 +"1987-09-09",10.3 +"1987-09-10",7.0 +"1987-09-11",9.0 +"1987-09-12",10.2 +"1987-09-13",6.8 +"1987-09-14",9.3 +"1987-09-15",9.8 +"1987-09-16",10.7 +"1987-09-17",7.8 +"1987-09-18",9.2 +"1987-09-19",15.0 +"1987-09-20",7.8 +"1987-09-21",5.3 +"1987-09-22",9.5 +"1987-09-23",7.6 +"1987-09-24",14.0 +"1987-09-25",14.9 +"1987-09-26",14.9 +"1987-09-27",19.2 +"1987-09-28",17.0 +"1987-09-29",13.0 +"1987-09-30",11.2 +"1987-10-01",9.5 +"1987-10-02",10.3 +"1987-10-03",9.3 +"1987-10-04",11.3 +"1987-10-05",6.5 +"1987-10-06",12.0 +"1987-10-07",8.3 +"1987-10-08",8.7 +"1987-10-09",8.7 +"1987-10-10",10.2 +"1987-10-11",6.9 +"1987-10-12",4.9 +"1987-10-13",10.0 +"1987-10-14",7.6 +"1987-10-15",14.5 +"1987-10-16",13.2 +"1987-10-17",9.9 +"1987-10-18",10.1 +"1987-10-19",11.3 +"1987-10-20",10.4 +"1987-10-21",10.9 +"1987-10-22",9.2 +"1987-10-23",10.5 +"1987-10-24",11.4 +"1987-10-25",13.5 +"1987-10-26",9.8 +"1987-10-27",13.1 +"1987-10-28",9.7 +"1987-10-29",11.4 +"1987-10-30",9.9 +"1987-10-31",14.4 +"1987-11-01",19.0 +"1987-11-02",23.0 +"1987-11-03",15.4 +"1987-11-04",9.6 +"1987-11-05",10.8 +"1987-11-06",12.1 +"1987-11-07",11.0 +"1987-11-08",12.6 +"1987-11-09",14.7 +"1987-11-10",11.1 +"1987-11-11",10.1 +"1987-11-12",11.4 +"1987-11-13",13.0 +"1987-11-14",11.9 +"1987-11-15",9.5 +"1987-11-16",13.5 +"1987-11-17",15.2 +"1987-11-18",18.4 +"1987-11-19",24.1 +"1987-11-20",14.1 +"1987-11-21",10.7 +"1987-11-22",8.7 +"1987-11-23",13.3 +"1987-11-24",11.6 +"1987-11-25",9.9 +"1987-11-26",10.8 +"1987-11-27",11.5 +"1987-11-28",10.0 +"1987-11-29",13.9 +"1987-11-30",13.6 +"1987-12-01",11.9 +"1987-12-02",11.1 +"1987-12-03",8.2 +"1987-12-04",9.4 +"1987-12-05",12.7 +"1987-12-06",11.6 +"1987-12-07",11.0 +"1987-12-08",11.3 +"1987-12-09",13.4 +"1987-12-10",14.9 +"1987-12-11",15.2 +"1987-12-12",13.9 +"1987-12-13",15.0 +"1987-12-14",16.2 +"1987-12-15",17.7 +"1987-12-16",20.5 +"1987-12-17",14.7 +"1987-12-18",12.5 +"1987-12-19",10.9 +"1987-12-20",12.8 +"1987-12-21",12.7 +"1987-12-22",11.2 +"1987-12-23",11.4 +"1987-12-24",11.2 +"1987-12-25",12.1 +"1987-12-26",12.7 +"1987-12-27",16.2 +"1987-12-28",14.2 +"1987-12-29",14.3 +"1987-12-30",13.3 +"1987-12-31",16.7 +"1988-01-01",15.3 +"1988-01-02",14.3 +"1988-01-03",13.5 +"1988-01-04",15.0 +"1988-01-05",13.6 +"1988-01-06",15.2 +"1988-01-07",17.0 +"1988-01-08",18.7 +"1988-01-09",16.5 +"1988-01-10",17.4 +"1988-01-11",18.3 +"1988-01-12",18.3 +"1988-01-13",22.4 +"1988-01-14",21.4 +"1988-01-15",20.9 +"1988-01-16",17.6 +"1988-01-17",15.5 +"1988-01-18",16.6 +"1988-01-19",16.2 +"1988-01-20",15.6 +"1988-01-21",14.5 +"1988-01-22",14.0 +"1988-01-23",15.6 +"1988-01-24",12.3 +"1988-01-25",11.6 +"1988-01-26",12.6 +"1988-01-27",14.9 +"1988-01-28",17.3 +"1988-01-29",21.4 +"1988-01-30",23.4 +"1988-01-31",14.4 +"1988-02-01",14.1 +"1988-02-02",15.0 +"1988-02-03",14.5 +"1988-02-04",15.1 +"1988-02-05",13.9 +"1988-02-06",13.4 +"1988-02-07",9.2 +"1988-02-08",12.5 +"1988-02-09",15.1 +"1988-02-10",12.1 +"1988-02-11",14.5 +"1988-02-12",16.3 +"1988-02-13",16.5 +"1988-02-14",14.9 +"1988-02-15",13.2 +"1988-02-16",11.8 +"1988-02-17",13.6 +"1988-02-18",16.2 +"1988-02-19",14.1 +"1988-02-20",13.5 +"1988-02-21",15.0 +"1988-02-22",14.8 +"1988-02-23",16.2 +"1988-02-24",16.2 +"1988-02-25",13.3 +"1988-02-26",15.3 +"1988-02-27",18.4 +"1988-02-28",16.2 +"1988-02-29",16.3 +"1988-03-01",12.4 +"1988-03-02",15.6 +"1988-03-03",14.9 +"1988-03-04",14.8 +"1988-03-05",12.7 +"1988-03-06",14.2 +"1988-03-07",16.8 +"1988-03-08",16.7 +"1988-03-09",16.2 +"1988-03-10",14.5 +"1988-03-11",10.0 +"1988-03-12",12.6 +"1988-03-13",11.9 +"1988-03-14",11.8 +"1988-03-15",13.4 +"1988-03-16",14.5 +"1988-03-17",15.7 +"1988-03-18",15.3 +"1988-03-19",13.9 +"1988-03-20",13.7 +"1988-03-21",15.1 +"1988-03-22",15.6 +"1988-03-23",14.4 +"1988-03-24",13.9 +"1988-03-25",16.2 +"1988-03-26",16.7 +"1988-03-27",15.5 +"1988-03-28",16.4 +"1988-03-29",17.5 +"1988-03-30",18.2 +"1988-03-31",16.1 +"1988-04-01",16.5 +"1988-04-02",14.6 +"1988-04-03",16.4 +"1988-04-04",13.6 +"1988-04-05",15.9 +"1988-04-06",11.9 +"1988-04-07",14.7 +"1988-04-08",9.4 +"1988-04-09",6.6 +"1988-04-10",7.9 +"1988-04-11",11.0 +"1988-04-12",15.7 +"1988-04-13",15.2 +"1988-04-14",15.9 +"1988-04-15",10.6 +"1988-04-16",8.3 +"1988-04-17",8.6 +"1988-04-18",12.7 +"1988-04-19",10.5 +"1988-04-20",12.0 +"1988-04-21",11.1 +"1988-04-22",13.0 +"1988-04-23",12.4 +"1988-04-24",13.3 +"1988-04-25",15.9 +"1988-04-26",12.0 +"1988-04-27",13.7 +"1988-04-28",17.6 +"1988-04-29",14.3 +"1988-04-30",13.7 +"1988-05-01",15.2 +"1988-05-02",14.5 +"1988-05-03",14.9 +"1988-05-04",15.5 +"1988-05-05",16.4 +"1988-05-06",14.5 +"1988-05-07",12.6 +"1988-05-08",13.6 +"1988-05-09",11.2 +"1988-05-10",11.0 +"1988-05-11",12.0 +"1988-05-12",6.8 +"1988-05-13",10.6 +"1988-05-14",13.1 +"1988-05-15",13.5 +"1988-05-16",11.7 +"1988-05-17",13.2 +"1988-05-18",12.0 +"1988-05-19",10.4 +"1988-05-20",10.0 +"1988-05-21",8.2 +"1988-05-22",9.4 +"1988-05-23",10.3 +"1988-05-24",8.1 +"1988-05-25",8.7 +"1988-05-26",12.6 +"1988-05-27",10.9 +"1988-05-28",8.7 +"1988-05-29",9.3 +"1988-05-30",6.3 +"1988-05-31",7.8 +"1988-06-01",10.0 +"1988-06-02",11.0 +"1988-06-03",11.1 +"1988-06-04",12.6 +"1988-06-05",10.2 +"1988-06-06",11.1 +"1988-06-07",8.7 +"1988-06-08",9.5 +"1988-06-09",9.7 +"1988-06-10",8.2 +"1988-06-11",5.0 +"1988-06-12",6.5 +"1988-06-13",12.1 +"1988-06-14",8.9 +"1988-06-15",6.1 +"1988-06-16",2.8 +"1988-06-17",3.7 +"1988-06-18",6.8 +"1988-06-19",6.6 +"1988-06-20",7.0 +"1988-06-21",7.3 +"1988-06-22",7.9 +"1988-06-23",10.6 +"1988-06-24",8.1 +"1988-06-25",6.7 +"1988-06-26",8.0 +"1988-06-27",10.0 +"1988-06-28",6.7 +"1988-06-29",9.4 +"1988-06-30",9.3 +"1988-07-01",6.0 +"1988-07-02",5.8 +"1988-07-03",4.9 +"1988-07-04",5.0 +"1988-07-05",8.4 +"1988-07-06",12.3 +"1988-07-07",13.0 +"1988-07-08",11.4 +"1988-07-09",6.8 +"1988-07-10",7.6 +"1988-07-11",12.4 +"1988-07-12",7.1 +"1988-07-13",7.5 +"1988-07-14",10.0 +"1988-07-15",5.3 +"1988-07-16",6.3 +"1988-07-17",8.0 +"1988-07-18",8.3 +"1988-07-19",9.3 +"1988-07-20",9.5 +"1988-07-21",5.6 +"1988-07-22",7.0 +"1988-07-23",8.5 +"1988-07-24",8.5 +"1988-07-25",8.2 +"1988-07-26",8.5 +"1988-07-27",9.6 +"1988-07-28",9.7 +"1988-07-29",7.1 +"1988-07-30",8.4 +"1988-07-31",9.2 +"1988-08-01",9.8 +"1988-08-02",8.1 +"1988-08-03",9.4 +"1988-08-04",10.0 +"1988-08-05",5.1 +"1988-08-06",6.7 +"1988-08-07",6.9 +"1988-08-08",6.8 +"1988-08-09",8.6 +"1988-08-10",9.1 +"1988-08-11",3.9 +"1988-08-12",4.8 +"1988-08-13",8.4 +"1988-08-14",11.6 +"1988-08-15",12.1 +"1988-08-16",12.4 +"1988-08-17",10.0 +"1988-08-18",10.1 +"1988-08-19",9.7 +"1988-08-20",11.7 +"1988-08-21",7.9 +"1988-08-22",8.6 +"1988-08-23",7.7 +"1988-08-24",5.8 +"1988-08-25",8.7 +"1988-08-26",10.6 +"1988-08-27",6.7 +"1988-08-28",8.8 +"1988-08-29",9.7 +"1988-08-30",9.0 +"1988-08-31",11.8 +"1988-09-01",15.2 +"1988-09-02",10.0 +"1988-09-03",10.5 +"1988-09-04",5.5 +"1988-09-05",9.4 +"1988-09-06",8.8 +"1988-09-07",5.3 +"1988-09-08",13.0 +"1988-09-09",15.2 +"1988-09-10",13.2 +"1988-09-11",11.5 +"1988-09-12",6.8 +"1988-09-13",4.7 +"1988-09-14",5.2 +"1988-09-15",6.8 +"1988-09-16",10.7 +"1988-09-17",10.1 +"1988-09-18",10.0 +"1988-09-19",9.8 +"1988-09-20",5.5 +"1988-09-21",13.5 +"1988-09-22",16.6 +"1988-09-23",8.4 +"1988-09-24",8.2 +"1988-09-25",11.1 +"1988-09-26",10.8 +"1988-09-27",8.8 +"1988-09-28",10.8 +"1988-09-29",8.7 +"1988-09-30",12.4 +"1988-10-01",9.0 +"1988-10-02",13.5 +"1988-10-03",14.7 +"1988-10-04",10.9 +"1988-10-05",8.5 +"1988-10-06",6.0 +"1988-10-07",12.7 +"1988-10-08",11.1 +"1988-10-09",8.7 +"1988-10-10",12.3 +"1988-10-11",13.3 +"1988-10-12",5.6 +"1988-10-13",13.7 +"1988-10-14",8.5 +"1988-10-15",11.2 +"1988-10-16",8.7 +"1988-10-17",11.7 +"1988-10-18",12.5 +"1988-10-19",8.2 +"1988-10-20",15.6 +"1988-10-21",10.3 +"1988-10-22",11.4 +"1988-10-23",9.7 +"1988-10-24",6.3 +"1988-10-25",14.3 +"1988-10-26",11.3 +"1988-10-27",7.3 +"1988-10-28",12.8 +"1988-10-29",11.9 +"1988-10-30",14.3 +"1988-10-31",11.6 +"1988-11-01",13.2 +"1988-11-02",15.5 +"1988-11-03",14.1 +"1988-11-04",9.5 +"1988-11-05",7.2 +"1988-11-06",11.8 +"1988-11-07",16.8 +"1988-11-08",12.5 +"1988-11-09",9.4 +"1988-11-10",11.9 +"1988-11-11",10.3 +"1988-11-12",16.9 +"1988-11-13",17.5 +"1988-11-14",7.5 +"1988-11-15",8.6 +"1988-11-16",11.1 +"1988-11-17",11.5 +"1988-11-18",10.7 +"1988-11-19",15.7 +"1988-11-20",12.8 +"1988-11-21",13.0 +"1988-11-22",12.9 +"1988-11-23",14.3 +"1988-11-24",13.7 +"1988-11-25",12.1 +"1988-11-26",11.9 +"1988-11-27",11.8 +"1988-11-28",11.4 +"1988-11-29",10.3 +"1988-11-30",11.7 +"1988-12-01",12.0 +"1988-12-02",17.4 +"1988-12-03",16.8 +"1988-12-04",16.2 +"1988-12-05",13.0 +"1988-12-06",12.5 +"1988-12-07",12.4 +"1988-12-08",16.1 +"1988-12-09",20.2 +"1988-12-10",14.3 +"1988-12-11",11.0 +"1988-12-12",14.4 +"1988-12-13",15.7 +"1988-12-14",19.7 +"1988-12-15",20.7 +"1988-12-16",23.9 +"1988-12-17",16.6 +"1988-12-18",17.5 +"1988-12-19",14.9 +"1988-12-20",13.6 +"1988-12-21",11.9 +"1988-12-22",15.2 +"1988-12-23",17.3 +"1988-12-24",19.8 +"1988-12-25",15.8 +"1988-12-26",9.5 +"1988-12-27",12.9 +"1988-12-28",12.9 +"1988-12-29",14.8 +"1988-12-30",14.1 +"1989-01-01",14.3 +"1989-01-02",17.4 +"1989-01-03",18.5 +"1989-01-04",16.8 +"1989-01-05",11.5 +"1989-01-06",9.5 +"1989-01-07",12.2 +"1989-01-08",15.7 +"1989-01-09",16.3 +"1989-01-10",13.6 +"1989-01-11",12.6 +"1989-01-12",13.8 +"1989-01-13",12.1 +"1989-01-14",13.4 +"1989-01-15",17.3 +"1989-01-16",19.4 +"1989-01-17",16.6 +"1989-01-18",13.9 +"1989-01-19",13.1 +"1989-01-20",16.0 +"1989-01-21",14.5 +"1989-01-22",15.0 +"1989-01-23",12.6 +"1989-01-24",12.5 +"1989-01-25",15.2 +"1989-01-26",16.2 +"1989-01-27",16.5 +"1989-01-28",20.1 +"1989-01-29",20.6 +"1989-01-30",16.9 +"1989-01-31",16.5 +"1989-02-01",16.1 +"1989-02-02",14.4 +"1989-02-03",16.3 +"1989-02-04",15.7 +"1989-02-05",14.2 +"1989-02-06",13.2 +"1989-02-07",16.8 +"1989-02-08",18.5 +"1989-02-09",16.7 +"1989-02-10",15.3 +"1989-02-11",15.9 +"1989-02-12",15.2 +"1989-02-13",17.5 +"1989-02-14",18.3 +"1989-02-15",19.4 +"1989-02-16",19.4 +"1989-02-17",19.5 +"1989-02-18",20.5 +"1989-02-19",15.7 +"1989-02-20",15.0 +"1989-02-21",16.1 +"1989-02-22",14.3 +"1989-02-23",13.0 +"1989-02-24",16.2 +"1989-02-25",17.7 +"1989-02-26",13.2 +"1989-02-27",15.8 +"1989-02-28",18.5 +"1989-03-01",20.4 +"1989-03-02",22.0 +"1989-03-03",19.7 +"1989-03-04",19.6 +"1989-03-05",20.3 +"1989-03-06",18.3 +"1989-03-07",18.9 +"1989-03-08",20.3 +"1989-03-09",21.4 +"1989-03-10",18.3 +"1989-03-11",17.8 +"1989-03-12",17.7 +"1989-03-13",12.8 +"1989-03-14",15.1 +"1989-03-15",15.0 +"1989-03-16",14.8 +"1989-03-17",12.0 +"1989-03-18",12.5 +"1989-03-19",15.0 +"1989-03-20",17.1 +"1989-03-21",17.3 +"1989-03-22",16.9 +"1989-03-23",16.5 +"1989-03-24",13.6 +"1989-03-25",13.2 +"1989-03-26",9.4 +"1989-03-27",9.5 +"1989-03-28",11.8 +"1989-03-29",10.4 +"1989-03-30",9.7 +"1989-03-31",12.6 +"1989-04-01",13.3 +"1989-04-02",15.1 +"1989-04-03",14.2 +"1989-04-04",14.2 +"1989-04-05",19.2 +"1989-04-06",12.6 +"1989-04-07",14.2 +"1989-04-08",11.9 +"1989-04-09",13.9 +"1989-04-10",13.5 +"1989-04-11",15.3 +"1989-04-12",13.9 +"1989-04-13",14.0 +"1989-04-14",12.9 +"1989-04-15",8.5 +"1989-04-16",11.4 +"1989-04-17",10.9 +"1989-04-18",12.0 +"1989-04-19",8.6 +"1989-04-20",9.0 +"1989-04-21",9.6 +"1989-04-22",10.2 +"1989-04-23",9.8 +"1989-04-24",8.3 +"1989-04-25",11.0 +"1989-04-26",11.9 +"1989-04-27",14.0 +"1989-04-28",15.8 +"1989-04-29",14.5 +"1989-04-30",13.2 +"1989-05-01",14.2 +"1989-05-02",14.6 +"1989-05-03",11.8 +"1989-05-04",14.4 +"1989-05-05",10.4 +"1989-05-06",10.3 +"1989-05-07",10.8 +"1989-05-08",10.5 +"1989-05-09",9.5 +"1989-05-10",12.5 +"1989-05-11",13.7 +"1989-05-12",12.7 +"1989-05-13",11.9 +"1989-05-14",11.4 +"1989-05-15",9.7 +"1989-05-16",8.3 +"1989-05-17",8.1 +"1989-05-18",11.7 +"1989-05-19",11.6 +"1989-05-20",7.4 +"1989-05-21",5.2 +"1989-05-22",11.0 +"1989-05-23",9.5 +"1989-05-24",9.2 +"1989-05-25",10.7 +"1989-05-26",9.0 +"1989-05-27",10.2 +"1989-05-28",10.3 +"1989-05-29",12.1 +"1989-05-30",13.2 +"1989-05-31",6.6 +"1989-06-01",2.3 +"1989-06-02",1.4 +"1989-06-03",2.1 +"1989-06-04",6.6 +"1989-06-05",8.9 +"1989-06-06",7.8 +"1989-06-07",9.0 +"1989-06-08",10.3 +"1989-06-09",7.9 +"1989-06-10",7.2 +"1989-06-11",8.6 +"1989-06-12",8.8 +"1989-06-13",6.2 +"1989-06-14",9.5 +"1989-06-15",10.2 +"1989-06-16",9.7 +"1989-06-17",11.2 +"1989-06-18",10.2 +"1989-06-19",10.1 +"1989-06-20",8.1 +"1989-06-21",6.6 +"1989-06-22",5.0 +"1989-06-23",4.7 +"1989-06-24",5.3 +"1989-06-25",4.5 +"1989-06-26",2.3 +"1989-06-27",1.4 +"1989-06-28",0.5 +"1989-06-29",2.4 +"1989-06-30",8.0 +"1989-07-01",6.0 +"1989-07-02",7.1 +"1989-07-03",9.7 +"1989-07-04",6.9 +"1989-07-05",5.3 +"1989-07-06",7.0 +"1989-07-07",6.2 +"1989-07-08",7.0 +"1989-07-09",9.7 +"1989-07-10",8.0 +"1989-07-11",8.5 +"1989-07-12",7.1 +"1989-07-13",7.5 +"1989-07-14",3.3 +"1989-07-15",1.8 +"1989-07-16",2.6 +"1989-07-17",5.3 +"1989-07-18",5.8 +"1989-07-19",5.8 +"1989-07-20",7.2 +"1989-07-21",5.3 +"1989-07-22",1.6 +"1989-07-23",3.1 +"1989-07-24",5.3 +"1989-07-25",7.7 +"1989-07-26",4.2 +"1989-07-27",5.5 +"1989-07-28",9.0 +"1989-07-29",11.2 +"1989-07-30",8.0 +"1989-07-31",7.6 +"1989-08-01",3.7 +"1989-08-02",7.5 +"1989-08-03",8.1 +"1989-08-04",8.4 +"1989-08-05",7.1 +"1989-08-06",7.6 +"1989-08-07",7.6 +"1989-08-08",5.6 +"1989-08-09",7.0 +"1989-08-10",10.5 +"1989-08-11",7.3 +"1989-08-12",7.8 +"1989-08-13",5.8 +"1989-08-14",3.8 +"1989-08-15",5.8 +"1989-08-16",6.7 +"1989-08-17",6.6 +"1989-08-18",6.6 +"1989-08-19",9.0 +"1989-08-20",8.1 +"1989-08-21",5.1 +"1989-08-22",8.6 +"1989-08-23",7.0 +"1989-08-24",5.5 +"1989-08-25",7.4 +"1989-08-26",6.2 +"1989-08-27",4.2 +"1989-08-28",6.3 +"1989-08-29",7.0 +"1989-08-30",4.0 +"1989-08-31",8.0 +"1989-09-01",8.8 +"1989-09-02",8.8 +"1989-09-03",6.1 +"1989-09-04",8.6 +"1989-09-05",8.9 +"1989-09-06",7.8 +"1989-09-07",5.0 +"1989-09-08",7.0 +"1989-09-09",13.3 +"1989-09-10",7.9 +"1989-09-11",7.5 +"1989-09-12",8.3 +"1989-09-13",7.2 +"1989-09-14",6.5 +"1989-09-15",8.9 +"1989-09-16",7.4 +"1989-09-17",9.9 +"1989-09-18",9.3 +"1989-09-19",10.6 +"1989-09-20",8.6 +"1989-09-21",7.2 +"1989-09-22",12.6 +"1989-09-23",7.8 +"1989-09-24",6.3 +"1989-09-25",9.2 +"1989-09-26",5.8 +"1989-09-27",9.0 +"1989-09-28",5.0 +"1989-09-29",11.9 +"1989-09-30",13.4 +"1989-10-01",10.5 +"1989-10-02",6.2 +"1989-10-03",5.1 +"1989-10-04",9.5 +"1989-10-05",11.7 +"1989-10-06",9.2 +"1989-10-07",7.3 +"1989-10-08",9.7 +"1989-10-09",9.4 +"1989-10-10",10.0 +"1989-10-11",10.9 +"1989-10-12",11.0 +"1989-10-13",10.9 +"1989-10-14",8.0 +"1989-10-15",11.2 +"1989-10-16",7.5 +"1989-10-17",7.2 +"1989-10-18",13.2 +"1989-10-19",12.9 +"1989-10-20",9.4 +"1989-10-21",10.2 +"1989-10-22",9.5 +"1989-10-23",12.4 +"1989-10-24",10.2 +"1989-10-25",13.4 +"1989-10-26",11.6 +"1989-10-27",8.0 +"1989-10-28",9.0 +"1989-10-29",9.3 +"1989-10-30",13.5 +"1989-10-31",8.0 +"1989-11-01",8.1 +"1989-11-02",10.0 +"1989-11-03",8.5 +"1989-11-04",12.5 +"1989-11-05",15.0 +"1989-11-06",13.3 +"1989-11-07",11.0 +"1989-11-08",11.9 +"1989-11-09",8.3 +"1989-11-10",9.7 +"1989-11-11",11.3 +"1989-11-12",12.5 +"1989-11-13",9.4 +"1989-11-14",11.4 +"1989-11-15",13.2 +"1989-11-16",13.8 +"1989-11-17",16.0 +"1989-11-18",10.9 +"1989-11-19",11.9 +"1989-11-20",12.4 +"1989-11-21",13.2 +"1989-11-22",15.5 +"1989-11-23",21.6 +"1989-11-24",14.9 +"1989-11-25",14.4 +"1989-11-26",12.9 +"1989-11-27",13.1 +"1989-11-28",14.0 +"1989-11-29",17.9 +"1989-11-30",17.7 +"1989-12-01",16.3 +"1989-12-02",18.3 +"1989-12-03",13.7 +"1989-12-04",13.3 +"1989-12-05",10.6 +"1989-12-06",14.1 +"1989-12-07",16.0 +"1989-12-08",16.5 +"1989-12-09",14.1 +"1989-12-10",18.7 +"1989-12-11",16.2 +"1989-12-12",14.8 +"1989-12-13",12.6 +"1989-12-14",10.4 +"1989-12-15",12.2 +"1989-12-16",12.6 +"1989-12-17",12.1 +"1989-12-18",17.3 +"1989-12-19",16.4 +"1989-12-20",12.6 +"1989-12-21",12.3 +"1989-12-22",11.8 +"1989-12-23",12.0 +"1989-12-24",12.7 +"1989-12-25",16.4 +"1989-12-26",16.0 +"1989-12-27",13.3 +"1989-12-28",11.7 +"1989-12-29",10.4 +"1989-12-30",14.4 +"1989-12-31",12.7 +"1990-01-01",14.8 +"1990-01-02",13.3 +"1990-01-03",15.6 +"1990-01-04",14.5 +"1990-01-05",14.3 +"1990-01-06",15.3 +"1990-01-07",16.4 +"1990-01-08",14.8 +"1990-01-09",17.4 +"1990-01-10",18.8 +"1990-01-11",22.1 +"1990-01-12",19.0 +"1990-01-13",15.5 +"1990-01-14",15.8 +"1990-01-15",14.7 +"1990-01-16",10.7 +"1990-01-17",11.5 +"1990-01-18",15.0 +"1990-01-19",14.5 +"1990-01-20",14.5 +"1990-01-21",13.3 +"1990-01-22",14.3 +"1990-01-23",14.3 +"1990-01-24",20.5 +"1990-01-25",15.0 +"1990-01-26",17.1 +"1990-01-27",16.9 +"1990-01-28",16.9 +"1990-01-29",13.6 +"1990-01-30",16.4 +"1990-01-31",16.1 +"1990-02-01",12.0 +"1990-02-02",12.2 +"1990-02-03",14.8 +"1990-02-04",14.8 +"1990-02-05",14.4 +"1990-02-06",12.9 +"1990-02-07",13.4 +"1990-02-08",15.9 +"1990-02-09",16.1 +"1990-02-10",17.6 +"1990-02-11",15.6 +"1990-02-12",15.0 +"1990-02-13",13.0 +"1990-02-14",14.1 +"1990-02-15",17.3 +"1990-02-16",15.7 +"1990-02-17",18.6 +"1990-02-18",12.7 +"1990-02-19",14.0 +"1990-02-20",13.7 +"1990-02-21",16.3 +"1990-02-22",20.0 +"1990-02-23",17.0 +"1990-02-24",15.2 +"1990-02-25",16.5 +"1990-02-26",16.5 +"1990-02-27",17.3 +"1990-02-28",19.1 +"1990-03-01",19.3 +"1990-03-02",17.3 +"1990-03-03",19.0 +"1990-03-04",19.8 +"1990-03-05",19.3 +"1990-03-06",17.2 +"1990-03-07",14.2 +"1990-03-08",10.3 +"1990-03-09",13.0 +"1990-03-10",15.3 +"1990-03-11",15.0 +"1990-03-12",12.1 +"1990-03-13",9.2 +"1990-03-14",11.0 +"1990-03-15",15.0 +"1990-03-16",11.6 +"1990-03-17",11.6 +"1990-03-18",15.1 +"1990-03-19",15.0 +"1990-03-20",13.6 +"1990-03-21",12.5 +"1990-03-22",14.3 +"1990-03-23",16.0 +"1990-03-24",17.4 +"1990-03-25",16.9 +"1990-03-26",18.0 +"1990-03-27",20.6 +"1990-03-28",14.2 +"1990-03-29",10.9 +"1990-03-30",11.9 +"1990-03-31",13.3 +"1990-04-01",15.3 +"1990-04-02",14.7 +"1990-04-03",11.0 +"1990-04-04",12.2 +"1990-04-05",14.2 +"1990-04-06",17.0 +"1990-04-07",15.8 +"1990-04-08",15.2 +"1990-04-09",15.1 +"1990-04-10",14.7 +"1990-04-11",18.5 +"1990-04-12",16.4 +"1990-04-13",18.4 +"1990-04-14",15.1 +"1990-04-15",9.9 +"1990-04-16",10.2 +"1990-04-17",12.6 +"1990-04-18",13.2 +"1990-04-19",11.5 +"1990-04-20",13.8 +"1990-04-21",14.5 +"1990-04-22",14.7 +"1990-04-23",11.2 +"1990-04-24",12.7 +"1990-04-25",13.7 +"1990-04-26",11.5 +"1990-04-27",10.4 +"1990-04-28",8.9 +"1990-04-29",11.1 +"1990-04-30",9.5 +"1990-05-01",13.0 +"1990-05-02",13.9 +"1990-05-03",12.6 +"1990-05-04",14.3 +"1990-05-05",16.0 +"1990-05-06",13.3 +"1990-05-07",7.0 +"1990-05-08",4.9 +"1990-05-09",6.9 +"1990-05-10",13.7 +"1990-05-11",10.6 +"1990-05-12",12.3 +"1990-05-13",11.1 +"1990-05-14",10.2 +"1990-05-15",9.5 +"1990-05-16",8.9 +"1990-05-17",13.4 +"1990-05-18",9.1 +"1990-05-19",9.4 +"1990-05-20",8.7 +"1990-05-21",5.8 +"1990-05-22",4.5 +"1990-05-23",7.2 +"1990-05-24",10.0 +"1990-05-25",10.5 +"1990-05-26",10.7 +"1990-05-27",8.2 +"1990-05-28",6.1 +"1990-05-29",4.5 +"1990-05-30",6.1 +"1990-05-31",9.8 +"1990-06-01",9.7 +"1990-06-02",8.2 +"1990-06-03",8.4 +"1990-06-04",8.5 +"1990-06-05",10.4 +"1990-06-06",6.8 +"1990-06-07",6.0 +"1990-06-08",6.6 +"1990-06-09",7.8 +"1990-06-10",10.3 +"1990-06-11",7.2 +"1990-06-12",7.4 +"1990-06-13",11.4 +"1990-06-14",5.4 +"1990-06-15",4.4 +"1990-06-16",6.4 +"1990-06-17",9.3 +"1990-06-18",7.7 +"1990-06-19",8.1 +"1990-06-20",8.3 +"1990-06-21",9.1 +"1990-06-22",7.7 +"1990-06-23",10.6 +"1990-06-24",8.2 +"1990-06-25",7.9 +"1990-06-26",5.2 +"1990-06-27",5.9 +"1990-06-28",3.7 +"1990-06-29",5.6 +"1990-06-30",9.4 +"1990-07-01",7.4 +"1990-07-02",7.3 +"1990-07-03",7.7 +"1990-07-04",7.7 +"1990-07-05",9.3 +"1990-07-06",4.4 +"1990-07-07",5.7 +"1990-07-08",10.2 +"1990-07-09",10.2 +"1990-07-10",9.3 +"1990-07-11",5.4 +"1990-07-12",5.0 +"1990-07-13",7.6 +"1990-07-14",9.6 +"1990-07-15",10.4 +"1990-07-16",11.2 +"1990-07-17",9.1 +"1990-07-18",11.2 +"1990-07-19",6.8 +"1990-07-20",8.3 +"1990-07-21",9.7 +"1990-07-22",9.6 +"1990-07-23",9.8 +"1990-07-24",10.8 +"1990-07-25",9.2 +"1990-07-26",6.5 +"1990-07-27",8.1 +"1990-07-28",7.3 +"1990-07-29",7.9 +"1990-07-30",6.0 +"1990-07-31",5.0 +"1990-08-01",6.8 +"1990-08-02",9.8 +"1990-08-03",5.7 +"1990-08-04",8.6 +"1990-08-05",10.6 +"1990-08-06",7.8 +"1990-08-07",7.7 +"1990-08-08",8.6 +"1990-08-09",6.5 +"1990-08-10",6.9 +"1990-08-11",6.4 +"1990-08-12",8.5 +"1990-08-13",7.8 +"1990-08-14",9.3 +"1990-08-15",8.4 +"1990-08-16",7.8 +"1990-08-17",7.4 +"1990-08-18",7.7 +"1990-08-19",8.9 +"1990-08-20",9.7 +"1990-08-21",9.9 +"1990-08-22",6.1 +"1990-08-23",6.6 +"1990-08-24",7.6 +"1990-08-25",7.4 +"1990-08-26",8.0 +"1990-08-27",2.1 +"1990-08-28",5.9 +"1990-08-29",11.6 +"1990-08-30",8.6 +"1990-08-31",7.9 +"1990-09-01",6.0 +"1990-09-02",9.5 +"1990-09-03",8.6 +"1990-09-04",7.6 +"1990-09-05",10.4 +"1990-09-06",10.3 +"1990-09-07",7.5 +"1990-09-08",3.0 +"1990-09-09",5.3 +"1990-09-10",10.5 +"1990-09-11",14.6 +"1990-09-12",12.6 +"1990-09-13",9.8 +"1990-09-14",7.2 +"1990-09-15",10.1 +"1990-09-16",10.4 +"1990-09-17",3.7 +"1990-09-18",7.3 +"1990-09-19",11.6 +"1990-09-20",16.3 +"1990-09-21",9.6 +"1990-09-22",6.8 +"1990-09-23",5.2 +"1990-09-24",10.6 +"1990-09-25",16.3 +"1990-09-26",9.8 +"1990-09-27",4.6 +"1990-09-28",11.1 +"1990-09-29",8.7 +"1990-09-30",10.0 +"1990-10-01",11.3 +"1990-10-02",10.5 +"1990-10-03",9.9 +"1990-10-04",11.0 +"1990-10-05",14.0 +"1990-10-06",9.2 +"1990-10-07",9.8 +"1990-10-08",6.0 +"1990-10-09",9.8 +"1990-10-10",9.2 +"1990-10-11",11.8 +"1990-10-12",10.3 +"1990-10-13",7.5 +"1990-10-14",7.7 +"1990-10-15",15.8 +"1990-10-16",14.6 +"1990-10-17",10.5 +"1990-10-18",11.3 +"1990-10-19",10.9 +"1990-10-20",6.4 +"1990-10-21",10.9 +"1990-10-22",9.0 +"1990-10-23",10.9 +"1990-10-24",12.4 +"1990-10-25",11.6 +"1990-10-26",13.3 +"1990-10-27",14.4 +"1990-10-28",18.4 +"1990-10-29",13.6 +"1990-10-30",14.9 +"1990-10-31",14.8 +"1990-11-01",15.4 +"1990-11-02",11.8 +"1990-11-03",13.0 +"1990-11-04",11.1 +"1990-11-05",12.5 +"1990-11-06",18.3 +"1990-11-07",19.2 +"1990-11-08",15.4 +"1990-11-09",13.1 +"1990-11-10",11.5 +"1990-11-11",8.6 +"1990-11-12",12.6 +"1990-11-13",13.8 +"1990-11-14",14.6 +"1990-11-15",13.2 +"1990-11-16",12.3 +"1990-11-17",8.8 +"1990-11-18",10.7 +"1990-11-19",9.9 +"1990-11-20",8.3 +"1990-11-21",15.0 +"1990-11-22",12.2 +"1990-11-23",10.5 +"1990-11-24",11.1 +"1990-11-25",13.0 +"1990-11-26",12.9 +"1990-11-27",8.8 +"1990-11-28",14.7 +"1990-11-29",14.7 +"1990-11-30",12.7 +"1990-12-01",13.3 +"1990-12-02",13.2 +"1990-12-03",16.2 +"1990-12-04",17.3 +"1990-12-05",20.5 +"1990-12-06",20.2 +"1990-12-07",19.4 +"1990-12-08",15.5 +"1990-12-09",14.1 +"1990-12-10",11.0 +"1990-12-11",11.1 +"1990-12-12",14.0 +"1990-12-13",11.4 +"1990-12-14",12.5 +"1990-12-15",13.4 +"1990-12-16",13.6 +"1990-12-17",13.9 +"1990-12-18",17.2 +"1990-12-19",14.7 +"1990-12-20",15.4 +"1990-12-21",13.1 +"1990-12-22",13.2 +"1990-12-23",13.9 +"1990-12-24",10.0 +"1990-12-25",12.9 +"1990-12-26",14.6 +"1990-12-27",14.0 +"1990-12-28",13.6 +"1990-12-29",13.5 +"1990-12-30",15.7 +"1990-12-31",13.0 \ No newline at end of file diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/src.zip b/docs/tutorials/complete_applications/scenario_management_overview/src/src.zip new file mode 100644 index 000000000..d248208c7 Binary files /dev/null and b/docs/tutorials/complete_applications/scenario_management_overview/src/src.zip differ diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/step_01.py b/docs/tutorials/complete_applications/scenario_management_overview/src/step_01.py index 002b5141a..bfa8c4af3 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/step_01.py +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/step_01.py @@ -1,23 +1,36 @@ from taipy import Config import taipy as tp +import pandas as pd +import datetime as dt + + +data = pd.read_csv("https://raw.githubusercontent.com/Avaiga/taipy-getting-started-core/develop/src/daily-min-temperatures.csv") + # Normal function used by Taipy -def double(nb): - return nb * 2 +def predict(historical_temperature: pd.DataFrame, date_to_forecast: str) -> float: + print(f"Running baseline...") + historical_temperature['Date'] = pd.to_datetime(historical_temperature['Date']) + historical_same_day = historical_temperature.loc[ + (historical_temperature['Date'].dt.day == date_to_forecast.day) & + (historical_temperature['Date'].dt.month == date_to_forecast.month) + ] + return historical_same_day['Temp'].mean() # Configuration of Data Nodes -input_data_node_cfg = Config.configure_data_node("input", default_data=21) -output_data_node_cfg = Config.configure_data_node("output") +historical_temperature_cfg = Config.configure_data_node("historical_temperature") +date_to_forecast_cfg = Config.configure_data_node("date_to_forecast") +predictions_cfg = Config.configure_data_node("predictions") # Configuration of tasks -task_cfg = Config.configure_task("double", - double, - input_data_node_cfg, - output_data_node_cfg) +predictions_cfg = Config.configure_task("predict", + predict, + [historical_temperature_cfg, date_to_forecast_cfg], + predictions_cfg) -# Configuration of the pipeline and scenario -pipeline_cfg = Config.configure_pipeline("my_pipeline", [task_cfg]) -scenario_cfg = Config.configure_scenario("my_scenario", [pipeline_cfg]) +# Configuration of scenario +scenario_cfg = Config.configure_scenario(id="my_scenario", + task_configs=[predictions_cfg]) Config.export('config_01.toml') @@ -27,6 +40,26 @@ def double(nb): # Creation of the scenario and execution scenario = tp.create_scenario(scenario_cfg) + scenario.historical_temperature.write(data) + scenario.date_to_forecast.write(dt.datetime.now()) tp.submit(scenario) - print("Value at the end of task", scenario.output.read()) \ No newline at end of file + print("Value at the end of task", scenario.predictions.read()) + + def save(state): + state.scenario.historical_temperature.write(data) + state.scenario.date_to_forecast.write(state.date) + tp.gui.notify(state, "s", "Saved! Ready to submit") + + date = None + scenario_md = """ +<|{scenario}|scenario_selector|> +<|{date}|date|on_change=save|active={scenario}|> +<|{scenario}|scenario|> +<|{scenario}|scenario_dag|> + +<|Refresh|button|on_action={lambda s: s.assign("scenario", scenario)}|> +<|{scenario.predictions.read() if scenario else ''}|> +""" + + tp.Gui(scenario_md).run() \ No newline at end of file diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/step_01_toml.py b/docs/tutorials/complete_applications/scenario_management_overview/src/step_01_toml.py index 2bcf5e2f6..c778b6a0a 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/step_01_toml.py +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/step_01_toml.py @@ -1,9 +1,55 @@ from taipy import Config import taipy as tp +import pandas as pd +import datetime as dt + + +data = pd.read_csv("https://raw.githubusercontent.com/Avaiga/taipy-getting-started-core/develop/src/daily-min-temperatures.csv") + # Normal function used by Taipy -def double(nb): - return nb * 2 +def predict(historical_temperature: pd.DataFrame, date_to_forecast: str) -> float: + print(f"Running baseline...") + historical_temperature['Date'] = pd.to_datetime(historical_temperature['Date']) + historical_same_day = historical_temperature.loc[ + (historical_temperature['Date'].dt.day == date_to_forecast.day) & + (historical_temperature['Date'].dt.month == date_to_forecast.month) + ] + return historical_same_day['Temp'].mean() + +Config.load('config_01.toml') + +if __name__ == '__main__': + scenario_cfg = Config.scenarios['my_scenario'] + + # Run of the Core + tp.Core().run() + + # Creation of the scenario and execution + scenario = tp.create_scenario(scenario_cfg) + scenario.historical_temperature.write(data) + scenario.date_to_forecast.write(dt.datetime.now()) + tp.submit(scenario) + + print("Value at the end of task", scenario.predictions.read()) + + def save(state): + state.scenario.historical_temperature.write(data) + state.scenario.date_to_forecast.write(state.date) + tp.gui.notify(state, "s", "Saved! Ready to submit") + + date = None + scenario_md = """ +<|{scenario}|scenario_selector|> +<|{date}|date|on_change=save|active={scenario}|> +<|{scenario}|scenario|> +<|{scenario}|scenario_dag|> + +<|Refresh|button|on_action={lambda s: s.assign("scenario", scenario)}|> +<|{scenario.predictions.read() if scenario else ''}|> +""" + + tp.Gui(scenario_md).run() Config.load('config_01.toml') diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/step_02.py b/docs/tutorials/complete_applications/scenario_management_overview/src/step_02.py index e06863e55..aa9fed7fb 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/step_02.py +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/step_02.py @@ -13,9 +13,8 @@ def double(nb): input_data_node_cfg, output_data_node_cfg) -pipeline_cfg = Config.configure_pipeline("my_pipeline", [task_cfg]) - -scenario_cfg = Config.configure_scenario("my_scenario", [pipeline_cfg]) +scenario_cfg = Config.configure_scenario(id="my_scenario", + task_configs=[task_cfg]) Config.export('config_02.toml') @@ -38,3 +37,11 @@ def double(nb): print([s.name for s in tp.get_scenarios()]) scenario = tp.get(scenario.id) tp.delete(scenario.id) + + scenario = None + data_node = None + + tp.Gui("""<|{scenario}|scenario_selector|> + <|{scenario}|scenario|> + <|{scenario}|scenario_dag|> + <|{data_node}|data_node_selector|>""").run() diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/step_02_toml.py b/docs/tutorials/complete_applications/scenario_management_overview/src/step_02_toml.py index 2d3bf6358..8345c5711 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/step_02_toml.py +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/step_02_toml.py @@ -11,11 +11,9 @@ def double(nb): # my_scenario is the id of the scenario configured scenario_cfg = Config.scenarios['my_scenario'] - tp.Core().run() - scenario = tp.create_scenario(scenario_cfg, name="Scenario") tp.submit(scenario) - print("First submit", scenario.output.read()) + print("Output of First submit:", scenario.output.read()) print("Before write", scenario.input.read()) scenario.input.write(54) @@ -29,3 +27,13 @@ def double(nb): print([s.name for s in tp.get_scenarios()]) scenario = tp.get(scenario.id) tp.delete(scenario.id) + + scenario = None + data_node = None + + tp.Gui("""<|{scenario}|scenario_selector|> + <|{scenario}|scenario|> + <|{scenario}|scenario_dag|> + <|{data_node}|data_node_selector|>""").run() + + diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/step_03.py b/docs/tutorials/complete_applications/scenario_management_overview/src/step_03.py index c653a7c02..3364c9236 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/step_03.py +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/step_03.py @@ -15,7 +15,7 @@ def count_values(df): historical_data_cfg = Config.configure_csv_data_node(id="historical_data", - default_path="src/time_series.csv") + default_path="time_series.csv") month_values_cfg = Config.configure_data_node(id="month_data") nb_of_values_cfg = Config.configure_data_node(id="nb_of_values") @@ -30,23 +30,25 @@ def count_values(df): input=month_values_cfg, output=nb_of_values_cfg) -pipeline_cfg = Config.configure_pipeline(id="my_pipeline", - task_configs=[task_filter_cfg, - task_count_values_cfg]) scenario_cfg = Config.configure_scenario(id="my_scenario", - pipeline_configs=[pipeline_cfg]) + task_configs=[task_filter_cfg, + task_count_values_cfg]) Config.export('config_03.toml') if __name__ == '__main__': tp.Core().run() - scenario_1 = tp.create_scenario(scenario_cfg, creation_date=dt.datetime(2022,10,7), name="Scenario 2022/10/7") - scenario_1.submit() + scenario = tp.create_scenario(scenario_cfg, creation_date=dt.datetime(2022,10,7), name="Scenario 2022/10/7") + scenario.submit() - scenario_2 = tp.create_scenario(scenario_cfg, creation_date=dt.datetime(2022,10,7), name="Scenario 2022/10/7") - scenario_2.submit() + print("Nb of values of scenario:", scenario.nb_of_values.read()) + + data_node = None + + tp.Gui("""<|{scenario}|scenario_selector|> + <|{scenario}|scenario|> + <|{scenario}|scenario_dag|> + <|{data_node}|data_node_selector|>""").run() - print("Nb of values of scenario 1:", scenario_1.nb_of_values.read()) - print("Nb of values of scenario 2:", scenario_2.nb_of_values.read()) diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/step_03_toml.py b/docs/tutorials/complete_applications/scenario_management_overview/src/step_03_toml.py index 07b3deafe..68452db84 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/step_03_toml.py +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/step_03_toml.py @@ -22,9 +22,15 @@ def count_values(df): tp.Core().run() - scenario_1 = tp.create_scenario(scenario_cfg, creation_date=dt.datetime(2022,10,7), name="Scenario 2022/10/7") - scenario_1.submit() + scenario = tp.create_scenario(scenario_cfg, creation_date=dt.datetime(2022,10,7), name="Scenario 2022/10/7") + scenario.submit() - scenario_2 = tp.create_scenario(scenario_cfg, creation_date=dt.datetime(2022,10,7), name="Scenario 2022/10/7") - scenario_2.submit() + print("Nb of values of scenario:", scenario.nb_of_values.read()) + + data_node = None + + tp.Gui("""<|{scenario}|scenario_selector|> + <|{scenario}|scenario|> + <|{scenario}|scenario_dag|> + <|{data_node}|data_node_selector|>""").run() diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/step_04.py b/docs/tutorials/complete_applications/scenario_management_overview/src/step_04.py index 778e173a2..41d1a0844 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/step_04.py +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/step_04.py @@ -30,13 +30,10 @@ def count_values(df): input=month_values_cfg, output=nb_of_values_cfg) -pipeline_cfg = Config.configure_pipeline(id="my_pipeline", - task_configs=[task_filter_cfg, - task_count_values_cfg]) - scenario_cfg = Config.configure_scenario(id="my_scenario", - pipeline_configs=[pipeline_cfg], - frequency=Frequency.MONTHLY) + task_configs=[task_filter_cfg, + task_count_values_cfg], + frequency=Frequency.MONTHLY) Config.export('config_04.toml') @@ -50,8 +47,6 @@ def count_values(df): creation_date=dt.datetime(2022,10,5), name="Scenario 2022/10/5") - # scenario 1 and 2 belongs to the same cycle so I can define the cycle_metadata just once for - # scenario 1 and 2 because cycle_metadata has a Cycle scope scenario_1.month.write(10) scenario_2.month.write(10) @@ -62,12 +57,12 @@ def count_values(df): scenario_2.submit() print("Scenario 1 before", scenario_1.is_primary) - print("Scenario 2 before", scenario_1.is_primary) + print("Scenario 2 before", scenario_2.is_primary) tp.set_primary(scenario_2) print("Scenario 1 after", scenario_1.is_primary) - print("Scenario 2 after", scenario_1.is_primary) + print("Scenario 2 after", scenario_2.is_primary) scenario_3 = tp.create_scenario(scenario_cfg, creation_date=dt.datetime(2021,9,1), @@ -76,3 +71,11 @@ def count_values(df): scenario_3.submit() print("Is scenario 3 primary?", scenario_3.is_primary) + + scenario = None + data_node = None + + tp.Gui("""<|{scenario}|scenario_selector|> + <|{scenario}|scenario|> + <|{scenario}|scenario_dag|> + <|{data_node}|data_node_selector|>""").run() diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/step_04_toml.py b/docs/tutorials/complete_applications/scenario_management_overview/src/step_04_toml.py index d6200479f..2a517e53d 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/step_04_toml.py +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/step_04_toml.py @@ -19,7 +19,6 @@ def count_values(df): # my_scenario is the id of the scenario configured scenario_cfg = Config.scenarios['my_scenario'] - tp.Core().run() scenario_1 = tp.create_scenario(scenario_cfg, @@ -29,12 +28,9 @@ def count_values(df): creation_date=dt.datetime(2022,10,5), name="Scenario 2022/10/5") - # scenario 1 and 2 belongs to the same cycle so I can define the cycle_metadata just once for - # scenario 1 and 2 because cycle_metadata has a Cycle scope scenario_1.month.write(10) scenario_2.month.write(10) - print("Month Data Node of Scenario 1", scenario_1.month.read()) print("Month Data Node of Scenario 2", scenario_2.month.read()) @@ -43,12 +39,12 @@ def count_values(df): print("Scenario 1 before", scenario_1.is_primary) - print("Scenario 2 before", scenario_1.is_primary) + print("Scenario 2 before", scenario_2.is_primary) tp.set_primary(scenario_2) print("Scenario 1 after", scenario_1.is_primary) - print("Scenario 2 after", scenario_1.is_primary) + print("Scenario 2 after", scenario_2.is_primary) scenario_3 = tp.create_scenario(scenario_cfg, @@ -58,3 +54,12 @@ def count_values(df): scenario_3.submit() print("Is scenario 3 primary?", scenario_3.is_primary) + + data_node = None + scenario = None + + + tp.Gui("""<|{scenario}|scenario_selector|> + <|{scenario}|scenario|> + <|{scenario}|scenario_dag|> + <|{data_node}|data_node_selector|>""").run() diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/step_05.py b/docs/tutorials/complete_applications/scenario_management_overview/src/step_05.py index 622c58b9f..038cb6503 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/step_05.py +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/step_05.py @@ -14,8 +14,8 @@ def count_values(df): historical_data_cfg = Config.configure_csv_data_node(id="historical_data", - default_path="time_series.csv", - scope=Scope.GLOBAL) + default_path="time_series.csv", + scope=Scope.GLOBAL) month_cfg = Config.configure_data_node(id="month", scope=Scope.CYCLE) month_values_cfg = Config.configure_data_node(id="month_data", @@ -33,13 +33,12 @@ def count_values(df): input=month_values_cfg, output=nb_of_values_cfg) -pipeline_cfg = Config.configure_pipeline(id="my_pipeline", - task_configs=[task_filter_cfg, - task_count_values_cfg]) + scenario_cfg = Config.configure_scenario(id="my_scenario", - pipeline_configs=[pipeline_cfg], - frequency=Frequency.MONTHLY) + task_configs=[task_filter_cfg, + task_count_values_cfg], + frequency=Frequency.MONTHLY) Config.export('config_05.toml') @@ -67,6 +66,7 @@ def count_values(df): print("\nScenario 2: first submit") scenario_2.submit() print("Value", scenario_2.nb_of_values.read()) + print("Scenario 2: second submit") scenario_2.submit() print("Value", scenario_2.nb_of_values.read()) @@ -75,8 +75,3 @@ def count_values(df): scenario_3.month.write(9) scenario_3.submit() print("Value", scenario_3.nb_of_values.read()) - - print("Scenario 3: change in historical data") - scenario_3.historical_data.write(pd.read_csv('time_series_2.csv')) - scenario_3.submit() - print("Value", scenario_3.nb_of_values.read()) \ No newline at end of file diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/step_05_toml.py b/docs/tutorials/complete_applications/scenario_management_overview/src/step_05_toml.py index d40bee3f7..eeaa8cb65 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/step_05_toml.py +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/step_05_toml.py @@ -51,10 +51,4 @@ def count_values(df): print("\nScenario 3: submit") scenario_3.month.write(9) scenario_3.submit() - print("Value", scenario_3.nb_of_values.read()) - - - print("Scenario 3: change in historical data") - scenario_3.historical_data.write(pd.read_csv('time_series_2.csv')) - scenario_3.submit() print("Value", scenario_3.nb_of_values.read()) \ No newline at end of file diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/step_06.py b/docs/tutorials/complete_applications/scenario_management_overview/src/step_06.py index 4b9ab8aa4..ebb6a654b 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/step_06.py +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/step_06.py @@ -14,34 +14,31 @@ def count_values(df): historical_data_cfg = Config.configure_csv_data_node(id="historical_data", - default_path="time_series.csv", - scope=Scope.GLOBAL) + default_path="time_series.csv", + scope=Scope.GLOBAL) month_cfg = Config.configure_data_node(id="month", scope=Scope.CYCLE) month_values_cfg = Config.configure_data_node(id="month_data", - scope=Scope.CYCLE, - cacheable=True) + scope=Scope.CYCLE) -nb_of_values_cfg = Config.configure_data_node(id="nb_of_values", - cacheable=True) +nb_of_values_cfg = Config.configure_data_node(id="nb_of_values") task_filter_cfg = Config.configure_task(id="filter_by_month", function=filter_by_month, input=[historical_data_cfg, month_cfg], - output=month_values_cfg) + output=month_values_cfg, + skippable=True) task_count_values_cfg = Config.configure_task(id="count_values", function=count_values, input=month_values_cfg, - output=nb_of_values_cfg) - -pipeline_cfg = Config.configure_pipeline(id="my_pipeline", - task_configs=[task_filter_cfg, - task_count_values_cfg]) + output=nb_of_values_cfg, + skippable=True) scenario_cfg = Config.configure_scenario(id="my_scenario", - pipeline_configs=[pipeline_cfg], - frequency=Frequency.MONTHLY) + task_configs=[task_filter_cfg, + task_count_values_cfg], + frequency=Frequency.MONTHLY) Config.export('config_06.toml') @@ -59,37 +56,24 @@ def count_values(df): name="Scenario 2022/9/1") - - # scenario 1 and 2 belongs to the same cycle so - # defining the month for scenario 1 defines the month for the scenarios in the cycle + # scenario 1 and 2 belongs to the same cycle scenario_1.month.write(10) - print("Scenario 1: month", scenario_1.month.read()) - print("Scenario 2: month", scenario_2.month.read()) - print("Scenario 1: submit") scenario_1.submit() - print("Value", scenario_1.nb_of_values.read()) - # first task has already been executed by scenario 1 because scenario 2 shares the same data node for this task - print("Scenario 2: first submit") + # first task has already been executed by scenario 1 + # because scenario 2 shares the same data node for this task scenario_2.submit() - print("Value", scenario_2.nb_of_values.read()) # every task has already been executed so everything will be skipped - print("Scenario 2: second submit") scenario_2.submit() - print("Value", scenario_2.nb_of_values.read()) # scenario 3 has no connection to the other scenarios so everything will be executed - print("Scenario 3: submit") scenario_3.month.write(9) scenario_3.submit() - print("Value", scenario_3.nb_of_values.read()) - # changing an input data node will make the task be reexecuted print("Scenario 3: change in historical data") scenario_3.historical_data.write(pd.read_csv('time_series_2.csv')) scenario_3.submit() - print("Value", scenario_3.nb_of_values.read()) diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/step_06_toml.py b/docs/tutorials/complete_applications/scenario_management_overview/src/step_06_toml.py index 9b74cf487..f45dd7997 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/step_06_toml.py +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/step_06_toml.py @@ -32,36 +32,24 @@ def count_values(df): name="Scenario 2022/9/1") - - # scenario 1 and 2 belongs to the same cycle so - # defining the month for scenario 1 defines the month for the scenarios in the cycle + # scenario 1 and 2 belongs to the same cycle scenario_1.month.write(10) - print("Scenario 1: month", scenario_1.month.read()) - print("Scenario 2: month", scenario_2.month.read()) - print("Scenario 1: submit") scenario_1.submit() - print("Value", scenario_1.nb_of_values.read()) - # first task has already been executed by scenario 1 because scenario 2 shares the same data node for this task - print("Scenario 2: first submit") + # first task has already been executed by scenario 1 + # because scenario 2 shares the same data node for this task scenario_2.submit() - print("Value", scenario_2.nb_of_values.read()) # every task has already been executed so everything will be skipped - print("Scenario 2: second submit") scenario_2.submit() - print("Value", scenario_2.nb_of_values.read()) # scenario 3 has no connection to the other scenarios so everything will be executed - print("Scenario 3: submit") scenario_3.month.write(9) scenario_3.submit() - print("Value", scenario_3.nb_of_values.read()) # changing an input data node will make the task be reexecuted print("Scenario 3: change in historical data") scenario_3.historical_data.write(pd.read_csv('time_series_2.csv')) scenario_3.submit() - print("Value", scenario_3.nb_of_values.read()) diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/step_07.py b/docs/tutorials/complete_applications/scenario_management_overview/src/step_07.py index 77b29ac81..ba12ae80d 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/step_07.py +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/step_07.py @@ -22,26 +22,28 @@ def add(nb): # Configuration of tasks first_task_cfg = Config.configure_task("double", - double, - input_cfg, - intermediate_cfg) + double, + input_cfg, + intermediate_cfg) second_task_cfg = Config.configure_task("add", - add, - intermediate_cfg, - output_cfg) + add, + intermediate_cfg, + output_cfg) # Configuration of the pipeline and scenario -pipeline_cfg = Config.configure_pipeline("my_pipeline", [first_task_cfg, second_task_cfg]) -scenario_cfg = Config.configure_scenario("my_scenario", [pipeline_cfg]) +scenario_cfg = Config.configure_scenario(id="my_scenario", + task_configs=[first_task_cfg, + second_task_cfg]) Config.export("config_07.toml") if __name__=="__main__": tp.Core().run() scenario_1 = tp.create_scenario(scenario_cfg) + scenario_2 = tp.create_scenario(scenario_cfg) scenario_1.submit() - scenario_1.submit() + scenario_2.submit() scenario_1 = tp.create_scenario(scenario_cfg) scenario_1.submit(wait=True) diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/step_07_toml.py b/docs/tutorials/complete_applications/scenario_management_overview/src/step_07_toml.py index d0cb912bc..d2c649097 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/step_07_toml.py +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/step_07_toml.py @@ -1,40 +1,31 @@ -from taipy.core.config import Config, Scope, Frequency +from taipy.core.config import Config import taipy as tp import datetime as dt import pandas as pd import time +# Normal function used by Taipy +def double(nb): + return nb * 2 -def filter_by_month(df, month): - df['Date'] = pd.to_datetime(df['Date']) - df = df[df['Date'].dt.month == month] - return df - -def count_values(df): - print("Wait 10 seconds") +def add(nb): + print("Wait 10 seconds in add function") time.sleep(10) - return len(df) + return nb + 10 Config.load('config_07.toml') Config.configure_job_executions(mode="standalone", max_nb_of_workers=2) + if __name__=="__main__": - # my_scenario is the id of the scenario configured scenario_cfg = Config.scenarios['my_scenario'] - tp.Core().run() - scenario_1 = tp.create_scenario(scenario_cfg, creation_date=dt.datetime(2022,10,7), name="Scenario 2022/10/7") - scenario_1.month.write(10) - scenario_1.submit() + scenario_1 = tp.create_scenario(scenario_cfg) + scenario_2 = tp.create_scenario(scenario_cfg) scenario_1.submit() + scenario_2.submit() - time.sleep(30) - - -if __name__=="__main__": - tp.Core().run() - scenario_1 = tp.create_scenario(scenario_cfg, creation_date=dt.datetime(2022,10,7), name="Scenario 2022/10/7") - scenario_1.month.write(10) + scenario_1 = tp.create_scenario(scenario_cfg) scenario_1.submit(wait=True) - scenario_1.submit(wait=True, timeout=5) \ No newline at end of file + scenario_1.submit(wait=True, timeout=5) diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/step_08.py b/docs/tutorials/complete_applications/scenario_management_overview/src/step_08.py index e8319eeff..60d462fba 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/step_08.py +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/step_08.py @@ -1,8 +1,7 @@ -from taipy.core.config import Config, Frequency +from taipy.core.config import Config import taipy as tp - # Normal function used by Taipy def double(nb): return nb * 2 @@ -27,15 +26,14 @@ def add(nb): intermediate_cfg, output_cfg) -# Configuration of the pipeline and scenario -pipeline_cfg = Config.configure_pipeline("my_pipeline", [first_task_cfg, second_task_cfg]) def compare_function(*data_node_results): - compare_result= {} + # example of function + compare_result = {} current_res_i = 0 for current_res in data_node_results: - compare_result[current_res_i]={} + compare_result[current_res_i] = {} next_res_i = 0 for next_res in data_node_results: print(f"comparing result {current_res_i} with result {next_res_i}") @@ -46,10 +44,9 @@ def compare_function(*data_node_results): scenario_cfg = Config.configure_scenario(id="multiply_scenario", - name="my_scenario", - pipeline_configs=[pipeline_cfg], - comparators={output_cfg.id: compare_function}, - frequency=Frequency.MONTHLY) + name="my_scenario", + task_configs=[first_task_cfg, second_task_cfg], + comparators={output_cfg.id: compare_function}) Config.export("config_08.toml") diff --git a/docs/tutorials/complete_applications/scenario_management_overview/src/step_09.py b/docs/tutorials/complete_applications/scenario_management_overview/src/step_09.py index 6f387554a..8fa68e9f2 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/src/step_09.py +++ b/docs/tutorials/complete_applications/scenario_management_overview/src/step_09.py @@ -1,6 +1,6 @@ -from taipy.core.config import Config, Frequency +from taipy.config import Config +from taipy.core import Status import taipy as tp -import datetime as dt import time @@ -19,6 +19,7 @@ def add(nb): intermediate_cfg = Config.configure_data_node("intermediate") output_cfg = Config.configure_data_node("output") + # Configuration of tasks first_task_cfg = Config.configure_task("double", double, @@ -30,10 +31,6 @@ def add(nb): intermediate_cfg, output_cfg) -# Configuration of the pipeline and scenario -pipeline_cfg = Config.configure_pipeline("my_pipeline", [first_task_cfg, second_task_cfg]) - - def callback_scenario_state(scenario, job): """All the scenarios are subscribed to the callback_scenario_state function. It means whenever a job is done, it is called. @@ -44,14 +41,15 @@ def callback_scenario_state(scenario, job): job (_type_): the job that has its status changed """ print(scenario.name) - if job.status.value == 7: + if job.status == Status.COMPLETED: for data_node in job.task.output.values(): print(data_node.read()) - +# Configuration of scenario scenario_cfg = Config.configure_scenario(id="my_scenario", - name="my_scenario", - pipeline_configs=[pipeline_cfg]) + task_configs=[first_task_cfg, + second_task_cfg], + name="my_scenario") Config.export("config_09.toml") diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_01/ReadMe.md b/docs/tutorials/complete_applications/scenario_management_overview/step_01/ReadMe.md deleted file mode 100644 index d01494759..000000000 --- a/docs/tutorials/complete_applications/scenario_management_overview/step_01/ReadMe.md +++ /dev/null @@ -1,160 +0,0 @@ -> You can download the code of this step [here](../src/step_01.py) or all the steps [here](https://github.com/Avaiga/taipy-getting-started-core/tree/develop/src). - -# Step 1: Configuration and execution - -Before looking at some code examples, let’s define some basic terms Taipy Core uses. Taipy Core revolves around four major concepts. - -## Four fundamental concepts in Taipy Core: -- [**Data Nodes**](https://docs.taipy.io/en/latest/manuals/core/concepts/data-node/): are the translation of _variables_ in Taipy. Data Nodes don't contain the data but know how to retrieve it. They can refer to any data: any Python object (string, int, list, dict, model, data frame, etc.), a Pickle file, a CSV file, a SQL database, etc. They know how to read and write data. You can even write your own custom Data Node to access a particular data format. - -- [**Tasks**](https://docs.taipy.io/en/latest/manuals/core/concepts/task/): are the translation of _functions_ in Taipy. - -- [**Pipelines**](https://docs.taipy.io/en/latest/manuals/core/concepts/pipeline/): are a list of tasks executed with intelligent scheduling created automatically by Taipy. They usually represent a sequence of Tasks/functions ranging from data processing steps to simple baseline Algorithms all the way to more sophisticated pipelines: Machine-Learning, Mathematical models, Simulation, etc. - -- [**Scenarios**](https://docs.taipy.io/en/latest/manuals/core/concepts/scenario/): End-Users often require modifying various parameters to reflect different business situations. Taipy Scenarios provide the framework to "run"/"execute" pipelines under different conditions/variations (i.e., data/parameters modified by the end-user) - - -## What is a configuration? - -A [**configuration**](https://docs.taipy.io/en/latest/manuals/core/config/) is a structure to define scenarios and pipelines. It represents our Direct Acyclic Graph(s); it models the data sources, parameters, and tasks. Once defined, a configuration acts like a superclass; it is used to generate different instances of scenarios. - - -Let's create our first configuration. For this, we have two alternatives: - -- Using Taipy Studio - -- Or directly coding in Python. - -Once the scenario configuration is defined, we can create instances, aka *'entities'* of scenarios, that can be submitted for execution. Entities are made from all configuration objects: scenario config, pipeline config, tasks, and data node configs. We will refer to them as _scenario entities_, _pipeline entities_, _task entities_, and _Data Node entities_. Since this is very much like the mechanism of class and instances present in object programming, we will use the word entity and instance interchangeably. - -Let’s consider the simplest possible pipeline: a single function taking as input an integer and generating an integer output (doubling the input number). See below: - - -```python -from taipy import Config -import taipy as tp - -# Normal function used by Taipy -def double(nb): - return nb * 2 -``` - -![](config_01.svg){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } - -- Two Data Nodes are being configured ('input' and 'output'). The 'input' Data Node has a _default_data_ set at 21. They will be stored as Pickle files (default storage format) and unique to each scenario entity/instance (this is the concept of scope which is covered later’). To clarify, the names given to the Data Nodes are arbitrary. The task links the two Data Nodes through the Python function double. - -- The pipeline contains this task, and the scenario includes this single pipeline. - -!!! example "Configuration" - - === "Taipy Studio" - - **Alternative 1:** Configuration using Taipy Studio - - By watching the animation below, you can feel how this configuration gets created using Taipy Studio. Once created, the configuration can be saved as a TOML file (see below) - - - ![](config_01.gif){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } - - - **Note**: Remember to save the file after each change. - - - Create a new file: 'config_01.toml' - - - Open Taipy Studio view - - - Right-click on the right configuration and choose 'Taipy: Show View' - - - Add your first Data Node by clicking the button on the right corner of the window - - - Create a name for it and change its details in the 'Details' section of Taipy Studio - - - name: input - - - Details: default_data=21, storage_type=pickle - - - Do the same for the output - - - name: output - - - Details: storage_type=pickle - - - Add a task and choose a function to associate with `.` - - - name: double - - - Details: function=`__main__.double` - - - Link the Data Nodes and the task - - - Add a pipeline and link it to the task - - - Add a scenario and link to the pipeline - - To use this configuration in our code (`main.py` for example), we must load it and retrieve the `scenario_cfg`. This `scenario_cfg` is the basis to instantiate our scenarios. - - ```python - Config.load('config_01.toml') - - # my_scenario is the id of the scenario configured - scenario_cfg = Config.scenarios['my_scenario'] - ``` - - === "Python configuration" - - **Alternative 2:** Configuration using Python Code - - Here is the code to configure a simple scenario. - - ```python - # Configuration of Data Nodes - input_data_node_cfg = Config.configure_data_node("input", default_data=21) - output_data_node_cfg = Config.configure_data_node("output") - - # Configuration of tasks - task_cfg = Config.configure_task("double", - double, - input_data_node_cfg, - output_data_node_cfg) - - # Configuration of the pipeline and scenario - pipeline_cfg = Config.configure_pipeline("my_pipeline", [task_cfg]) - scenario_cfg = Config.configure_scenario("my_scenario", [pipeline_cfg]) - ``` - -The code below presents how you can create scenarios and submit them. - -First of all, Taipy Core has to be launched(`tp.Core().run()`). It will create a service that acts as a job scheduler. - -Creating a scenario/pipeline (`tp.create_scenario()` / `tp.create_pipeline()`) will create all its related entities (_tasks_, _Data Nodes_, etc). These entities are being created thanks to the previous configuration. Still, no scenario has been run yet. `tp.submit()` is the line of code that will run all the scenario-related pipelines and tasks. Note that a pipeline or a task can also be submitted directly (`tp.submit()`, `tp.submit()`). - -```python -# Run of the Core -tp.Core().run() - -# Creation of the scenario and execution -scenario = tp.create_scenario(scenario_cfg) -tp.submit(scenario) - -print("Value at the end of task", scenario.output.read()) -``` - -Results: - -``` -[2022-12-22 16:20:02,740][Taipy][INFO] job JOB_double_699613f8-7ff4-471b-b36c-d59fb6688905 is completed. -Value at the end of task 42 -``` - -'/.data' is the default storage folder for Taipy Core. It contains data, scenarios, pipelines, jobs, and tasks. These entities can be persisted between two runs depending on how the code is run. - -## Ways of executing the code: Versioning - -Taipy Core provides a [versioning system](https://docs.taipy.io/en/latest/manuals/core/versioning/) to keep track of the changes that a configuration will experience over time: new data sources, new parameters, new versions of your Machine Learning engine, etc. `python main.py -h` opens a helper to understand the versioning options. Here are the principal ways to run the code with versioning: - -- _Development_: is the default way of executing the code. When running a Taipy Core application in development mode, Taipy can’t access all entities created from a previous Development run. Launching your Taipy code as `python main.py` executes it in Development mode. - -- _Experiment_: all Taipy Core entities from the previous run are kept, but each new run will ignore them. An identifier is attached to each run. -`python main.py --experiment` will execute the code in Experiment mode. The user can then re-execute a previous run (by selecting a previously used identifier). This version number is as follows: `python main.py --experiment 1`. - -- _Production_: When running a Taipy Core application in production mode, Taipy can access all entities attached to the current or another production version. It corresponds to the case where the application is stable and running in a production environment. The user can decide the identifier to use. `python main.py --production` will execute the code in Experiment mode, or `python main.py --production 1` to run it with a specific version. diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_01/config_01.gif b/docs/tutorials/complete_applications/scenario_management_overview/step_01/config_01.gif index 36a7a338e..69f51dd28 100644 Binary files a/docs/tutorials/complete_applications/scenario_management_overview/step_01/config_01.gif and b/docs/tutorials/complete_applications/scenario_management_overview/step_01/config_01.gif differ diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_01/config_01.mp4 b/docs/tutorials/complete_applications/scenario_management_overview/step_01/config_01.mp4 new file mode 100644 index 000000000..b07814006 Binary files /dev/null and b/docs/tutorials/complete_applications/scenario_management_overview/step_01/config_01.mp4 differ diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_01/config_01.svg b/docs/tutorials/complete_applications/scenario_management_overview/step_01/config_01.svg index 10e5ac1ac..936c7d80c 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/step_01/config_01.svg +++ b/docs/tutorials/complete_applications/scenario_management_overview/step_01/config_01.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_01/demo.gif b/docs/tutorials/complete_applications/scenario_management_overview/step_01/demo.gif new file mode 100644 index 000000000..5cab871a7 Binary files /dev/null and b/docs/tutorials/complete_applications/scenario_management_overview/step_01/demo.gif differ diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_01/step_01.md b/docs/tutorials/complete_applications/scenario_management_overview/step_01/step_01.md new file mode 100644 index 000000000..db1b6cffb --- /dev/null +++ b/docs/tutorials/complete_applications/scenario_management_overview/step_01/step_01.md @@ -0,0 +1,237 @@ +> You can download the code for +Step 1 +or all the steps here. + +# Configuration and execution + +*Time to complete: 15 minutes; Level: Beginner* + +Before looking at some code examples, let’s define some basic terms Taipy Core uses. Taipy Core revolves around three major concepts. + +## Three fundamental concepts in Taipy: +- [**Data Node**](../../../../manuals/core/concepts/data-node.md): is the translation of a _variable_ in Taipy. Data Nodes know how to retrieve any type of data. They can refer to: any Python object (string, int, list, dict, model, data frame, etc.), a Pickle file, a CSV file, a SQL database, etc. + +- [**Task**](../../../../manuals/core/concepts/task.md): is the expression of a _function_ in Taipy. + +- [**Scenarios**](../../../../manuals/core/concepts/scenario.md): is an instance of your pipelines. End-users often require modifying various parameters to reflect different business situations. Taipy Scenarios provide the framework to "run"/"execute" pipelines under different conditions/variations (i.e., data/parameters modified by the end-user). + + +## What is a configuration? + +A [**configuration**](../../../../manuals/core/config/index.md) is a structure to define scenarios. It represents our Direct Acyclic Graph(s); it models the data sources, parameters, and tasks. Once defined, a configuration acts like a superclass; it is used to generate different instances of scenarios. + + +Let's create our first configuration. For this, we have two alternatives: + +- Using Taipy Studio + +- Or directly coding in Python. + +Let’s consider the simplest possible pipeline: a single function taking two inputs: a dataset and a date to forecast and generate a prediction for the chosen date. See below: + + +```python +from taipy import Config +import taipy as tp +import pandas as pd + +def predict(historical_temperature: pd.DataFrame, date_to_forecast: str) -> float: + print(f"Running baseline...") + historical_temperature['Date'] = pd.to_datetime(historical_temperature['Date']) + historical_same_day = historical_temperature.loc[ + (historical_temperature['Date'].dt.day == date_to_forecast.day) & + (historical_temperature['Date'].dt.month == date_to_forecast.month) + ] + return historical_same_day['Temp'].mean() +``` + +![](config_01.svg){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } + +- Three Data Nodes are being configured ('historical_temperature', 'date_to_forecast' and 'predictions'). All the input Data Nodes will be written before the submission of the pipeline. The task links the three Data Nodes through the Python function *predict*. The submission write the input ('predictions'). + + +!!! example "Configuration" + + === "Taipy Studio" + + **Alternative 1:** Configuration using Taipy Studio + + By watching the animation below, you can see how this configuration gets created using Taipy Studio. In fact, Taipy Studio is an editor of a TOML file specific to Taipy. It lets you edit and view a TOML file that will be used in our code. + + + + + To use this configuration in our code (`main.py` for example), we must load it and retrieve the `scenario_cfg`. This `scenario_cfg` is the basis to instantiate our scenarios. + + ```python + Config.load('config_01.toml') + + # my_scenario is the id of the scenario configured + scenario_cfg = Config.scenarios['my_scenario'] + ``` + + === "Python configuration" + + **Alternative 2:** Configuration using Python Code + + Here is the code to configure a simple scenario. + + ```python + # Configuration of Data Nodes + historical_temperature_cfg = Config.configure_data_node("historical_temperature") + date_to_forecast_cfg = Config.configure_data_node("date_to_forecast") + predictions_cfg = Config.configure_data_node("predictions") + + # Configuration of tasks + predictions_cfg = Config.configure_task(id="predict", + function=predict, + input=[historical_temperature_cfg, date_to_forecast_cfg], + output=predictions_cfg) + + # Configuration of scenario + scenario_cfg = Config.configure_scenario(id="my_scenario", + task_configs=[predictions_cfg]) + ``` + +The configuration is done! Let's use it to create scenarios and submit them. + +First, launch Taipy Core in your code (`tp.Core().run()`). Then, you can play with Taipy: + +- create scenarios, + +- submit them, + +- write your data nodes, + +- read your data nodes. + +Creating a scenario (`tp.create_scenario()`) creates all its related entities (_tasks_, _Data Nodes_, etc). These entities are being created thanks to the previous configuration. Still, no scenario has been run yet. `tp.submit()` is the line of code that runs all the scenario-related pipelines and tasks. + +```python +# Run of the Core +tp.Core().run() + +# Creation of the scenario and execution +scenario = tp.create_scenario(scenario_cfg) +scenario.historical_temperature.write(data) +scenario.date_to_forecast.write(dt.datetime.now()) +tp.submit(scenario) + +print("Value at the end of task", scenario.output.read()) +``` + +Results: + +``` +[2022-12-22 16:20:02,740][Taipy][INFO] job JOB_predict_... is completed. +Value at the end of task 23.45 +``` + +## Gui-Core visual elements + +Add these few lines to the code of your script. This creates a web application to: + +- select scenarios you created, + +- create new ones, + +- submit them, + +- see the configuration used by the scenario. + +```python +def save(state): + # write values of Data Node to submit scenario + state.scenario.historical_temperature.write(data) + state.scenario.date_to_forecast.write(state.date) + tp.gui.notify(state, "s", "Saved! Ready to submit") + +date = None +scenario_md = """ +<|{scenario}|scenario_selector|> +<|{date}|date|on_change=save|active={scenario}|> +<|{scenario}|scenario|> +<|{scenario}|scenario_dag|> + +<|Refresh|button|on_action={lambda s: s.assign("scenario", scenario)}|> +<|{scenario.predictions.read() if scenario else ''}|> +""" + +tp.Gui(scenario_md).run() +``` + +The [Gui-Core visual elements](../../../../manuals/gui/corelements/data_node.md_template) let you add visual elements for the Taipy backend. This way, creating a web application corresponding to your backend has never been simpler. + +![](demo.gif){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } + +## Entire code + +```python +from taipy import Config +import taipy as tp +import pandas as pd + + +data = pd.read_csv("https://raw.githubusercontent.com/Avaiga/taipy-getting-started-core/develop/src/daily-min-temperatures.csv") + + + +# Normal function used by Taipy +def predict(historical_temperature: pd.DataFrame, date_to_forecast: str) -> float: + print(f"Running baseline...") + historical_temperature['Date'] = pd.to_datetime(historical_temperature['Date']) + historical_same_day = historical_temperature.loc[ + (historical_temperature['Date'].dt.day == date_to_forecast.day) & + (historical_temperature['Date'].dt.month == date_to_forecast.month) + ] + return historical_same_day['Temp'].mean() + +# Configuration of Data Nodes +historical_temperature_cfg = Config.configure_data_node("historical_temperature") +date_to_forecast_cfg = Config.configure_data_node("date_to_forecast") +predictions_cfg = Config.configure_data_node("predictions") + +# Configuration of tasks +predictions_cfg = Config.configure_task("predict", + predict, + [historical_temperature_cfg, date_to_forecast_cfg], + predictions_cfg) + +# Configuration of scenario +scenario_cfg = Config.configure_scenario(id="my_scenario", + task_configs=[predictions_cfg]) + + +if __name__ == '__main__': + # Run of the Core + tp.Core().run() + + # Creation of the scenario and execution + scenario = tp.create_scenario(scenario_cfg) + scenario.historical_temperature.write(data) + scenario.date_to_forecast.write(dt.datetime.now()) + tp.submit(scenario) + + print("Value at the end of task", scenario.predictions.read()) + + def save(state): + state.scenario.historical_temperature.write(data) + state.scenario.date_to_forecast.write(state.date) + tp.gui.notify(state, "s", "Saved! Ready to submit") + + date = None + scenario_md = """ +<|{scenario}|scenario_selector|> +<|{date}|date|on_change=save|active={scenario}|> +<|{scenario}|scenario|> +<|{scenario}|scenario_dag|> + +<|Refresh|button|on_action={lambda s: s.assign("scenario", scenario)}|> +<|{scenario.predictions.read() if scenario else ''}|> +""" + + tp.Gui(scenario_md).run() +``` + \ No newline at end of file diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_02/ReadMe.md b/docs/tutorials/complete_applications/scenario_management_overview/step_02/ReadMe.md deleted file mode 100644 index 38b1ad4af..000000000 --- a/docs/tutorials/complete_applications/scenario_management_overview/step_02/ReadMe.md +++ /dev/null @@ -1,96 +0,0 @@ -> You can download the code of this step [here](../src/step_02.py) or all the steps [here](https://github.com/Avaiga/taipy-getting-started-core/tree/develop/src). - -# Step 2: Basic functions - -Let's discuss some of the essential functions that come along with Taipy. - -- [`.write()`](https://docs.taipy.io/en/latest/manuals/core/entities/data-node-mgt/#read-write-a-data-node): this instruction changes the data of a Data Node. It also changes the _last_edit_date_ of the Data Node, influencing whether a task can be skipped. - -- [`tp.get_scenarios()`](https://docs.taipy.io/en/latest/manuals/core/entities/scenario-cycle-mgt/#get-all-scenarios): this function returns the list of all the scenarios - -- [`tp.get()`](https://docs.taipy.io/en/latest/manuals/core/entities/data-node-mgt/#get-data-node): this function returns an entity based on the id of the entity - -- [`tp.delete()`](https://docs.taipy.io/en/latest/manuals/core/entities/scenario-cycle-mgt/#delete-a-scenario): this function deletes the entity and nested elements based on the id of the entity - -## Utility of having scenarios - -Taipy lets the user create multiple instances of the same configuration. Data can differ between different scenario instances. It is essential to detect/understand the difference in data between scenario instances: e.g., comparing the output/results of different instances... Such differences in behavior between different scenarios entities (from the same scenario configuration) can be due to the following: - -- Changing data from input data nodes, - -- Randomness in a task (random algorithm), - -- Different values from parameters set by the end-user, etc. - -The developer can directly change the data nodes entities with the _write_ function (see below). - -![](config_02.svg){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } - -```python -scenario = tp.create_scenario(scenario_cfg, name="Scenario") -tp.submit(scenario) -print("Output of First submit:", scenario.output.read()) -``` - -Results: - -``` -[2022-12-22 16:20:02,874][Taipy][INFO] job JOB_double_a5ecfa4d-1963-4776-8f68-0859d22970b9 is completed. -Output of First submit: 42 -``` - -## _write_ function - -Data of a Data Node can be changed using _write_. The syntax is `...write(value)`. If the scenario contains a single pipeline, we can write `..write(value)`. - - -```python -print("Before write", scenario.input.read()) -scenario.input.write(54) -print("After write",scenario.input.read()) -``` - -Results: -``` -Before write 21 -After write 54 -``` - -The submission of the scenario will update the output values. - - -```python -tp.submit(scenario) -print("Second submit",scenario.output.read()) -``` -Results: -``` -[2022-12-22 16:20:03,011][Taipy][INFO] job JOB_double_7eee213f-062c-4d67-b0f8-4b54c04e45e7 is completed. -Second submit 108 -``` - -## Other useful functions - -- `tp.get_scenarios` accesses all the scenarios by returning a list. - -```python -print([s.name for s in tp.get_scenarios()]) -``` - -Results: -``` -["Scenario"] -``` - -- Get an entity from its id: - -```python -scenario = tp.get(scenario.id) -``` - -- Delete an entity through its id. For example, to delete a scenario: - -```python -tp.delete(scenario.id) -``` - diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_02/step_02.md b/docs/tutorials/complete_applications/scenario_management_overview/step_02/step_02.md new file mode 100644 index 000000000..4c892a8ca --- /dev/null +++ b/docs/tutorials/complete_applications/scenario_management_overview/step_02/step_02.md @@ -0,0 +1,158 @@ +> You can download the code for +Step 2 +or all the steps here. + +# Basic functions + +*Time to complete: 15 minutes; Level: Beginner* + +Let's discuss some of the essential functions that come along with Taipy. + +- [`.write()`](../../../../manuals/core/entities/data-node-mgt.md/#read-write-a-data-node): this instruction changes the data of a Data Node. + +- [`tp.get_scenarios()`](../../../../manuals/core/entities/scenario-cycle-mgt.md/#get-all-scenarios): this function returns the list of all the scenarios. + +- [`tp.get()`](../../../../manuals/core/entities/data-node-mgt.md/#get-data-node): this function returns an entity based on the id of the entity. + +- [`tp.delete()`](../../../../manuals/core/entities/scenario-cycle-mgt.md/#delete-a-scenario): this function deletes the entity and nested elements based on the id of the entity. + +## Utility of having scenarios + +Taipy lets the user create multiple instances of the same configuration. Data can differ between different scenario instances. It is essential to understand the difference in data between scenario instances. Such differences in scenarios can be due to the following: + +- Changing data from input data nodes, + +- Randomness in a task (random algorithm), + +- Different values from parameters set by the end-user, etc. + +The developer can directly change the data nodes entities with the _write_ function (see below). + +![](config_02.svg){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } + +```python +scenario = tp.create_scenario(scenario_cfg, name="Scenario") +tp.submit(scenario) +print("Output of First submit:", scenario.output.read()) +``` + +Results: + +``` +[2022-12-22 16:20:02,874][Taipy][INFO] job JOB_double_a5ecfa4d-1963-4776-8f68-0859d22970b9 is completed. +Output of First submit: 42 +``` + +## _write_ function + +Data of a Data Node can be changed using _write_. The syntax is `..write(value)`. + + +```python +print("Before write", scenario.input.read()) +scenario.input.write(54) +print("After write",scenario.input.read()) +``` + +Results: +``` +Before write 21 +After write 54 +``` + +The submission of the scenario updates the output values. + + +```python +tp.submit(scenario) +print("Second submit",scenario.output.read()) +``` + +Results: +``` +[2022-12-22 16:20:03,011][Taipy][INFO] job JOB_double_7eee213f-062c-4d67-b0f8-4b54c04e45e7 is completed. +Second submit 108 +``` + +## Other useful functions + +- `tp.get_scenarios` accesses all the scenarios by returning a list. + +```python +print([s.name for s in tp.get_scenarios()]) +``` + +Results: +``` +["Scenario"] +``` + +- Get an entity from its id: + +```python +scenario = tp.get(scenario.id) +``` + +- Delete an entity through its id. For example, to delete a scenario: + +```python +tp.delete(scenario.id) +``` + +## Ways of executing the code: Versioning + +Taipy provides a [versioning system](../../../../manuals/core/versioning/index.md) to keep track of the changes that a configuration experiences over time: new data sources, new parameters, new versions of your Machine Learning engine, etc. `python main.py -h` opens a helper to understand the versioning options at your disposal. + +# Entire code + +```python +from taipy import Config +import taipy as tp + + +def double(nb): + return nb * 2 + +# Configuration in Python +input_data_node_cfg = Config.configure_data_node("input", default_data=21) +output_data_node_cfg = Config.configure_data_node("output") + +task_cfg = Config.configure_task("double", + double, + input_data_node_cfg, + output_data_node_cfg) + +scenario_cfg = Config.configure_scenario(id="my_scenario", + task_configs=[task_cfg]) + + +if __name__ == '__main__': + tp.Core().run() + + scenario = tp.create_scenario(scenario_cfg, name="Scenario") + tp.submit(scenario) + print("Output of First submit:", scenario.output.read()) + + print("Before write", scenario.input.read()) + scenario.input.write(54) + print("After write",scenario.input.read()) + + + tp.submit(scenario) + print("Second submit",scenario.output.read()) + + # Basic functions of Taipy Core + print([s.name for s in tp.get_scenarios()]) + scenario = tp.get(scenario.id) + tp.delete(scenario.id) + + scenario = None + data_node = None + + tp.Gui("""<|{scenario}|scenario_selector|> + <|{scenario}|scenario|> + <|{scenario}|scenario_dag|> + <|{data_node}|data_node_selector|>""").run() +``` + + diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_03/Data-Sources.jpg b/docs/tutorials/complete_applications/scenario_management_overview/step_03/Data-Sources.jpg new file mode 100644 index 000000000..d42ef770c Binary files /dev/null and b/docs/tutorials/complete_applications/scenario_management_overview/step_03/Data-Sources.jpg differ diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_03/ReadMe.md b/docs/tutorials/complete_applications/scenario_management_overview/step_03/ReadMe.md deleted file mode 100644 index 89f8b6acb..000000000 --- a/docs/tutorials/complete_applications/scenario_management_overview/step_03/ReadMe.md +++ /dev/null @@ -1,129 +0,0 @@ -> You can download the code of this step [here](../src/step_04.py) or all the steps [here](https://github.com/Avaiga/taipy-getting-started-core/tree/develop/src). - -# Step 3: Data Node types - -- *[Pickle](https://docs.taipy.io/en/latest/manuals/core/config/data-node-config/#pickle)* (default): Taipy can read and write any data that can be serializable. - -- *[CSV](https://docs.taipy.io/en/latest/manuals/core/config/data-node-config/#csv)*: Taipy can read and write any data frame as a CSV. - -- *[JSON](https://docs.taipy.io/en/latest/manuals/core/config/data-node-config/#json)*: Taipy can read and write any JSONable data as a JSON file. - -- *[SQL](https://docs.taipy.io/en/latest/manuals/core/config/data-node-config/#sql)*: Taipy can read and write from/to a SQL table or a SQL database. - -- *[Mongo](https://docs.taipy.io/en/latest/manuals/core/config/data-node-config/#mongo-collection)*: Taipy can read and write from/to a Mongo Collection - -- *[Parquet](https://docs.taipy.io/en/latest/manuals/core/config/data-node-config/#parquet)*: Taipy can read and write data frames from/to a Parquet format - -- *[Generic](https://docs.taipy.io/en/latest/manuals/core/config/data-node-config/#generic)*: Taipy provides a generic Data Node that can read and store any data based on a custom _reading_ and _writing_ function created by the user. - -This section will use the simple DAG/execution configuration described below. The configuration consists of the following: - -1. Three Data Nodes: -2. -- _historical data_: This is a CSV-type Data Node. It reads from a CSV file into the initial data frame. You can find the dataset used in the Getting Started [here](https://github.com/Avaiga/taipy-getting-started-core/blob/develop/src/time_series.csv). - -- _month_data_: This is a pickle Data Node. It stores in a pickle format the data frame generated by the task '_filter_' (obtained after some filtering of the initial data frame). - -- _nb_of_values_: This is also a pickle Data Node. It stores an integer generated by the '_count_values_' task. - -3. Two tasks linking these Data Nodes: - -- _filter_: filters on the current month of the data frame - -- _count_values_: calculates the number of elements in this month - -5. One single pipeline in this scenario configuration grouping these two tasks. - - -![](config_03.svg){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } - -```python -def filter_current(df): - current_month = dt.datetime.now().month - df['Date'] = pd.to_datetime(df['Date']) - df = df[df['Date'].dt.month == current_month] - return df - -def count_values(df): - return len(df) -``` - -!!! example "Configuration" - - === "Taipy Studio" - - ![](config_03.gif){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } - - - Create the beginning of the Config with Data Nodes following the graph. - - - Change the details of *historical_data* in the 'Details' section of Taipy Studio - - - name: historical_data - - - Details: default_path='xxxx/yyyy.csv', storage_type=csv - - - Add tasks: filter_current and count_values - - - Finish the Config by connecting tasks and Data Nodes and creating the pipeline and scenario - - To use this configuration in our code (`main.py` for example), we must load it and retrieve the `scenario_cfg`. This `scenario_cfg` is the basis to instantiate our scenarios. - - ```python - Config.load('config_03.toml') - - # my_scenario is the id of the scenario configured - scenario_cfg = Config.scenarios['my_scenario'] - ``` - - === "Python configuration" - - ```python - # here is a CSV Data Node - historical_data_cfg = Config.configure_csv_data_node(id="historical_data", - default_path="time_series.csv") - month_values_cfg = Config.configure_data_node(id="month_data") - nb_of_values_cfg = Config.configure_data_node(id="nb_of_values") - ``` - - - ```python - task_filter_cfg = Config.configure_task(id="filter_current", - function=filter_current, - input=historical_data_cfg, - output=month_values_cfg) - - task_count_values_cfg = Config.configure_task(id="count_values", - function=count_values, - input=month_values_cfg, - output=nb_of_values_cfg) - ``` - - - ```python - pipeline_cfg = Config.configure_pipeline(id="my_pipeline", - task_configs=[task_filter_cfg, - task_count_values_cfg]) - - scenario_cfg = Config.configure_scenario(id="my_scenario", - pipeline_configs=[pipeline_cfg]) - - ``` - - -```python -tp.Core().run() - -scenario_1 = tp.create_scenario(scenario_cfg, creation_date=dt.datetime(2022,10,7), name="Scenario 2022/10/7") -scenario_1.submit() - -print("Nb of values of scenario 1:", scenario_1.nb_of_values.read()) -``` - -Results: - -``` -[2022-12-22 16:20:03,424][Taipy][INFO] job JOB_filter_current_257edf8d-3ca3-46f5-aec6-c8a413c86c43 is completed. -[2022-12-22 16:20:03,510][Taipy][INFO] job JOB_count_values_90c9b3c7-91e7-49ef-9064-69963d60f52a is completed. - -Nb of values of scenario 1: 896 -``` diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_03/step_03.md b/docs/tutorials/complete_applications/scenario_management_overview/step_03/step_03.md new file mode 100644 index 000000000..4edabd4ba --- /dev/null +++ b/docs/tutorials/complete_applications/scenario_management_overview/step_03/step_03.md @@ -0,0 +1,127 @@ +> You can download the code for +Step 3 +or all the steps here. + +# Data Node types + +*Time to complete: 15 minutes; Level: Beginner* + +![](Data-Sources.jpg){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } + +- *[Pickle](../../../../manuals/core/config/data-node-config.md/#pickle)* (default): Taipy can read and write any data that can be serializable. + +- *[CSV](../../../../manuals/core/config/data-node-config.md/#csv)*: Taipy can read and write any data frame as a CSV. + +- *[JSON](../../../../manuals/core/config/data-node-config.md/#json)*: Taipy can read and write any JSONable data as a JSON file. + +- *[SQL](../../../../manuals/core/config/data-node-config.md/#sql)*: Taipy can read and write from/to a SQL table or a SQL database. + +- *[Mongo](../../../../manuals/core/config/data-node-config.md/#mongo-collection)*: Taipy can read and write from/to a Mongo Collection + +- *[Parquet](../../../../manuals/core/config/data-node-config.md/#parquet)*: Taipy can read and write data frames from/to a Parquet format + +- *[Generic](../../../../manuals/core/config/data-node-config.md/#generic)*: Taipy provides a generic Data Node that can read and store any data based on a custom _reading_ and _writing_ function created by the user. + +This section uses the simple DAG/execution configuration described below. The configuration consists of the following: + +1. Three Data Nodes: + +_historical data_: This is a CSV-type Data Node. It reads from a CSV file into the initial data frame. You can find the dataset used in the Getting Started +here. + +_month_data_: It stores the data frame generated by the task '_filter_' (stored as a Pickle). + +_nb_of_values_: It stores an integer generated by the '_count_values_' task (stored as a Pickle). + +2. Two tasks linking these Data Nodes: + +_filter_: filters on the current month of the data frame + +_count_values_: calculates the number of elements in this month + + +![](config_03.svg){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } + +```python +def filter_current(df): + current_month = dt.datetime.now().month + df['Date'] = pd.to_datetime(df['Date']) + df = df[df['Date'].dt.month == current_month] + return df + +def count_values(df): + return len(df) +``` + +!!! example "Configuration" + + === "Taipy Studio" + + ![](config_03.gif){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } + + To use this configuration in our code (`main.py` for example), we must load it and retrieve the `scenario_cfg`. This `scenario_cfg` is the basis to instantiate our scenarios. You can retrieve it or take it [here](../src/config_05.toml). + + ```python + Config.load('config_03.toml') + + # my_scenario is the id of the scenario configured + scenario_cfg = Config.scenarios['my_scenario'] + ``` + + === "Python configuration" + + ```python + # here is a CSV Data Node + historical_data_cfg = Config.configure_csv_data_node(id="historical_data", + default_path="time_series.csv") + month_values_cfg = Config.configure_data_node(id="month_data") + nb_of_values_cfg = Config.configure_data_node(id="nb_of_values") + ``` + + + ```python + task_filter_cfg = Config.configure_task(id="filter_current", + function=filter_current, + input=historical_data_cfg, + output=month_values_cfg) + + task_count_values_cfg = Config.configure_task(id="count_values", + function=count_values, + input=month_values_cfg, + output=nb_of_values_cfg) + ``` + + + ```python + scenario_cfg = Config.configure_scenario(id="my_scenario", + task_configs=[task_filter_cfg, + task_count_values_cfg]) + + ``` + +Here is some code to showcase the scenario creation and submission. + +```python +tp.Core().run() + +scenario = tp.create_scenario(scenario_cfg, creation_date=dt.datetime(2022,10,7), name="Scenario 2022/10/7") +scenario.submit() + +print("Nb of values of scenario:", scenario.nb_of_values.read()) + +data_node = None + +tp.Gui("""<|{scenario}|scenario_selector|> + <|{scenario}|scenario|> + <|{scenario}|scenario_dag|> + <|{data_node}|data_node_selector|>""").run() +``` + +Results: + +``` +[2022-12-22 16:20:03,424][Taipy][INFO] job JOB_filter_current_... is completed. +[2022-12-22 16:20:03,510][Taipy][INFO] job JOB_count_values_... is completed. + +Nb of values of scenario: 896 +``` diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_04/ReadMe.md b/docs/tutorials/complete_applications/scenario_management_overview/step_04/step_04.md similarity index 60% rename from docs/tutorials/complete_applications/scenario_management_overview/step_04/ReadMe.md rename to docs/tutorials/complete_applications/scenario_management_overview/step_04/step_04.md index c49fb65a2..438cd223b 100644 --- a/docs/tutorials/complete_applications/scenario_management_overview/step_04/ReadMe.md +++ b/docs/tutorials/complete_applications/scenario_management_overview/step_04/step_04.md @@ -1,13 +1,20 @@ -# Step 4: Cycles +> You can download the code for +Step 4 +or all the steps here. -[Cycles](https://docs.taipy.io/en/latest/manuals/core/concepts/cycle/) have been introduced to reflect business situations our customers frequently encounter. +# Cycles + +*Time to complete: 15 minutes; Level: Intermediate* + +[Cycles](../../../../manuals/core/concepts/cycle.md) have been introduced to reflect business situations our customers frequently encounter and can be extremely useful. + +For instance, a large fast food chain wants to generate sales forecasts for its stores every week. When creating a given scenario, it needs to be attached to a given week. And often, a single one will be published amongst all the scenarios generated for a given week. This kind of 'official' scenario is referred to as the 'Primary' scenario in Taipy. -For instance, a large Fast Food chain wants to generate sales forecasts for its stores every week. When creating a given scenario, it will need to be attached to a given week. And often, a single one will be published amongst all the scenarios generated for a given week. This kind of 'official' scenario will be referred to as the 'Primary' scenario in Taipy Core. Note that Cycles can be ignored entirely if the business problem has no time frequency. -In this step, scenarios are attached to a MONTHLY cycle. Using Cycles, the developer will benefit from specific Taipy's functions to navigate through these Cycles. For instance, by providing the Cycle, Taipy can get all the scenarios created in a month. You can also easily get every primary scenario generated for the past X months to monitor KPIs over time. +In this step, scenarios are attached to a MONTHLY cycle. Using Cycles, the developer benefits from specific Taipy's functions to navigate through these Cycles. For instance, by providing the Cycle, Taipy can get all the scenarios created in a month. You can also easily get every primary scenario generated for the past X months to monitor KPIs over time. Let’s slightly change the filter function by passing the month as an argument to get started. You must create a new Data Node representing the month (see the steps below). @@ -19,14 +26,15 @@ def filter_by_month(df, month): return df ``` + Then to introduce Cycles, you need to set the frequency (predefined attribute) of the scenario to Monthly (as described below). + ![](config_04.svg){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } !!! example "Configuration" - === "Taipy Studio" ![](config_04.gif){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } @@ -35,7 +43,7 @@ Then to introduce Cycles, you need to set the frequency (predefined attribute) o - Add the frequency property for the scenario and put "MONTHLY:FREQUENCY" (DAYLY, WEEKLY, MONTHLY, YEARLY) - - Load the new configuration in the code + - Load the new [configuration](../src/config_04.toml) in the code === "Python configuration" @@ -54,15 +62,18 @@ Then to introduce Cycles, you need to set the frequency (predefined attribute) o ... scenario_cfg = Config.configure_scenario(id="my_scenario", - pipeline_configs=[pipeline_cfg], - frequency=Frequency.MONTHLY) - + task_configs=[task_filter_cfg, + task_count_values_cfg], + frequency=Frequency.MONTHLY) ``` +As you can see, a Cycle is activated once you have set the desired frequency of the scenario. In this code snippet, since we have specified `frequency=Frequency.MONTHLY`, the corresponding scenario is automatically attached to the correct period (month) when it is created. + + +The Cycle which a Scenario belongs to is based on the _creation_date_ (`datetime.datetime.now()` by default) of the scenario. It can be "attached" to a specific cycle by manually setting its _creation_date_, as we are doing in the following example. -As you can see, a Cycle is activated once you have set the desired frequency on the scenario. In this code snippet, since we have specified `frequency=Frequency.MONTHLY`, the corresponding scenario will be automatically attached to the correct period (month) once it is created. The _creation_date_ here is artificially given to the scenarios. ```python tp.Core().run() @@ -75,7 +86,7 @@ scenario_2 = tp.create_scenario(scenario_cfg, name="Scenario 2022/10/5") ``` -Scenario 1 and Scenario 2 are two scenario entities/instances created from the same scenario configuration. They belong to the same Cycle but don't share the same Data Nodes. By default, each scenario instance has its own data node instances. They are not shared with any other scenario. The Scope concept can modify this behavior, which will be covered in the next step. +Scenario 1 and Scenario 2 are two scenario entities/instances created from the same scenario configuration. They belong to the same Cycle but don't share the same Data Nodes. By default, each scenario instance has its own data node instances. They are not shared with any other scenario. The Scope concept can modify this behavior, which is covered in the next step. ```python @@ -95,19 +106,35 @@ Results: ``` Month Data Node of Scenario 1 10 Month Data Node of Scenario 2 10 -[2022-12-22 16:20:04,746][Taipy][INFO] job JOB_filter_by_month_a4d3c4a7-5ec9-4cca-8a1b-578c910e255a is completed. -[2022-12-22 16:20:04,833][Taipy][INFO] job JOB_count_values_a81b2f60-e9f9-4848-aa58-272810a0b755 is completed. -[2022-12-22 16:20:05,026][Taipy][INFO] job JOB_filter_by_month_22a3298b-ac8d-4b55-b51f-5fab0971cc9e is completed. -[2022-12-22 16:20:05,084][Taipy][INFO] job JOB_count_values_a52b910a-4024-443e-8ea2-f3cdda6c1c9d is completed. -[2022-12-22 16:20:05,317][Taipy][INFO] job JOB_filter_by_month_8643e5cf-e863-434f-a1ba-18222d6faab8 is completed. -[2022-12-22 16:20:05,376][Taipy][INFO] job JOB_count_values_72ab71be-f923-4898-a8a8-95ec351c24d9 is completed. +[2022-12-22 16:20:04,746][Taipy][INFO] job JOB_filter_by_month_... is completed. +[2022-12-22 16:20:04,833][Taipy][INFO] job JOB_count_values_... is completed. +[2022-12-22 16:20:05,026][Taipy][INFO] job JOB_filter_by_month_... is completed. +[2022-12-22 16:20:05,084][Taipy][INFO] job JOB_count_values_... is completed. +[2022-12-22 16:20:05,317][Taipy][INFO] job JOB_filter_by_month_... is completed. +[2022-12-22 16:20:05,376][Taipy][INFO] job JOB_count_values_... is completed. ``` ## Primary scenarios -In each Cycle, there is a primary scenario. A primary scenario is interesting because it represents the important scenario of the Cycle, the reference. By default, the first scenario created for a cycle will be primary. +In each Cycle, there is a primary scenario. A primary scenario is interesting because it represents the important scenario of the Cycle, the reference. By default, the first scenario created for a cycle is primary. -[`tp.set_primary()`](https://docs.taipy.io/en/latest/manuals/core/entities/scenario-cycle-mgt/#promote-a-scenario-as-primary) allows changing the primary scenario in a Cycle. +### GUI-Core visual elements + +GUI-Core elements may be used to manipulate Cycles. Cycles are visible in *scenario_selector* or *data_node_selector*. It is also possible to make a scenario primary directly through the `scenario` visual element. + +```python +data_node = None +scenario = None + +tp.Gui("""<|{scenario}|scenario_selector|> + <|{scenario}|scenario|> + <|{scenario}|scenario_dag|> + <|{data_node}|data_node_selector|>""").run() +``` + +### Python code associated to primary scenarios + +[`tp.set_primary()`](../../../../manuals/core/entities/scenario-cycle-mgt.md/#promote-a-scenario-as-primary) allows changing the primary scenario in a Cycle. `.is_primary` identifies as a boolean whether the scenario is primary or not. @@ -136,8 +163,6 @@ Scenario 3 is the only scenario in another Cycle due to its creation date and is scenario_3 = tp.create_scenario(scenario_cfg, creation_date=dt.datetime(2021,9,1), name="Scenario 2022/9/1") -scenario_3.month.write(9) -scenario_3.submit() print("Is scenario 3 primary?", scenario_3.is_primary) ``` @@ -145,14 +170,9 @@ print("Is scenario 3 primary?", scenario_3.is_primary) Results: ``` -[2022-12-22 16:20:05,317][Taipy][INFO] job JOB_filter_by_month_8643e5cf-e863-434f-a1ba-18222d6faab8 is completed. -[2022-12-22 16:20:05,376][Taipy][INFO] job JOB_count_values_72ab71be-f923-4898-a8a8-95ec351c24d9 is completed. - Is scenario 3 primary? True ``` -Also, as you can see, every scenario has been submitted and executed entirely. However, the results for these tasks are all the same. Skipping Tasks (defined in subsequent steps) will help optimize your executions by skipping the execution of redundant tasks. - ## Useful functions on cycles - `tp.get_primary_scenarios()`: returns a list of all primary scenarios diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_05/ReadMe.md b/docs/tutorials/complete_applications/scenario_management_overview/step_05/ReadMe.md deleted file mode 100644 index d9817ad46..000000000 --- a/docs/tutorials/complete_applications/scenario_management_overview/step_05/ReadMe.md +++ /dev/null @@ -1,107 +0,0 @@ -> You can download the code of this step [here](../src/step_05.py) or all the steps [here](https://github.com/Avaiga/taipy-getting-started-core/tree/develop/src). - -# Step 5: Scopes - -[Scopes](https://docs.taipy.io/en/latest/manuals/core/concepts/scope/) determine how Data Nodes are shared between cycles, scenarios, and pipelines. The developer may decide to: - -- Keep Data Nodes local to each pipeline. - -- Extend the scope by sharing data nodes between a given scenario's pipelines. - -- Extend the scope by sharing data nodes across all scenarios of a given cycle. - -- Finally, extend the scope globally (across all scenarios of all cycles). For example, the initial/historical dataset is usually shared by all the scenarios/pipelines/cycles. It has a Global Scope and will be unique in the entire application. - -To summarize, the different possible scopes are: - -- _Pipeline scope_: two pipelines can reference different Data Nodes even if their names are the same. For example, we can have a _prediction_ Data Node of an ARIMA model (ARIMA pipeline) and a _prediction_ Data Node of a RandomForest model (RandomForest pipeline). A scenario can contain multiple pipelines. - -- _Scenario scope (default)_: pipelines share the same Data Node within a scenario. - -- _Cycle scope_: scenarios from the same Cycle share the same Data Node. - -- _Global scope_: Data Nodes are shared across all the scenarios/pipelines/cycles. - -It is worth noting that the default scope for Data nodes is the Scenario scope. - -![](config_05.svg){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } - -!!! example "Configuration" - - === "Taipy Studio" - - Modifying the scope of a Data Node is as simple as changing its Scope parameter in the configuration. - - The configuration is taken in the previous step, so you can copy the last TOML Config file directly. - - ![](config_05.gif){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } - - - Change the Scope of historical_data to be global - - - name: historical_data - - - Details: default_path=xxxx/yyyy.csv, storage_type=csv, scope=GLOBAL:SCOPE - - - Change the Scope of month_data and month to be Cycle - - - name: output - - - Details: storage_type:pickle, scope=CYCLE:SCOPE - - - Load the new configuration in the code - - === "Python configuration" - - Modifying the scope of a Data Node is as simple as changing its Scope parameter inside the configuration. - - The configuration is taken in the previous step so you can copy the previous code directly. - - ```python - from taipy.config import Scope, Frequency - - historical_data_cfg = Config.configure_csv_data_node(id="historical_data", - default_path="time_series.csv", - scope=Scope.GLOBAL) - month_cfg = Config.configure_data_node(id="month", scope=Scope.CYCLE) - - month_values_cfg = Config.configure_data_node(id="month_data", - scope=Scope.CYCLE) - ``` - - -Cycles are created based on the _creation_date_ of scenarios. In the example below, we force the creation_date to a given date (in real life, the actual creation date of the scenario gets used automatically). - -```python -tp.Core().run() - -scenario_1 = tp.create_scenario(scenario_cfg, - creation_date=dt.datetime(2022,10,7), - name="Scenario 2022/10/7") -scenario_2 = tp.create_scenario(scenario_cfg, - creation_date=dt.datetime(2022,10,5), - name="Scenario 2022/10/5") -scenario_3 = tp.create_scenario(scenario_cfg, - creation_date=dt.datetime(2021,9,1), - name="Scenario 2021/9/1") -``` - -Scenario 1 and 2 belong to the same Cycle: since _month_ now has a **Cycle** scope, we can define _month_ just once for both scenarios: 1 and 2. - - -```python -scenario_1.month.write(10) -scenario_3.month.write(9) -print("Scenario 1: month", scenario_1.month.read()) -print("Scenario 2: month", scenario_2.month.read()) -print("Scenario 3: month", scenario_2.month.read()) -``` -Results: -``` -Scenario 1: month 10 -Scenario 2: month 10 -Scenario 3: month 9 -``` - -Defining the _month_ of scenario 1 will also determine the _month_ of scenario 2 since they share the same Data Node. - -This is not the case for _nb_of_values_ that are of Scenario scope; each _nb_of_values_ has its own value in each scenario. diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_05/step_05.md b/docs/tutorials/complete_applications/scenario_management_overview/step_05/step_05.md new file mode 100644 index 000000000..e167cad34 --- /dev/null +++ b/docs/tutorials/complete_applications/scenario_management_overview/step_05/step_05.md @@ -0,0 +1,159 @@ +> You can download the code for +Step 5 +or all the steps here. + +# Scopes + +*Time to complete: 15 minutes; Level: Intermediate* + +[Scopes](../../../../manuals/core/concepts/scope.md) determine how Data Nodes are shared between cycles and scenarios. The developer may decide: + +- `Scope.SCENARIO` (_default_): Having one data node for each scenario. + +- `Scope.CYCLE`: Extend the scope by sharing data nodes across all scenarios of a given cycle. + +- `Scope.GLOBAL`: Finally, extend the scope globally (across all scenarios of all cycles). For example, the initial/historical dataset is usually shared by all the scenarios/pipelines/cycles. It is unique in the entire application. + +![](config_05.svg){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } + +!!! example "Configuration" + + === "Taipy Studio" + + Modifying the scope of a Data Node is as simple as changing its Scope parameter in the configuration. + + The configuration is taken in the previous step, so you can copy the last TOML Config file directly or take it [here](../src/config_04.toml). + + ![](config_05.gif){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } + + - Change the Scope of historical_data to be global + + - Change the Scope of month_data and month to be Cycle + + - Load the new configuration in the code + + === "Python configuration" + + Modifying the scope of a Data Node is as simple as changing its Scope parameter inside the configuration. + + The configuration is taken in the previous step so you can copy the previous code directly. + + ```python + from taipy.config import Scope, Frequency + + historical_data_cfg = Config.configure_csv_data_node(id="historical_data", + default_path="time_series.csv", + scope=Scope.GLOBAL) + month_cfg = Config.configure_data_node(id="month", scope=Scope.CYCLE) + + month_values_cfg = Config.configure_data_node(id="month_data", + scope=Scope.CYCLE) + + ... + ``` + + +Cycles are created based on the _creation_date_ of scenarios. In the example below, we force the creation_date to a given date (in real life, the actual creation date of the scenario gets used automatically). + +```python +tp.Core().run() + +scenario_1 = tp.create_scenario(scenario_cfg, + creation_date=dt.datetime(2022,10,7), + name="Scenario 2022/10/7") +scenario_2 = tp.create_scenario(scenario_cfg, + creation_date=dt.datetime(2022,10,5), + name="Scenario 2022/10/5") +scenario_3 = tp.create_scenario(scenario_cfg, + creation_date=dt.datetime(2021,9,1), + name="Scenario 2021/9/1") +``` + +Scenario 1 and 2 belong to the same Cycle: since _month_ now has a **Cycle** scope, we can define _month_ just once for both scenarios: 1 and 2. + + +```python +scenario_1.month.write(10) +scenario_3.month.write(9) +print("Scenario 1: month", scenario_1.month.read()) +print("Scenario 2: month", scenario_2.month.read()) +print("Scenario 3: month", scenario_3.month.read()) +``` + +Results: +``` +Scenario 1: month 10 +Scenario 2: month 10 +Scenario 3: month 9 +``` + +Defining the _month_ of scenario 1 will also determine the _month_ of scenario 2 since they share the same Data Node. + +This is not the case for _nb_of_values_ that are of Scenario scope; each _nb_of_values_ has its own value in each scenario. + +## Entire code + +```python +from taipy.core.config import Config, Frequency, Scope +import taipy as tp +import datetime as dt +import pandas as pd + + +def filter_by_month(df, month): + df['Date'] = pd.to_datetime(df['Date']) + df = df[df['Date'].dt.month == month] + return df + +def count_values(df): + return len(df) + + +historical_data_cfg = Config.configure_csv_data_node(id="historical_data", + default_path="time_series.csv", + scope=Scope.GLOBAL) +month_cfg = Config.configure_data_node(id="month", scope=Scope.CYCLE) + +month_values_cfg = Config.configure_data_node(id="month_data", + scope=Scope.CYCLE) +nb_of_values_cfg = Config.configure_data_node(id="nb_of_values") + + +task_filter_cfg = Config.configure_task(id="filter_by_month", + function=filter_by_month, + input=[historical_data_cfg,month_cfg], + output=month_values_cfg) + +task_count_values_cfg = Config.configure_task(id="count_values", + function=count_values, + input=month_values_cfg, + output=nb_of_values_cfg) + + + +scenario_cfg = Config.configure_scenario(id="my_scenario", + task_configs=[task_filter_cfg, + task_count_values_cfg], + frequency=Frequency.MONTHLY) + + +if __name__ == '__main__': + tp.Core().run() + + scenario_1 = tp.create_scenario(scenario_cfg, + creation_date=dt.datetime(2022,10,7), + name="Scenario 2022/10/7") + scenario_2 = tp.create_scenario(scenario_cfg, + creation_date=dt.datetime(2022,10,5), + name="Scenario 2022/10/5") + + scenario_1.month.write(10) + print("Scenario 1: month", scenario_1.month.read()) + print("Scenario 2: month", scenario_2.month.read()) + + print("\nScenario 1 & 2: submit") + scenario_1.submit() + scenario_2.submit() + print("Value", scenario_1.nb_of_values.read()) + print("Value", scenario_2.nb_of_values.read()) +``` diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_06/ReadMe.md b/docs/tutorials/complete_applications/scenario_management_overview/step_06/ReadMe.md deleted file mode 100644 index f73a6217f..000000000 --- a/docs/tutorials/complete_applications/scenario_management_overview/step_06/ReadMe.md +++ /dev/null @@ -1,173 +0,0 @@ -> You can download the code of this step [here](../src/step_06.py) or all the steps [here](https://github.com/Avaiga/taipy-getting-started-core/tree/develop/src). - -# Step 6: Skipping tasks - -Skipping tasks is an essential feature of Taipy. Running twice a function with the same input parameters will create the same output for a given pipeline or scenario. Executing this sort of function is a waste of time and resources. - -Taipy Core provides for each task the _skippable_ attribute. If this attribute is set to True, Taipy Core’s scheduler will automatically detect if changes have occurred on any of the input Data Nodes of a task. If no changes have occurred, it will automatically skip the execution of that task. By default, skippable is set to False. - - -![](config_06.svg){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } - -!!! example "Configuration" - - === "Taipy Studio" - - ![](config_06.gif){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } - - - Add the skippable to the tasks - - - name: filter_current - - - Details: function=`__main__.filter_current:function`, skippable=True:bool - - - Do the same for count_values - - - ```python - Config.load('config_06.toml') - - # my_scenario is the id of the scenario configured - scenario_cfg = Config.scenarios['my_scenario'] - ``` - - === "Python configuration" - - ```python - task_filter_cfg = Config.configure_task(id="filter_by_month", - function=filter_by_month, - input=[historical_data_cfg, month_cfg], - output=month_values_cfg, - skippable=True) - - task_count_values_cfg = Config.configure_task(id="count_values", - function=count_values, - input=month_values_cfg, - output=nb_of_values_cfg, - skippable=True) - ``` - -The configuration is almost the same. `skippable=True` are added to the tasks we want to be skipped. - -Here we create three different scenarios with different creation dates and names. Scenario 1 and scenario 2 belong to the same cycle. - - -```python -tp.Core().run() - -scenario_1 = tp.create_scenario(scenario_cfg, - creation_date=dt.datetime(2022,10,7), - name="Scenario 2022/10/7") -scenario_2 = tp.create_scenario(scenario_cfg, - creation_date=dt.datetime(2022,10,5), - name="Scenario 2022/10/5") -scenario_3 = tp.create_scenario(scenario_cfg, - creation_date=dt.datetime(2021,9,1), - name="Scenario 2022/9/1") -``` - - -```python -# scenario 1 and 2 belong to the same cycle, so -# defining the month for scenario 1 defines the month for the scenarios in the cycle -scenario_1.month.write(10) -print("Scenario 1: month", scenario_1.month.read()) -print("Scenario 2: month", scenario_2.month.read()) -``` - -Results: - -``` -Scenario 1: month 10 -Scenario 2: month 10 -``` - -Every task has yet to be submitted, so when submitting scenario 1, all tasks will be executed. - -```python -print("Scenario 1: submit") -scenario_1.submit() -print("Value", scenario_1.nb_of_values.read()) -``` - -Results: - -``` -Scenario 1: submit -[2022-12-22 16:20:09,079][Taipy][INFO] job JOB_filter_by_month_0d7836eb-70eb-4fe6-b954-0e56967831b6 is completed. -[2022-12-22 16:20:09,177][Taipy][INFO] job JOB_count_values_91214241-ce81-42d8-9025-e83509652133 is completed. -Value 849 -``` - -When submitting scenario 2, the scheduler will skip the first task of this second scenario. Indeed, the two scenarios share the same input Data Nodes for this task, and no changes have occurred on these Data Nodes (since the last task run when we submitted scenario 1). - -```python -# the first task has already been executed by scenario 1 -print("Scenario 2: first submit") -scenario_2.submit() -print("Value", scenario_2.nb_of_values.read()) -``` - -Results: -``` -Scenario 2: first submit -[2022-12-22 16:20:09,317][Taipy][INFO] job JOB_filter_by_month_c1db1f0c-6e0a-4691-b0a3-331d473c4c42 is skipped. -[2022-12-22 16:20:09,371][Taipy][INFO] job JOB_count_values_271cefd0-8648-47fa-8948-ed49e93e3eee is completed. -Value 849 -``` - -Resubmitting the same scenario without any change will skip every task. - -```python -# every task has already been executed so that the scheduler will skip everything -print("Scenario 2: second submit") -scenario_2.submit() -print("Value", scenario_2.nb_of_values.read()) -``` - -Results: -``` -Scenario 2: second submit -[2022-12-22 16:20:09,516][Taipy][INFO] job JOB_filter_by_month_da2762d1-6f24-40c1-9bd1-d6786fee7a8d is skipped. -[2022-12-22 16:20:09,546][Taipy][INFO] job JOB_count_values_9071dff4-37b2-4095-a7ed-34ef81daad27 is skipped. -Value 849 -``` - -This scenario is not in the same cycle. We change the month to 9, and the scheduler will complete every task. - - -```python -# scenario 3 has no connection to the other scenarios, so everything will be executed -print("Scenario 3: submit") -scenario_3.month.write(9) -scenario_3.submit() -print("Value", scenario_3.nb_of_values.read()) -``` - -Results: -``` -Scenario 3: submit -[2022-12-22 16:20:10,071][Taipy][INFO] job JOB_filter_by_month_c4d06eba-a149-4b79-9194-78972c7b7a18 is completed. -[2022-12-22 16:20:10,257][Taipy][INFO] job JOB_count_values_817df173-6bae-4742-a2c0-b8b8eba52872 is completed. -Value 1012 -``` - -Here, we change the input Data Node of the pipeline so Taipy will re-run the correct tasks to ensure that everything is up-to-date. - - -```python -# changing an input data node will make the task be executed -print("Scenario 3: change in historical data") -scenario_3.historical_data.write(pd.read_csv('time_series_2.csv')) -scenario_3.submit() -print("Value", scenario_3.nb_of_values.read()) -``` - -Results: - -``` -Scenario 3: change in historical data -[2022-12-22 16:20:10,870][Taipy][INFO] job JOB_filter_by_month_92f32135-b410-41f0-b9f3-a852c2eb07cd is completed. -[2022-12-22 16:20:10,932][Taipy][INFO] job JOB_count_values_a6a75e13-4cd4-4f7e-bc4e-d14a86733440 is completed. -Value 1012 -``` diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_06/step_06.md b/docs/tutorials/complete_applications/scenario_management_overview/step_06/step_06.md new file mode 100644 index 000000000..2ef23f1dc --- /dev/null +++ b/docs/tutorials/complete_applications/scenario_management_overview/step_06/step_06.md @@ -0,0 +1,147 @@ +> You can download the code for +Step 6 +or all the steps here. + +# Skipping tasks + +*Time to complete: 15 minutes; Level: Intermediate* + +Skipping tasks is an essential feature of Taipy. Running twice a function with the same inputs can create the same output. Executing this sort of function is a waste of time and resources. + +Taipy offers the option to set the _skippable_ attribute for each task. If this attribute is set to True, Taipy Core’s scheduler automatically detects if changes have occurred on any of the input Data Nodes of a task. +If there are no changes, it automatically skips the execution of that task. By default, _skippable_ is set to False. + + +![](config_06.svg){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } + +!!! example "Configuration" + + === "Taipy Studio" + + ![](config_06.gif){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } + + - Add _skippable_ to the tasks + + ```python + Config.load('config_06.toml') + + # my_scenario is the id of the scenario configured + scenario_cfg = Config.scenarios['my_scenario'] + ``` + + === "Python configuration" + + The configuration is almost the same. `skippable=True` are added to the tasks we want to be skipped. + + ```python + task_filter_cfg = Config.configure_task(id="filter_by_month", + function=filter_by_month, + input=[historical_data_cfg, month_cfg], + output=month_values_cfg, + skippable=True) + + task_count_values_cfg = Config.configure_task(id="count_values", + function=count_values, + input=month_values_cfg, + output=nb_of_values_cfg, + skippable=True) + ``` + +Here we create three different scenarios with different creation dates and names. Scenario 1 and scenario 2 belong to the same cycle. + +```python +tp.Core().run() + +scenario_1 = tp.create_scenario(scenario_cfg, + creation_date=dt.datetime(2022,10,7), + name="Scenario 2022/10/7") +scenario_2 = tp.create_scenario(scenario_cfg, + creation_date=dt.datetime(2022,10,5), + name="Scenario 2022/10/5") +scenario_3 = tp.create_scenario(scenario_cfg, + creation_date=dt.datetime(2021,9,1), + name="Scenario 2022/9/1") + +scenario_1.month.write(10) +``` + +Here, the scenario 1 is submitted. + +```python +print("Scenario 1: submit") +scenario_1.submit() +print("Value", scenario_1.nb_of_values.read()) +``` + +Results: + +``` +Scenario 1: submit +[2022-12-22 16:20:09,079][Taipy][INFO] job JOB_filter_by_month_... is completed. +[2022-12-22 16:20:09,177][Taipy][INFO] job JOB_count_values_... is completed. +Value 849 +``` + +When you submit scenario 2, the scheduler skips the initial task in this second scenario. This is because both scenarios use the same Data Nodes for this task, and there have been no changes in the input Data Nodes since the last time the task ran when we submitted scenario 1. + +```python +# the first task has already been executed by scenario 1 +print("Scenario 2: first submit") +scenario_2.submit() +print("Value", scenario_2.nb_of_values.read()) +``` + +Results: +``` +Scenario 2: first submit +[2022-12-22 16:20:09,317][Taipy][INFO] job JOB_filter_by_month_... is skipped. +[2022-12-22 16:20:09,371][Taipy][INFO] job JOB_count_values_... is completed. +Value 849 +``` + +Resubmitting the same scenario without any change skips every task. + +```python +print("Scenario 2: second submit") +scenario_2.submit() +print("Value", scenario_2.nb_of_values.read()) +``` + +Results: +``` +Scenario 2: second submit +[2022-12-22 16:20:09,516][Taipy][INFO] job JOB_filter_by_month_... is skipped. +[2022-12-22 16:20:09,546][Taipy][INFO] job JOB_count_values_... is skipped. +Value 849 +``` + +Scenario 3 is not in the same cycle. The scheduler completes every task. + +```python +scenario_3.month.write(9) +scenario_3.submit() +``` + +Results: +``` +[2022-12-22 16:20:10,071][Taipy][INFO] job JOB_filter_by_month_... is completed. +[2022-12-22 16:20:10,257][Taipy][INFO] job JOB_count_values_... is completed. +``` + +Here, we change the input Data Node of the pipeline so Taipy will re-run the correct tasks to ensure that everything is up-to-date. + + +```python +# changing an input data node will make the task be executed +print("Scenario 3: change in historical data") +scenario_3.historical_data.write(pd.read_csv('time_series_2.csv')) +scenario_3.submit() +``` + +Results: + +``` +Scenario 3: change in historical data +[2022-12-22 16:20:10,870][Taipy][INFO] job JOB_filter_by_month_... is completed. +[2022-12-22 16:20:10,932][Taipy][INFO] job JOB_count_values_... is completed. +``` diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_07/ReadMe.md b/docs/tutorials/complete_applications/scenario_management_overview/step_07/ReadMe.md deleted file mode 100644 index 0e44f1e10..000000000 --- a/docs/tutorials/complete_applications/scenario_management_overview/step_07/ReadMe.md +++ /dev/null @@ -1,55 +0,0 @@ -> You can download the code of this step [here](../src/step_07.py) or all the steps [here](https://github.com/Avaiga/taipy-getting-started-core/tree/develop/src). - -# Step 7: Execution modes - -Taipy has [different ways](https://docs.taipy.io/en/latest/manuals/core/config/job-config/) to execute the code. Changing the execution mode can be useful for running multiple tasks in parallel. -- _standalone_ mode: asynchronous. Jobs can be run in parallel depending on the graph of execution if _max_nb_of_workers_ > 1. -- _development_ mode: synchronous. - -In this step, we define a new configuration and functions to showcase the two execution modes. - -```python -# Normal function used by Taipy -def double(nb): - return nb * 2 - -def add(nb): - print("Wait 10 seconds in add function") - time.sleep(10) - return nb + 10 -``` - -![](config_07.svg){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } - - - -This line of code will change the execution mode (the default execution mode is _development_). Changing it to _standalone_ will make Taipy Core asynchronous. Here a maximum of two tasks will be able to run concurrently. - -```python -Config.configure_job_executions(mode="standalone", max_nb_of_workers=2) -``` - - -```python -if __name__=="__main__": - tp.Core().run() - scenario_1 = tp.create_scenario(scenario_cfg) - scenario_1.submit() - scenario_1.submit() - - time.sleep(30) -``` - -Jobs from the two submissions are being executed simultaneously. If `max_nb_of_workers` was greater, we could run multiple scenarios at the same time and multiple tasks of a scenario at the same time. - -Some options for the [_submit_](https://docs.taipy.io/en/latest/manuals/reference/taipy.core.Scenario/#taipy.core.scenario.scenario.Scenario.submit) function exist: -- _wait_: if _wait_ is True, the submit is synchronous and will wait for the end of all the jobs (if _timeout_ is not defined). -- _timeout_: if _wait_ is True, Taipy will wait for the end of the submission up to a certain amount of time. - -```python -if __name__=="__main__": - tp.Core().run() - scenario_1 = tp.create_scenario(scenario_cfg) - scenario_1.submit(wait=True) - scenario_1.submit(wait=True, timeout=5) -``` diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_07/step_07.md b/docs/tutorials/complete_applications/scenario_management_overview/step_07/step_07.md new file mode 100644 index 000000000..42bd29d85 --- /dev/null +++ b/docs/tutorials/complete_applications/scenario_management_overview/step_07/step_07.md @@ -0,0 +1,118 @@ +> You can download the code for +Step 7 +or all the steps here. + +# Executing jobs + +*Time to complete: 15 minutes; Level: Advanced* + +Taipy has [different ways](../../../../manuals/core/config/job-config.md) to execute the code. Changing the execution mode can be useful for running multiple tasks in parallel. + +- _standalone_ mode: asynchronous. Jobs can be run in parallel depending on the graph of execution (if _max_nb_of_workers_ > 1). + +- _development_ mode: synchronous. The default execution mode is _development_. + +In this step, we define a new configuration and functions to showcase the two execution modes. + +```python +# Normal function used by Taipy +def double(nb): + return nb * 2 + +def add(nb): + print("Wait 10 seconds in add function") + time.sleep(10) + return nb + 10 +``` + +![](config_07.svg){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } + +This line of code changes the execution mode. _standalone_ makes Taipy Core asynchronous. Here, a maximum of two tasks are able to run concurrently. + +```python +Config.configure_job_executions(mode="standalone", max_nb_of_workers=2) +``` + + +```python +if __name__=="__main__": + tp.Core().run() + scenario_1 = tp.create_scenario(scenario_cfg) + scenario_2 = tp.create_scenario(scenario_cfg) + + scenario_1.submit() + scenario_2.submit() + + time.sleep(30) +``` + +Jobs from the two submissions are being executed simultaneously. If `max_nb_of_workers` was greater, we could run multiple scenarios at the same time and multiple tasks of a scenario at the same time. + +Some options for the _submit_ function exist: + +- _wait_: if _wait_ is True, the submission waits for the end of all the jobs (if _timeout_ is not defined). + +- _timeout_: if _wait_ is True, Taipy waits for the end of the submission up to a certain amount of time. + +```python +if __name__=="__main__": + tp.Core().run() + scenario_1 = tp.create_scenario(scenario_cfg) + scenario_1.submit(wait=True) + scenario_1.submit(wait=True, timeout=5) +``` + +## Entire code + + +```python +from taipy.core.config import Config +import taipy as tp +import datetime as dt +import pandas as pd +import time + +# Normal function used by Taipy +def double(nb): + return nb * 2 + +def add(nb): + print("Wait 10 seconds in add function") + time.sleep(10) + return nb + 10 + +Config.configure_job_executions(mode="standalone", max_nb_of_workers=2) + +# Configuration of Data Nodes +input_cfg = Config.configure_data_node("input", default_data=21) +intermediate_cfg = Config.configure_data_node("intermediate", default_data=21) +output_cfg = Config.configure_data_node("output") + +# Configuration of tasks +first_task_cfg = Config.configure_task("double", + double, + input_cfg, + intermediate_cfg) + +second_task_cfg = Config.configure_task("add", + add, + intermediate_cfg, + output_cfg) + +# Configuration of the pipeline and scenario +scenario_cfg = Config.configure_scenario(id="my_scenario", + task_configs=[first_task_cfg, + second_task_cfg]) + + +if __name__=="__main__": + tp.Core().run() + scenario_1 = tp.create_scenario(scenario_cfg) + scenario_2 = tp.create_scenario(scenario_cfg) + scenario_1.submit() + scenario_2.submit() + + scenario_1 = tp.create_scenario(scenario_cfg) + scenario_1.submit(wait=True) + scenario_1.submit(wait=True, timeout=5) +``` \ No newline at end of file diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_08/ReadMe.md b/docs/tutorials/complete_applications/scenario_management_overview/step_08/ReadMe.md deleted file mode 100644 index dd58e8436..000000000 --- a/docs/tutorials/complete_applications/scenario_management_overview/step_08/ReadMe.md +++ /dev/null @@ -1,68 +0,0 @@ -> You can download the code of this step [here](../src/step_08.py) or all the steps [here](https://github.com/Avaiga/taipy-getting-started-core/tree/develop/src). - -# Step 8: Scenario comparison - -This step reuses the configuration provided in the previous step except for the [scenario configuration](https://docs.taipy.io/en/latest/manuals/core/entities/scenario-cycle-mgt/#compare-scenarios). - -![](config_08.svg){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } - -Taipy provides a mechanism to compare scenarios by providing a function directly into the scenario's configuration. - -## Step 1: The first step consists in declaring on which data nodes to apply the comparison functions: - -Taipy can compare Data Nodes. In this example, we want a comparison applied to the '_output_' Data Node. It is indicated in the comparators parameter of the `configure_scenario()`. - -```python -scenario_cfg = Config.configure_scenario(id="multiply_scenario", - name="my_scenario", - pipeline_configs=[pipeline_cfg], - comparators={output_data_node_cfg.id: compare_function}, - frequency=Frequency.MONTHLY) -``` -## Step 2: Implement the comparison function (`compare_function()`) used above. - -_data_node_results_ is the list of the Output Data Nodes from all scenarios passed in the comparator. We iterate through it to compare scenarios. - -```python -def compare_function(*data_node_results): - compare_result= {} - current_res_i = 0 - for current_res in data_node_results: - compare_result[current_res_i]={} - next_res_i = 0 - for next_res in data_node_results: - print(f"comparing result {current_res_i} with result {next_res_i}") - compare_result[current_res_i][next_res_i] = next_res - current_res - next_res_i += 1 - current_res_i += 1 - return compare_result -``` - -Now, the `compare_scenarios()` can be used within Taipy. - -```python -tp.Core().run() - -scenario_1 = tp.create_scenario(scenario_cfg) -scenario_2 = tp.create_scenario(scenario_cfg) - - -print("\nScenario 1: submit") -scenario_1.submit() -print("Value", scenario_1.output.read()) - -print("\nScenario 2: first submit") -scenario_2.submit() -print("Value", scenario_2.output.read()) - - -print(tp.compare_scenarios(scenario_1, scenario_2)) -``` - -## Taipy Rest - -Taipy Rest allows the user to navigate through the entities of the application but also create and submit scenarios. Taipy Rest commands are referenced [here](https://docs.taipy.io/en/latest/manuals/reference_rest/). - -```python -tp.Rest().run() -``` \ No newline at end of file diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_08/step_08.md b/docs/tutorials/complete_applications/scenario_management_overview/step_08/step_08.md new file mode 100644 index 000000000..48f90be60 --- /dev/null +++ b/docs/tutorials/complete_applications/scenario_management_overview/step_08/step_08.md @@ -0,0 +1,133 @@ +> You can download the code for +Step 8 +or all the steps here. + +# Comparing scenarios + +*Time to complete: 15 minutes; Level: Advanced* + +![](config_08.svg){ width=700 style="margin:auto;display:block;border: 4px solid rgb(210,210,210);border-radius:7px" } + +Taipy provides a mechanism to compare data nodes of scenarios by providing a function directly into the scenario's configuration. + +## Step 1: The first step consists in declaring on which data nodes to apply the comparison functions: + +In this example, we want a comparison applied to the '_output_' Data Node. It is indicated in the comparators parameter of the `configure_scenario()`. + +```python +scenario_cfg = Config.configure_scenario(id="multiply_scenario", + name="my_scenario", + tasks_configs=[pipeline_cfg], + comparators={output_data_node_cfg.id: compare_function},) +``` +## Step 2: Implement the comparison function (`compare_function()`) used above. + +_data_node_results_ is the list of the Output Data Nodes from all scenarios passed in the comparator. We iterate through it to compare scenarios. + +```python +def compare_function(*data_node_results): + compare_result = {} + current_res_i = 0 + for current_res in data_node_results: + compare_result[current_res_i] = {} + next_res_i = 0 + for next_res in data_node_results: + print(f"comparing result {current_res_i} with result {next_res_i}") + compare_result[current_res_i][next_res_i] = next_res - current_res + next_res_i += 1 + current_res_i += 1 + return compare_result +``` + +Now, the `compare_scenarios()` can be used within Taipy. + +```python +tp.Core().run() + +scenario_1 = tp.create_scenario(scenario_cfg) +scenario_2 = tp.create_scenario(scenario_cfg) + +scenario_1.submit() +scenario_2.submit() + +print(tp.compare_scenarios(scenario_1, scenario_2)) +``` + +Results: + +``` +... +{'output': {'compare_function': {0: {0: 0, 1: -4}, 1: {0: 4, 1: 0}}}} +``` + +# Entire code + + +```python +from taipy.core.config import Config, Frequency +import taipy as tp + + +# Normal function used by Taipy +def double(nb): + return nb * 2 + +def add(nb): + return nb + 10 + + +# Configuration of Data Nodes +input_cfg = Config.configure_data_node("input", default_data=21) +intermediate_cfg = Config.configure_data_node("intermediate") +output_cfg = Config.configure_data_node("output") + +# Configuration of tasks +first_task_cfg = Config.configure_task("double", + double, + input_cfg, + intermediate_cfg) + +second_task_cfg = Config.configure_task("add", + add, + intermediate_cfg, + output_cfg) + + + +def compare_function(*data_node_results): + # example of function + compare_result = {} + current_res_i = 0 + for current_res in data_node_results: + compare_result[current_res_i] = {} + next_res_i = 0 + for next_res in data_node_results: + print(f"comparing result {current_res_i} with result {next_res_i}") + compare_result[current_res_i][next_res_i] = next_res - current_res + next_res_i += 1 + current_res_i += 1 + return compare_result + + +scenario_cfg = Config.configure_scenario(id="multiply_scenario", + name="my_scenario", + task_configs=[first_task_cfg, second_task_cfg], + comparators={output_cfg.id: compare_function}) + + +if __name__=="__main__": + tp.Core().run() + + scenario_1 = tp.create_scenario(scenario_cfg) + scenario_2 = tp.create_scenario(scenario_cfg) + + scenario_1.input.write(10) + scenario_2.input.write(8) + + scenario_1.submit() + scenario_2.submit() + + print(tp.compare_scenarios(scenario_1, scenario_2)) + + tp.Rest().run() +``` \ No newline at end of file diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_09/ReadMe.md b/docs/tutorials/complete_applications/scenario_management_overview/step_09/ReadMe.md deleted file mode 100644 index 3d2fe5643..000000000 --- a/docs/tutorials/complete_applications/scenario_management_overview/step_09/ReadMe.md +++ /dev/null @@ -1,30 +0,0 @@ -> You can download the code of this step [here](../src/step_09.py) or all the steps [here](https://github.com/Avaiga/taipy-getting-started-core/tree/develop/src). - -# Step 9: Scenario subscription - -This step reuses the configuration provided in step 7 except for the scenario configuration. To have an action after changing a job status, we can [subscribe a function](https://docs.taipy.io/en/latest/manuals/core/entities/scheduling-and-job-execution/#subscribe-to-job-execution) to a scenario. A status change will call this function. This feature allows the creation of logs or particular events for Taipy GUI. - -```python -def callback_scenario(scenario, job): - """All the scenarios are subscribed to the callback_scenario_state function. It means whenever a job is done, it is called. - - Args: - scenario (Scenario): the scenario of the job changed - job (_type_): the job that has its status changed - """ - print("Name:", scenario.name) - if job.status.value == 7: - for data_node in job.task.output.values(): - print(data_node.read()) - -``` - -A scenario can then subscribe to this callback. - -```python -scenario = tp.create_scenarios(scenario_cfg) - -scenario.subscribe(scenario_cfg) - -scenario.submit() -``` diff --git a/docs/tutorials/complete_applications/scenario_management_overview/step_09/step_09.md b/docs/tutorials/complete_applications/scenario_management_overview/step_09/step_09.md new file mode 100644 index 000000000..8bf22f77e --- /dev/null +++ b/docs/tutorials/complete_applications/scenario_management_overview/step_09/step_09.md @@ -0,0 +1,35 @@ +> You can download the code for +Step 9 +or all the steps here. + +# Subscribing to a scenario + +*Time to complete: 15 minutes; Level: Advanced* + +To have an action after changing a job status, we can [subscribe a function](../../../../manuals/core/entities/orchestrating-and-job-execution.md/#subscribe-to-job-execution) to a scenario. A status change calls this function. This feature allows the creation of logs or particular events for Taipy GUI. + +```python +def callback_scenario_state(scenario, job): + """All the scenarios are subscribed to the callback_scenario_state function. It means whenever a job is done, it is called. + Depending on the job and the status, it will update the message stored in a json that is then displayed on the GUI. + + Args: + scenario (Scenario): the scenario of the job changed + job (_type_): the job that has its status changed + """ + print(scenario.name) + if job.status == tp.core.Status.COMPLETED: + for data_node in job.task.output.values(): + print(data_node.read()) + +``` + +A scenario can then subscribe to this callback. + +```python +scenario = tp.create_scenarios(scenario_cfg) + +scenario.subscribe(scenario_cfg) + +scenario.submit() +```