From a8e7a2700c6cf1c1dfe74fef8b3a334d701215c5 Mon Sep 17 00:00:00 2001 From: Hahnbee Lee <55263191+hahnbeelee@users.noreply.github.com> Date: Mon, 31 Jul 2023 14:26:30 -0700 Subject: [PATCH 01/61] working --- .gitignore | 2 + nbs/_extensions/mintlify/_extension.yml | 29 +++++ nbs/_extensions/mintlify/mintlify.lua | 53 ++++++++ .../mintlify/mintlify_renderers.lua | 22 ++++ nbs/_extensions/mintlify/mintlify_utils.lua | 33 +++++ nbs/_extensions/mintlify/mintlify_writer.lua | 113 ++++++++++++++++++ nbs/_quarto.yml | 14 +-- 7 files changed, 257 insertions(+), 9 deletions(-) create mode 100644 nbs/_extensions/mintlify/_extension.yml create mode 100644 nbs/_extensions/mintlify/mintlify.lua create mode 100644 nbs/_extensions/mintlify/mintlify_renderers.lua create mode 100644 nbs/_extensions/mintlify/mintlify_utils.lua create mode 100644 nbs/_extensions/mintlify/mintlify_writer.lua diff --git a/.gitignore b/.gitignore index 44f997cf7..0ba7ed1d9 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,5 @@ sidebar.yml nbs/.last_checked .venv .idea + +/.luarc.json diff --git a/nbs/_extensions/mintlify/_extension.yml b/nbs/_extensions/mintlify/_extension.yml new file mode 100644 index 000000000..d8b187db4 --- /dev/null +++ b/nbs/_extensions/mintlify/_extension.yml @@ -0,0 +1,29 @@ +title: Mintlify +author: Mintlify, Inc +organization: Mintlify +contributes: + project: + project: + type: default + detect: + - ["mint.json"] + render: + - "**/*.qmd" + - "**/*.ipynb" + format: mintlify-md + formats: + md: + # Although we use a custom writer, we still need the variants here the lua filters to render correctly. + # Ideally, we would forward the variants to the custom writer. + variant: gfm+pipe_tables+tex_math_dollars+header_attributes+raw_html+all_symbols_escapable+backtick_code_blocks+fenced_code_blocks+space_in_atx_header+intraword_underscores+lists_without_preceding_blankline+shortcut_reference_links + writer: mintlify_writer.lua + output-ext: mdx + inline-includes: true + preserve-yaml: true + wrap: none + fig-format: retina + fig-width: 8 + fig-height: 5 + html-math-method: webtex + filters: + - mintlify.lua diff --git a/nbs/_extensions/mintlify/mintlify.lua b/nbs/_extensions/mintlify/mintlify.lua new file mode 100644 index 000000000..bbe60a9f1 --- /dev/null +++ b/nbs/_extensions/mintlify/mintlify.lua @@ -0,0 +1,53 @@ +-- mintlify.lua + +local kQuartoRawHtml = "quartoRawHtml" +local rawHtmlVars = pandoc.List() + +function Pandoc(doc) + -- insert exports at the top if we have them + if #rawHtmlVars > 0 then + local exports = ("export const %s =\n[%s];"):format(kQuartoRawHtml, + table.concat( + rawHtmlVars:map(function(var) return '`'.. var .. '`' end), + "," + ) + ) + doc.blocks:insert(1, pandoc.RawBlock("markdown", exports .. "\n")) + end + + return doc +end + + +-- strip image attributes (which may result from +-- fig-format: retina) as they will result in an +-- img tag which won't hit the asset pipeline +function Image(el) + el.attr = pandoc.Attr() + return el +end + +-- header attributes only support id +function Header(el) + el.attr = pandoc.Attr(el.identifier) + return el +end + +-- transform 'mdx' into passthrough content, transform 'html' +-- into raw commamark to pass through via dangerouslySetInnerHTML +function RawBlock(el) + if el.format == 'mdx' then + return pandoc.CodeBlock(el.text, pandoc.Attr("", {"mdx-code-block"})) + elseif el.format == 'html' then + -- track the raw html vars (we'll insert them at the top later on as + -- mdx requires all exports be declared together) + local html = string.gsub(el.text, "\n+", "\n") + rawHtmlVars:insert(html) + + -- generate a div container for the raw html and return it as the block + local html = ("
") + :format(kQuartoRawHtml, #rawHtmlVars-1) .. "\n" + return pandoc.RawBlock("html", html) + end +end + diff --git a/nbs/_extensions/mintlify/mintlify_renderers.lua b/nbs/_extensions/mintlify/mintlify_renderers.lua new file mode 100644 index 000000000..029b3fbf1 --- /dev/null +++ b/nbs/_extensions/mintlify/mintlify_renderers.lua @@ -0,0 +1,22 @@ +local codeBlock = require('mintlify_utils').codeBlock + +-- print("Found me") +-- _quarto.ast.add_renderer("Callout", function() +-- return we_are_docusaurus -- detect docusaurus-md +-- end, function(node) +-- local admonition = pandoc.List() +-- admonition:insert(pandoc.RawBlock("markdown", "\n:::" .. node.type)) +-- if node.title then +-- admonition:insert(pandoc.Header(2, node.title)) +-- end +-- local content = node.content +-- if type(content) == "table" then +-- admonition:extend(content) +-- else +-- admonition:insert(content) +-- end +-- admonition:insert(pandoc.RawBlock("markdown", ":::\n")) +-- return admonition +-- end) + +return {} -- return an empty table as a hack to pretend we're a shortcode handler for now \ No newline at end of file diff --git a/nbs/_extensions/mintlify/mintlify_utils.lua b/nbs/_extensions/mintlify/mintlify_utils.lua new file mode 100644 index 000000000..ae076ddaa --- /dev/null +++ b/nbs/_extensions/mintlify/mintlify_utils.lua @@ -0,0 +1,33 @@ +function codeBlock(el, filename) + local lang = el.attr.classes[1] + local title = filename or el.attr.attributes["filename"] or el.attr.attributes["title"] + local showLineNumbers = el.attr.classes:includes('number-lines') + if lang or title or showLineNumbers then + if not lang then + lang = 'text' + end + local code = "\n```" .. lang + if showLineNumbers then + code = code .. " showLineNumbers" + end + if title then + code = code .. " title=\"" .. title .. "\"" + end + code = code .. "\n" .. el.text .. "\n```\n" + + -- docusaures code block attributes don't conform to any syntax + -- that pandoc natively understands, so return the CodeBlock as + -- "raw" markdown (so it bypasses pandoc processing entirely) + return pandoc.RawBlock("markdown", code) + + elseif #el.attr.classes == 0 then + el.attr.classes:insert('text') + return el + end + + return nil +end + +return { + codeBlock = codeBlock +} \ No newline at end of file diff --git a/nbs/_extensions/mintlify/mintlify_writer.lua b/nbs/_extensions/mintlify/mintlify_writer.lua new file mode 100644 index 000000000..daa7d7019 --- /dev/null +++ b/nbs/_extensions/mintlify/mintlify_writer.lua @@ -0,0 +1,113 @@ + +local codeBlock = require('mintlify_utils').codeBlock + + +local reactPreamble = pandoc.List() + +local function addPreamble(preamble) + if not reactPreamble:includes(preamble) then + reactPreamble:insert(preamble) + end +end + +local function jsx(content) + return pandoc.RawBlock("markdown", content) +end + +local function tabset(node, filter) + -- note groupId + local groupId = "" + local group = node.attr.attributes["group"] + if group then + groupId = ([[ groupId="%s"]]):format(group) + end + + -- create tabs + local tabs = pandoc.Div({}) + tabs.content:insert(jsx("ZPkOU+>0W4ufXG6h}g|HuAa4%lxYQxj4O-+eY|JW&R>C#Bl&2JK!hM94v0E z-HSV%_5==?$+}b!E)h_&=c@ehkBiprZJXo3470R#;^{;^xyhx2@fjqCxu2<&uKn;X z0rF6MDQD4&(B`OWtIp^}n8b0Q6ZRRR+$$y?1zRP0^=nsf z`c mpIt6oD3N5X%tGN<;7qc2?p0J`46}3wSsadH;&m84$6e3_c7AKsZDK1!#0Z| z)ha#6wuK3nu9#TS0rZ`pN}R^R{ulS3RyC9mcD@G*HU3O6-B`ITPd41EvYg&mCs8_E zan2n*?R>QpzRRtNSYe!91dcyc!5KV;@G `W8 zcQBu^?6@EyXbw|w+`(Bxo}E+mTOJ!Ys?vc|4JlGNAG QWeszI`A`nBoN3t2>5&6 z>7{SCZ>~2&`qe_tN`OH>jQ?co_R(gOBTyQIkBc%(o2lOpz^J& P3tX!zy z4|DStV|8sWq4PJMex?Mcrq&9o#_?%c0*$lOx_h-YyS?2ojSXU0Bm~?nQY@NtU8Qx7 z&SpOIFb*syw5U>VdWn81!LuDds4&vc@Go>ISK5eIAszN+)D~aHLh`Nzde*=TCMFaB zYfGDj{X{@in;%rOrf>Ej_Y1>tp~$MuSdJWe*dXKY%DmSZKLS|h+-Hvq>R28GJFO9$ z+U(BuV`*$vgu~Y3;j+n-t3!>?+)pAvUms;dLhXu3yIYNA$nHYK(d7f1`0GOF_?%K| zB4N2(FIsWq(*B|cAQn~*ea$`Ra>JA)Y4=!XK(39Q0v*_q0^7$kopid26dPW5=V2#$ zoWe1-23Xwd%RJNFD~`IPDOySj;gWL6*iLrIp|ldf_yde@s0=}3v!N+7GuAjU*l0M0 z+XuHUncvTyn4Z1Yp#T416kwbQ-b3}m`*3^27+AVfb8wf?29jWE-u7?{Wgydh)%c9d zYWxRrS`)F&6lgkmw|()v2Nf3kujZXBpM7Bf+}SWc jZZ zrL2cDh37lVL(7B`ro|R9_(B4uaZWg!ug)Urj_sIa?6vt8O+-da@45Wk={cB@UYRhO zb-7ARBhI)#3uQn@eI{jH!FwJ~V*?T7#FuVm^!JA}CxCQN{9VX3Wp2u=ai8Np|L&0* zHwC7~PVjG=_~UY{=BQ}}CrGg{YTG<7icy|xk>MUR6g*4vD$=#BX*x1oGC!C@Cu~|h z0JGw 05!BFGB^l zE#U_{>xqF_3&tx;2v_!Hr5SoCdgmv#MMtlykwHWx#%flceMkUgxOj8dy?GL(!?pYA zCx-QpCoTB5{rsuM!UE7;YZJ+*K7YA*?t2K?U0~LLTFIA>6M ko^ZHymzAA#b6T`xz}OKLMv4}aVY0#xKhkpsJZ6Mxo{o(gA`Q# z3)=^Yt $X^EVb0;qY3T?RcJlgAWhXe2;Ms3MI{!SzSQyawai4-lo|1U{L<$Z z$%p YZO#QHgF2NB0nJSr3<7BXo-@oktpfcRE&X^d_hE|Nd z!DmpAu0w3~4=p}MzLvtfx7<$U@~R&*>tNYP9t?kXOE(}_a#o3MC(#C$KSdVrt|$~T zEdOCf+z>M~HnrBe
S8(1^wQLq5 z#(8?(U^DVBiC8|At;XwgJOOU6YRILO(SFE_1i$4|Op6pa^U<5B-b~3SBFKkpQgE}s zrn?UY)l--NA;@$7zr3UCrv{LMv-qT@;WFA~IRXljZ0syNTv%r X?^ m$&ym*$d% Date: Tue, 10 Oct 2023 10:57:56 -0700 Subject: [PATCH 38/61] add final formatting script --- .github/workflows/build-docs.yaml | 8 +++++++- final-formatting.bash | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index 459afb3a8..1eefc3ad3 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -20,9 +20,15 @@ jobs: pip install -Uq nbdev test -f setup.py && pip install -e ".[dev]" nbdev_docs - - name: Copy over mint.json + - name: Apply final formats + shell: bash + run: bash final-formatting.bash + - name: Copy over necessary assets run: | cp nbs/mint.json _docs/mint.json + cp nbs/imgs/logo/dark.png _docs/imgs/logo/dark.png + cp nbs/imgs/logo/light.png _docs/imgs/logo/light.png + cp nbs/favicon.svg _docs/favicon.svg - name: Deploy to Mintlify Docs uses: peaceiris/actions-gh-pages@v3 with: diff --git a/final-formatting.bash b/final-formatting.bash index 81fd23bbd..6af1bc1cc 100644 --- a/final-formatting.bash +++ b/final-formatting.bash @@ -1,6 +1,6 @@ #!/usr/bin/env bash -for file in $(find mintlify -type f -name "*mdx"); do +for file in $(find _docs -type f -name "*mdx"); do sed -i '' -e s/'style="float:right; font-size:smaller"'/'style={{ float: "right", fontSize: "smaller" }}'/g $file sed -i '' -e s/'
'/'
'/g $file done \ No newline at end of file From b58e816806aae9251046cba864b0f891990918f7 Mon Sep 17 00:00:00 2001 From: Hahnbee Lee <55263191+hahnbeelee@users.noreply.github.com> Date: Tue, 10 Oct 2023 12:20:04 -0700 Subject: [PATCH 39/61] echo file --- final-formatting.bash | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/final-formatting.bash b/final-formatting.bash index 6af1bc1cc..ec642bfa5 100644 --- a/final-formatting.bash +++ b/final-formatting.bash @@ -1,6 +1,7 @@ #!/usr/bin/env bash for file in $(find _docs -type f -name "*mdx"); do - sed -i '' -e s/'style="float:right; font-size:smaller"'/'style={{ float: "right", fontSize: "smaller" }}'/g $file - sed -i '' -e s/'
'/'
'/g $file + echo ${file} + sed -i '' -e 's/style="float:right; font-size:smaller"/style={{ float: "right", fontSize: "smaller" }}/g' $file + sed -i '' -e 's/
/
/g' $file done \ No newline at end of file From 20b961bd183cf2d0572dc27c9bcf32985d8f3a83 Mon Sep 17 00:00:00 2001 From: Hahnbee Lee <55263191+hahnbeelee@users.noreply.github.com> Date: Tue, 10 Oct 2023 12:41:28 -0700 Subject: [PATCH 40/61] add ostype if else --- final-formatting.bash | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/final-formatting.bash b/final-formatting.bash index ec642bfa5..451850326 100644 --- a/final-formatting.bash +++ b/final-formatting.bash @@ -1,7 +1,11 @@ #!/usr/bin/env bash for file in $(find _docs -type f -name "*mdx"); do - echo ${file} - sed -i '' -e 's/style="float:right; font-size:smaller"/style={{ float: "right", fontSize: "smaller" }}/g' $file - sed -i '' -e 's/
/
/g' $file + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' -e 's/style="float:right; font-size:smaller"/style={{ float: "right", fontSize: "smaller" }}/g' $file + sed -i '' -e 's/
/
/g' $file + else + sed -i -e 's/style="float:right; font-size:smaller"/style={{ float: "right", fontSize: "smaller" }}/g' $file + sed -i -e 's/
/
/g' $file + fi done \ No newline at end of file From ec0fbe96e76bfe03943fe513a296175b7a49d654 Mon Sep 17 00:00:00 2001 From: Hahnbee Lee <55263191+hahnbeelee@users.noreply.github.com> Date: Tue, 10 Oct 2023 13:04:13 -0700 Subject: [PATCH 41/61] dont put logos in folder --- .github/workflows/build-docs.yaml | 4 ++-- nbs/mint.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index 1eefc3ad3..fe5a241b2 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -26,8 +26,8 @@ jobs: - name: Copy over necessary assets run: | cp nbs/mint.json _docs/mint.json - cp nbs/imgs/logo/dark.png _docs/imgs/logo/dark.png - cp nbs/imgs/logo/light.png _docs/imgs/logo/light.png + cp nbs/imgs/logo/dark.png _docs/dark.png + cp nbs/imgs/logo/light.png _docs/light.png cp nbs/favicon.svg _docs/favicon.svg - name: Deploy to Mintlify Docs uses: peaceiris/actions-gh-pages@v3 diff --git a/nbs/mint.json b/nbs/mint.json index 341f7b473..9094e67a8 100644 --- a/nbs/mint.json +++ b/nbs/mint.json @@ -2,8 +2,8 @@ "$schema": "https://mintlify.com/schema.json", "name": "Nixtla", "logo": { - "light": "/logo/light.png", - "dark": "/logo/dark.png" + "light": "/light.png", + "dark": "/dark.png" }, "favicon": "/favicon.svg", "colors": { From 3069bedef3c8ee8db7a8f5a7083d389fe2d96b5e Mon Sep 17 00:00:00 2001 From: Hahnbee Lee <55263191+hahnbeelee@users.noreply.github.com> Date: Tue, 10 Oct 2023 13:13:24 -0700 Subject: [PATCH 42/61] remove index.html --- .github/workflows/build-docs.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index fe5a241b2..9a608fc0a 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -29,6 +29,7 @@ jobs: cp nbs/imgs/logo/dark.png _docs/dark.png cp nbs/imgs/logo/light.png _docs/light.png cp nbs/favicon.svg _docs/favicon.svg + rm _docs/index.html - name: Deploy to Mintlify Docs uses: peaceiris/actions-gh-pages@v3 with: From 3ae38c2cc1cb6e811790e247603b519ca8ddb7ad Mon Sep 17 00:00:00 2001 From: Hahnbee Lee <55263191+hahnbeelee@users.noreply.github.com> Date: Tue, 10 Oct 2023 13:26:46 -0700 Subject: [PATCH 43/61] uses: actions/checkout@v3 --- .github/workflows/build-docs.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index 9a608fc0a..72637f7a9 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -24,6 +24,7 @@ jobs: shell: bash run: bash final-formatting.bash - name: Copy over necessary assets + uses: actions/checkout@v3 run: | cp nbs/mint.json _docs/mint.json cp nbs/imgs/logo/dark.png _docs/dark.png From 03daa70e90b00cad2237b0a7b09e9ef2de618b28 Mon Sep 17 00:00:00 2001 From: Hahnbee Lee <55263191+hahnbeelee@users.noreply.github.com> Date: Tue, 10 Oct 2023 13:49:17 -0700 Subject: [PATCH 44/61] delete with bash --- .github/workflows/build-docs.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index 72637f7a9..e0e920f16 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -24,13 +24,14 @@ jobs: shell: bash run: bash final-formatting.bash - name: Copy over necessary assets - uses: actions/checkout@v3 run: | cp nbs/mint.json _docs/mint.json cp nbs/imgs/logo/dark.png _docs/dark.png cp nbs/imgs/logo/light.png _docs/light.png cp nbs/favicon.svg _docs/favicon.svg - rm _docs/index.html + - name: Delete index.html + shell: bash + run: rm _docs/index.html - name: Deploy to Mintlify Docs uses: peaceiris/actions-gh-pages@v3 with: From 0075a2786423970b570fa4293af9595b62b55b5e Mon Sep 17 00:00:00 2001 From: Hahnbee Lee <55263191+hahnbeelee@users.noreply.github.com> Date: Tue, 10 Oct 2023 14:01:14 -0700 Subject: [PATCH 45/61] rm -f --- .github/workflows/build-docs.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index e0e920f16..94e8d2a57 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -29,9 +29,7 @@ jobs: cp nbs/imgs/logo/dark.png _docs/dark.png cp nbs/imgs/logo/light.png _docs/light.png cp nbs/favicon.svg _docs/favicon.svg - - name: Delete index.html - shell: bash - run: rm _docs/index.html + rm -f _docs/index.html - name: Deploy to Mintlify Docs uses: peaceiris/actions-gh-pages@v3 with: From 9b0cc99cf886036af637dec3f4e9de0faaa4fe1a Mon Sep 17 00:00:00 2001 From: Hahnbee Lee <55263191+hahnbeelee@users.noreply.github.com> Date: Tue, 10 Oct 2023 15:42:44 -0700 Subject: [PATCH 46/61] fix formatting errors in models pages --- nbs/docs/models/ARCH.ipynb | 52 ++++++++++--------- nbs/docs/models/ARIMA.ipynb | 4 +- nbs/docs/models/AutoCES.ipynb | 4 +- nbs/docs/models/AutoETS.ipynb | 2 +- nbs/docs/models/AutoTheta.ipynb | 6 +-- nbs/docs/models/Holt.ipynb | 2 +- nbs/docs/models/OptimizedTheta.ipynb | 6 +-- .../models/SeasonalExponentialSmoothing.ipynb | 4 +- nbs/mint.json | 31 +++++++++++ nbs/src/core/distributed.fugue.ipynb | 6 ++- 10 files changed, 80 insertions(+), 37 deletions(-) diff --git a/nbs/docs/models/ARCH.ipynb b/nbs/docs/models/ARCH.ipynb index 090c71f23..ea36d32bb 100644 --- a/nbs/docs/models/ARCH.ipynb +++ b/nbs/docs/models/ARCH.ipynb @@ -213,7 +213,9 @@ "source": [ "## Loading libraries and data \n", "\n", - ":::{.callout-tip} Statsforecast will be needed. To install, see [instructions](../getting-started/0_Installation.ipynb). :::\n", + ":::{.callout-tip}\n", + "Statsforecast will be needed. To install, see [instructions](../getting-started/0_Installation.ipynb).\n", + ":::\n", "\n", "Next, we import plotting libraries and configure the plotting style." ] @@ -12889,7 +12891,7 @@ 0.11683902533544767, 0.18038662130227442, 1.1396760668737118, - 8.429606751246858e-06, + 0.000008429606751246858, 0.9301650273653356, 0.16603494698002158, 0.02552244687162859, @@ -13006,7 +13008,7 @@ 0.333507961464413, 1.5341682132027463, 0.535647628131223, - 8.047187854454163e-06, + 0.000008047187854454163, 0.05159803214177818, 0.07600424912094962, 0.05061172231156831, @@ -13146,7 +13148,7 @@ 2.7279986776819762, 2.7160487251081724, 0.21768883267417796, - 6.77720693099992e-06, + 0.00000677720693099992, 2.0892382083596366, 1.5511137261921708, 0.19711705562956672, @@ -13190,7 +13192,7 @@ 0.09514048933694128, 0.005799502263676435, 0.26977917189300543, - 2.2905689893454364e-05, + 0.000022905689893454364, 0.032835101620127545, 0.035071983113154785, 0.02720364389284937, @@ -13282,7 +13284,7 @@ 0.2733247895916533, 0.03816868105362628, 0.05644730956949203, - 1.7126891073291785e-05, + 0.000017126891073291785, 0.17648748135786346, 0.08890408218010715, 0.00021428585381320998, @@ -13293,7 +13295,7 @@ 0.0034536384504556326, 1.0219740565421616, 0.14230208866334162, - 3.4607522944888557e-06, + 0.0000034607522944888557, 0.0008948379096681811, 1.1918442949862227, 0.4224720090152985, @@ -13317,7 +13319,7 @@ 0.379505710351215, 0.04804736114077823, 0.018926161782214495, - 7.079826049627675e-05, + 0.00007079826049627675, 0.2256097560481151, 0.14422736286851592, 0.03029031934041486, @@ -13452,7 +13454,7 @@ 0.016163575341260606, 0.0033884362508481143, 0.16717428315038643, - 1.4022086968800128e-05, + 0.000014022086968800128, 0.010511348063911363, 0.012782595072851783, 0.04677744379099467, @@ -13500,7 +13502,7 @@ 0.5337190473107196, 0.03514066158205324, 0.21841633296069093, - 2.799770311426146e-05, + 0.00002799770311426146, 0.0035743299293066215, 0.2886525495692123, 0.0002361118071194596, @@ -13550,7 +13552,7 @@ 0.09277613223137564, 0.004196366830944074, 0.04937508180038409, - 5.208049534825782e-05, + 0.00005208049534825782, 0.16688400504491227, 0.014510991850446027, 0.13727838266375458, @@ -13693,7 +13695,7 @@ 0.006911690943276298, 0.3278850494791402, 0.7287238222344438, - 3.161982797127493e-05, + 0.00003161982797127493, 1.7903942515655977, 0.033747867911173186, 1.0887262880763404, @@ -13804,7 +13806,7 @@ 0.017032753347700658, 0.10819350754652532, 0.07635754962107597, - 4.720076651680163e-07, + 4.720076651680163e-7, 0.13257647932461017, 0.0015736305321550584, 0.005062602892380193, @@ -13859,7 +13861,7 @@ 0.0003997208956144086, 3.6430248324576744, 4.315374983468133, - 7.465081431494341e-05, + 0.00007465081431494341, 2.3702802404040986, 2.4875933720473613, 4.238751501049985, @@ -13930,14 +13932,14 @@ 0.12884377091778848, 0.45350527664342116, 1.3383250835766, - 3.047038069794671e-06, + 0.000003047038069794671, 0.046155230627765706, 0.04345704527385812, 0.21496506713259997, 0.010971728644473754, 0.3681449089203887, 0.12095591183388035, - 1.4533571009694057e-05, + 0.000014533571009694057, 0.43683167649436533, 0.003961054815055465, 0.002594457624136788, @@ -14040,7 +14042,7 @@ 1.1755067590686328, 1.692552536701068, 0.008292017842472079, - 8.837910181512196e-05, + 0.00008837910181512196, 0.0010388011063882155, 0.52268289783404, 0.08289521198197039, @@ -14048,9 +14050,9 @@ 0.09831904474102832, 0.06665444896152177, 0.0011743773216012492, - 3.989948937286202e-06, + 0.000003989948937286202, 0.23966670389611294, - 9.396568391014351e-05, + 0.00009396568391014351, 0.7083530264126577, 0.379280036868932, 0.05899634912283012, @@ -14108,7 +14110,7 @@ 0.012032641276976222, 0.08457382662710584, 0.73534494099483, - 5.26813972937628e-05, + 0.0000526813972937628, 0.5109083285028833, 0.0011242101166246262, 0.0018688345123409381, @@ -14117,7 +14119,7 @@ 0.0075020470243941095, 0.00038200004553110315, 0.26298092501994424, - 1.1549731265675906e-05, + 0.000011549731265675906, 0.33417910089435754, 0.0867904320408933, 0.7020433764156192, @@ -14592,7 +14594,7 @@ 0.6766417031004891, 0.0030353502921928455, 0.52166759677021, - 1.1534388436087901e-06, + 0.0000011534388436087901, 0.1494000082288102, 0.06768454071199759, 0.11456736834367175, @@ -14943,13 +14945,13 @@ 0.06211911053832683, 0.12810408947533514, 0.009926192984207037, - 1.7100299484364275e-05, + 0.000017100299484364275, 0.17097265655211852, 1.7589894800913939, 0.042823064448460374, 0.10930672666497082, 0.007314017675982816, - 7.100057638853501e-05, + 0.00007100057638853501, 0.3543283102780241, 0.00815750397918031, 0.00725186857060821, @@ -14977,7 +14979,7 @@ 0.5356191175456438, 0.7669523057389738, 1.7027866477021951, - 2.756746937148935e-06, + 0.000002756746937148935, 0.3731529145352457, 0.9711025783145061, 2.1124949696707556, diff --git a/nbs/docs/models/ARIMA.ipynb b/nbs/docs/models/ARIMA.ipynb index f4854579e..91066e627 100644 --- a/nbs/docs/models/ARIMA.ipynb +++ b/nbs/docs/models/ARIMA.ipynb @@ -296,7 +296,9 @@ "source": [ "## Loading libraries and data \n", "\n", - ":::{.callout-tip} Statsforecast will be needed. To install, see [instructions](../getting-started/0_Installation.ipynb). :::\n", + ":::{.callout-tip}\n", + "Statsforecast will be needed. To install, see [instructions](../getting-started/0_Installation.ipynb). \n", + ":::\n", "\n", "Next, we import plotting libraries and configure the plotting style." ] diff --git a/nbs/docs/models/AutoCES.ipynb b/nbs/docs/models/AutoCES.ipynb index 4c36482af..3d1b8e5e3 100644 --- a/nbs/docs/models/AutoCES.ipynb +++ b/nbs/docs/models/AutoCES.ipynb @@ -197,7 +197,9 @@ "source": [ "## Loading libraries and data \n", "\n", - ":::{.callout-tip} Statsforecast will be needed. To install, see [instructions](../getting-started/0_Installation.ipynb). :::\n", + ":::{.callout-tip}\n", + "Statsforecast will be needed. To install, see [instructions](../getting-started/0_Installation.ipynb).\n", + ":::\n", "\n", "Next, we import plotting libraries and configure the plotting style." ] diff --git a/nbs/docs/models/AutoETS.ipynb b/nbs/docs/models/AutoETS.ipynb index 60b76ec3a..c42e4dd95 100644 --- a/nbs/docs/models/AutoETS.ipynb +++ b/nbs/docs/models/AutoETS.ipynb @@ -111,7 +111,7 @@ "\n", "$$s_{t} = \\gamma^*(1-\\alpha) (y_{t}-\\ell_{t-1}-b_{t-1})+ [1-\\gamma^*(1-\\alpha)]s_{t-m},$$\n", "\n", - "Thus, we obtain identical forecasts using this approach by replacing $\\gamma$ in (1c) with $\\gamma^{*} (1-\\alpha) $. The modification given in (1c) was proposed by Ord et al. (1997) to make the state space formulation simpler. It is equivalent to Archibaldβs (1990) variation of the Holt-Wintersβ method." + "Thus, we obtain identical forecasts using this approach by replacing $\\gamma$ in (1c) with $\\gamma^{*} (1-\\alpha)$. The modification given in (1c) was proposed by Ord et al. (1997) to make the state space formulation simpler. It is equivalent to Archibaldβs (1990) variation of the Holt-Wintersβ method." ] }, { diff --git a/nbs/docs/models/AutoTheta.ipynb b/nbs/docs/models/AutoTheta.ipynb index b7a66624d..e372091c3 100644 --- a/nbs/docs/models/AutoTheta.ipynb +++ b/nbs/docs/models/AutoTheta.ipynb @@ -148,13 +148,13 @@ "\n", "$$\\hat Y_{n+h|n} = (1-\\frac{1}{\\theta}) [\\text{A}_n+\\text{B}_n (n+h)]+ \\frac{1}{\\theta} \\tilde {\\text{Z}}_{n+h|n} (\\theta) \\tag 6$$\n", "\n", - "where $\\tilde {\\text{Z}}_{n+h|n} (\\theta)=\\tilde {\\text{Z}}_{n+1|n} (\\theta)=\\alpha \\sum_{i=0}^{n-1}(1-\\alpha)^i \\text{Z}_{n-i}(\\theta)+(1-\\alpha)^n \\ell_{0}^{*} $ is the extrapolation of $\\text{Z}_t(\\theta)$ by an SES model with $\\ell_{0}^{*} \\in \\mathbb{R}$ as the initial level parameter and $\\alpha \\in (0,1)$ as the smoothing parameter. Note that for $\\theta=2$ Eq. (6) corresponds to Step 4 of the STheta algorithm. After some algebra, we can write\n", + "where $\\tilde {\\text{Z}}_{n+h|n} (\\theta)=\\tilde {\\text{Z}}_{n+1|n} (\\theta)=\\alpha \\sum_{i=0}^{n-1}(1-\\alpha)^i \\text{Z}_{n-i}(\\theta)+(1-\\alpha)^n \\ell_{0}^{*}$ is the extrapolation of $\\text{Z}_t(\\theta)$ by an SES model with $\\ell_{0}^{*} \\in \\mathbb{R}$ as the initial level parameter and $\\alpha \\in (0,1)$ as the smoothing parameter. Note that for $\\theta=2$ Eq. (6) corresponds to Step 4 of the STheta algorithm. After some algebra, we can write\n", "\n", "$$\\tilde {\\text{Z}}_{n+1|n} (\\theta)=\\theta \\ell{n}+(1-\\theta) \\{ \\text{A}_n [1-(1-\\alpha)^n] + \\text{B}_n [n+(1-\\frac{1}{\\alpha}) [1-(1-\\alpha)^n] ] \\} \\tag 7$$\n", "\n", - "where $\\ell_{t}=\\alpha Y_t +(1-\\alpha) \\ell_{t-1} $ for $t=1, \\cdots, n$ and $\\ell_{0}=\\ell_{0}^{*}/\\theta$.\n", + "where $\\ell_{t}=\\alpha Y_t +(1-\\alpha) \\ell_{t-1}$ for $t=1, \\cdots, n$ and $\\ell_{0}=\\ell_{0}^{*}/\\theta$.\n", "\n", - "In the light of Eqs. (6), (7), we suggest four stochastic approaches. These approaches differ due to the parameter $\\theta$ which may be either fixed at two or optimised, and the coefficients $\\text{A}_n$ and $\\text{B}_n$, which can be either fixed or dynamic functions. To formulate the state space models, it is helpful to adopt $\\mu_{t}$ as the one-step-ahead forecast at origin $t-1$ and $\\varepsilon_{t} $ as the respective additive error, i.e., $\\varepsilon_{t}=Y_t - \\mu_{t} $ if $\\mu_{t}= \\hat Y_{t|t-1} $. We assume $\\{ \\varepsilon_{t} \\} $ to be a Gaussian white noise process with mean zero and variance $\\sigma^2$. " + "In the light of Eqs. (6), (7), we suggest four stochastic approaches. These approaches differ due to the parameter $\\theta$ which may be either fixed at two or optimised, and the coefficients $\\text{A}_n$ and $\\text{B}_n$, which can be either fixed or dynamic functions. To formulate the state space models, it is helpful to adopt $\\mu_{t}$ as the one-step-ahead forecast at origin $t-1$ and $\\varepsilon_{t}$ as the respective additive error, i.e., $\\varepsilon_{t}=Y_t - \\mu_{t}$ if $\\mu_{t}= \\hat Y_{t|t-1}$. We assume $\\{ \\varepsilon_{t} \\}$ to be a Gaussian white noise process with mean zero and variance $\\sigma^2$. " ] }, { diff --git a/nbs/docs/models/Holt.ipynb b/nbs/docs/models/Holt.ipynb index 065900df9..1d961204c 100644 --- a/nbs/docs/models/Holt.ipynb +++ b/nbs/docs/models/Holt.ipynb @@ -112,7 +112,7 @@ "\n", "For each method there exist two models: one with additive errors and one with multiplicative errors. The point forecasts produced by the models are identical if they use the same smoothing parameter values. They will, however, generate different prediction intervals.\n", "\n", - "To distinguish between a model with additive errors and one with multiplicative errors. We label each state space model as ETS( .,.,.) for (Error, Trend, Seasonal). This label can also be thought of as ExponenTial Smoothing. Using the same notation as in Table 7.5, the possibilities for each component are: Error ={A,M } , Trend ={ N,A,A d} and Seasonal ={ N,A,M }\n", + "To distinguish between a model with additive errors and one with multiplicative errors. We label each state space model as ETS( .,.,.) for (Error, Trend, Seasonal). This label can also be thought of as ExponenTial Smoothing. Using the same notation as in Table 7.5, the possibilities for each component are: Error =\\\\{A,M } , Trend =\\\\{ N,A,A d} and Seasonal =\\\\{ N,A,M }\n", "\n", "For our case, the linear Holt model with a trend, we are going to see two cases, both for the additive and the multiplicative\n", "\n", diff --git a/nbs/docs/models/OptimizedTheta.ipynb b/nbs/docs/models/OptimizedTheta.ipynb index dc4dd7c6c..34e0434d6 100644 --- a/nbs/docs/models/OptimizedTheta.ipynb +++ b/nbs/docs/models/OptimizedTheta.ipynb @@ -127,13 +127,13 @@ "\n", "$$\\hat Y_{n+h|n} = (1-\\frac{1}{\\theta}) [\\text{A}_n+\\text{B}_n (n+h)]+ \\frac{1}{\\theta} \\tilde {\\text{Z}}_{n+h|n} (\\theta) \\tag 3$$\n", "\n", - "where $\\tilde {\\text{Z}}_{n+h|n} (\\theta)=\\tilde {\\text{Z}}_{n+1|n} (\\theta)=\\alpha \\sum_{i=0}^{n-1}(1-\\alpha)^i \\text{Z}_{n-i}(\\theta)+(1-\\alpha)^n \\ell_{0}^{*} $ is the extrapolation of $\\text{Z}_t(\\theta)$ by an SES model with $\\ell_{0}^{*} \\in \\mathbb{R}$ as the initial level parameter and $\\alpha \\in (0,1)$ as the smoothing parameter. Note that for $\\theta=2$ Eq. (3) corresponds to Step 4 of the STheta algorithm. After some algebra, we can write\n", + "where $\\tilde {\\text{Z}}_{n+h|n} (\\theta)=\\tilde {\\text{Z}}_{n+1|n} (\\theta)=\\alpha \\sum_{i=0}^{n-1}(1-\\alpha)^i \\text{Z}_{n-i}(\\theta)+(1-\\alpha)^n \\ell_{0}^{*}$ is the extrapolation of $\\text{Z}_t(\\theta)$ by an SES model with $\\ell_{0}^{*} \\in \\mathbb{R}$ as the initial level parameter and $\\alpha \\in (0,1)$ as the smoothing parameter. Note that for $\\theta=2$ Eq. (3) corresponds to Step 4 of the STheta algorithm. After some algebra, we can write\n", "\n", "$$\\tilde {\\text{Z}}_{n+1|n} (\\theta)=\\theta \\ell{n}+(1-\\theta) \\{ \\text{A}_n [1-(1-\\alpha)^n] + \\text{B}_n [n+(1-\\frac{1}{\\alpha}) [1-(1-\\alpha)^n] ] \\} \\tag 4$$\n", "\n", "where $\\ell_{t}=\\alpha Y_t +(1-\\alpha) \\ell_{t-1} $ for $t=1, \\cdots, n$ and $\\ell_{0}=\\ell_{0}^{*}/\\theta$.\n", "\n", - "In the light of Eqs. (3), (4), we suggest four stochastic approaches. These approaches differ due to the parameter $\\theta$ which may be either fixed at two or optimised, and the coefficients $\\text{A}_n$ and $\\text{B}_n$, which can be either fixed or dynamic functions. To formulate the state space models, it is helpful to adopt $\\mu_{t}$ as the one-step-ahead forecast at origin $t-1$ and $\\varepsilon_{t} $ as the respective additive error, i.e., $\\varepsilon_{t}=Y_t - \\mu_{t} $ if $\\mu_{t}= \\hat Y_{t|t-1} $. We assume $\\{ \\varepsilon_{t} \\} $ to be a Gaussian white noise process with mean zero and variance $\\sigma^2$. " + "In the light of Eqs. (3), (4), we suggest four stochastic approaches. These approaches differ due to the parameter $\\theta$ which may be either fixed at two or optimised, and the coefficients $\\text{A}_n$ and $\\text{B}_n$, which can be either fixed or dynamic functions. To formulate the state space models, it is helpful to adopt $\\mu_{t}$ as the one-step-ahead forecast at origin $t-1$ and $\\varepsilon_{t}$ as the respective additive error, i.e., $\\varepsilon_{t}=Y_t - \\mu_{t}$ if $\\mu_{t}= \\hat Y_{t|t-1}$. We assume $\\{ \\varepsilon_{t} \\}$ to be a Gaussian white noise process with mean zero and variance $\\sigma^2$. " ] }, { @@ -161,7 +161,7 @@ "\n", "For $\\theta=2$ OTM reproduces the forecasts of the STheta method; hereafter, we will refer to this particular case as the standard Theta model (STM). \n", "\n", - "**Theorem 2:** The SES-d $(\\ell_{0}^{**}, \\alpha, b)$ model, where $\\ell_{0}^{**} \\in \\mathbb{R}, \\alpha \\in (0,1) $ and $b \\in \\mathbb{R} $ is equivalent to $\\text{OTM} (\\ell_{0}, \\alpha, \\theta )$ where $\\ell_{0} \\in \\mathbb{R}$ and $\\theta \\geq 1$, if \n", + "**Theorem 2:** The SES-d $(\\ell_{0}^{**}, \\alpha, b)$ model, where $\\ell_{0}^{**} \\in \\mathbb{R}, \\alpha \\in (0,1)$ and $b \\in \\mathbb{R}$ is equivalent to $\\text{OTM} (\\ell_{0}, \\alpha, \\theta )$ where $\\ell_{0} \\in \\mathbb{R}$ and $\\theta \\geq 1$, if \n", "\n", "$$\\ell_{0}^{**} = \\ell_{0} + (1- \\frac{1}{\\theta} )A_n \\ \\ and \\ \\ b=(1-\\frac{1}{\\theta} )B_n $$ \n", "\n", diff --git a/nbs/docs/models/SeasonalExponentialSmoothing.ipynb b/nbs/docs/models/SeasonalExponentialSmoothing.ipynb index dcea25030..2dd9bae47 100644 --- a/nbs/docs/models/SeasonalExponentialSmoothing.ipynb +++ b/nbs/docs/models/SeasonalExponentialSmoothing.ipynb @@ -146,7 +146,9 @@ "source": [ "## Loading libraries and data \n", "\n", - ":::{.callout-tip} Statsforecast will be needed. To install, see [instructions](../getting-started/0_Installation.ipynb). :::\n", + ":::{.callout-tip}\n", + "Statsforecast will be needed. To install, see [instructions](../getting-started/0_Installation.ipynb).\n", + ":::\n", "\n", "Next, we import plotting libraries and configure the plotting style." ] diff --git a/nbs/mint.json b/nbs/mint.json index 9094e67a8..1698063c4 100644 --- a/nbs/mint.json +++ b/nbs/mint.json @@ -62,11 +62,42 @@ "docs/how-to-guides/exogenous.html", "docs/how-to-guides/getting_started_complete_polars.html", "docs/how-to-guides/migrating_R", + "docs/how-to-guides/numba_cache.html", "docs/how-to-guides/prophet_spark_m5.html", "docs/how-to-guides/ray.html", "docs/how-to-guides/spark.html" ] }, + { + "group": "Model References", + "pages": [ + "docs/models/adida.html", + "docs/models/arch.html", + "docs/models/arima.html", + "docs/models/autoarima.html", + "docs/models/autoces.html", + "docs/models/autoets.html", + "docs/models/autoregressive.html", + "docs/models/autotheta.html", + "docs/models/crostonclassic.html", + "docs/models/crostonoptimized.html", + "docs/models/crostonsba.html", + "docs/models/dynamicoptimizedtheta.html", + "docs/models/dynamicstandardtheta.html", + "docs/models/garch.html", + "docs/models/holt.html", + "docs/models/holtwinters.html", + "docs/models/imapa.html", + "docs/models/multipleseasonaltrend.html", + "docs/models/optimizedtheta.html", + "docs/models/seasonalexponentialsmoothing.html", + "docs/models/seasonalexponentialsmoothingoptimized.html", + "docs/models/simpleexponentialoptimized.html", + "docs/models/simpleexponentialsmoothing.html", + "docs/models/standardtheta.html", + "docs/models/tsb.html" + ] + }, { "group": "API Reference", "pages": [ diff --git a/nbs/src/core/distributed.fugue.ipynb b/nbs/src/core/distributed.fugue.ipynb index 0f1a6f892..bc7ea0a38 100644 --- a/nbs/src/core/distributed.fugue.ipynb +++ b/nbs/src/core/distributed.fugue.ipynb @@ -29,7 +29,11 @@ "source": [ "# FugueBackend\n", "\n", - "> The computational efficiency of `StatsForecast` can be tracked to its two core components:
1. Its `models` written in NumBa that optimizes Python code to reach C speeds.
2. Its `core.StatsForecast` class that enables distributed computing.
Here we use [Fugue](https://github.com/fugue-project/fugue) which is a unified interface for `Dask` and `Spark`.
" + "The computational efficiency of `StatsForecast` can be tracked to its two core components:\n", + "1. Its `models` written in NumBa that optimizes Python code to reach C speeds.\n", + "2. Its `core.StatsForecast` class that enables distributed computing.\n", + "\n", + "Here we use [Fugue](https://github.com/fugue-project/fugue) which is a unified interface for `Dask` and `Spark`." ] }, { From 19e974e26bfc79fe1780a9ceba748750af050735 Mon Sep 17 00:00:00 2001 From: Hahnbee Lee <55263191+hahnbeelee@users.noreply.github.com> Date: Tue, 10 Oct 2023 15:43:03 -0700 Subject: [PATCH 47/61] add script for previewing mintlify docs locally --- final-formatting.bash | 0 preview-mintlify-docs.bash | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+) mode change 100644 => 100755 final-formatting.bash create mode 100644 preview-mintlify-docs.bash diff --git a/final-formatting.bash b/final-formatting.bash old mode 100644 new mode 100755 diff --git a/preview-mintlify-docs.bash b/preview-mintlify-docs.bash new file mode 100644 index 000000000..27aa8468d --- /dev/null +++ b/preview-mintlify-docs.bash @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +echo "Running nbdev_docs..." +nbdev_docs +echo "nbdev_docs is done" + +echo "Running final-formatting.bash..." +chmod +x final-formatting.bash +./final-formatting.bash +echo "final-formatting.bash is done" + +echo "Moving necessary assets..." +cp nbs/mint.json _docs/mint.json +cp nbs/imgs/logo/dark.png _docs/dark.png +cp nbs/imgs/logo/light.png _docs/light.png +cp nbs/favicon.svg _docs/favicon.svg +echo "Done moving necessary assets" + +cd ./_docs +mintlify dev \ No newline at end of file From 06bd6cdcd3e83aaafc261a9919ecef9305a6d3da Mon Sep 17 00:00:00 2001 From: Hahnbee Lee <55263191+hahnbeelee@users.noreply.github.com> Date: Tue, 10 Oct 2023 15:56:15 -0700 Subject: [PATCH 48/61] copy over contribute folder --- .github/workflows/build-docs.yaml | 7 +++++++ nbs/mint.json | 4 ++-- preview-mintlify-docs.bash | 7 +++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index 94e8d2a57..dafff2c65 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -29,6 +29,13 @@ jobs: cp nbs/imgs/logo/dark.png _docs/dark.png cp nbs/imgs/logo/light.png _docs/light.png cp nbs/favicon.svg _docs/favicon.svg + mkdir _docs/docs/contribute + cp _proc/docs/contribute/contribute.md _docs/docs/contribute/contribute.mdx + cp _proc/docs/contribute/docs.md _docs/docs/contribute/docs.mdx + cp _proc/docs/contribute/issue-labels.md _docs/docs/contribute/issue-labels.mdx + cp _proc/docs/contribute/issues.md _docs/docs/contribute/issues.mdx + cp _proc/docs/contribute/step-by-step.md _docs/docs/contribute/step-by-step.mdx + cp _proc/docs/contribute/techstack.md _docs/docs/contribute/techstack.mdx rm -f _docs/index.html - name: Deploy to Mintlify Docs uses: peaceiris/actions-gh-pages@v3 diff --git a/nbs/mint.json b/nbs/mint.json index 1698063c4..86817bc40 100644 --- a/nbs/mint.json +++ b/nbs/mint.json @@ -103,8 +103,8 @@ "pages": [ "src/core/core.html", "src/core/distributed.fugue.html", - "src/core/models_intro", - "src/core/models.html" + "src/core/models.html", + "src/core/models_intro" ] }, { diff --git a/preview-mintlify-docs.bash b/preview-mintlify-docs.bash index 27aa8468d..fdde934c2 100644 --- a/preview-mintlify-docs.bash +++ b/preview-mintlify-docs.bash @@ -14,6 +14,13 @@ cp nbs/mint.json _docs/mint.json cp nbs/imgs/logo/dark.png _docs/dark.png cp nbs/imgs/logo/light.png _docs/light.png cp nbs/favicon.svg _docs/favicon.svg +mkdir _docs/docs/contribute +cp _proc/docs/contribute/contribute.md _docs/docs/contribute/contribute.mdx +cp _proc/docs/contribute/docs.md _docs/docs/contribute/docs.mdx +cp _proc/docs/contribute/issue-labels.md _docs/docs/contribute/issue-labels.mdx +cp _proc/docs/contribute/issues.md _docs/docs/contribute/issues.mdx +cp _proc/docs/contribute/step-by-step.md _docs/docs/contribute/step-by-step.mdx +cp _proc/docs/contribute/techstack.md _docs/docs/contribute/techstack.mdx echo "Done moving necessary assets" cd ./_docs From c39518df89de5aab8f79a56ef7b50917c5572c61 Mon Sep 17 00:00:00 2001 From: Hahnbee Lee <55263191+hahnbeelee@users.noreply.github.com> Date: Tue, 10 Oct 2023 16:02:50 -0700 Subject: [PATCH 49/61] nbdev_clean --- nbs/docs/models/ARCH.ipynb | 48 +++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/nbs/docs/models/ARCH.ipynb b/nbs/docs/models/ARCH.ipynb index ea36d32bb..0cd6018f8 100644 --- a/nbs/docs/models/ARCH.ipynb +++ b/nbs/docs/models/ARCH.ipynb @@ -12891,7 +12891,7 @@ 0.11683902533544767, 0.18038662130227442, 1.1396760668737118, - 0.000008429606751246858, + 8.429606751246858e-06, 0.9301650273653356, 0.16603494698002158, 0.02552244687162859, @@ -13008,7 +13008,7 @@ 0.333507961464413, 1.5341682132027463, 0.535647628131223, - 0.000008047187854454163, + 8.047187854454163e-06, 0.05159803214177818, 0.07600424912094962, 0.05061172231156831, @@ -13148,7 +13148,7 @@ 2.7279986776819762, 2.7160487251081724, 0.21768883267417796, - 0.00000677720693099992, + 6.77720693099992e-06, 2.0892382083596366, 1.5511137261921708, 0.19711705562956672, @@ -13192,7 +13192,7 @@ 0.09514048933694128, 0.005799502263676435, 0.26977917189300543, - 0.000022905689893454364, + 2.2905689893454364e-05, 0.032835101620127545, 0.035071983113154785, 0.02720364389284937, @@ -13284,7 +13284,7 @@ 0.2733247895916533, 0.03816868105362628, 0.05644730956949203, - 0.000017126891073291785, + 1.7126891073291785e-05, 0.17648748135786346, 0.08890408218010715, 0.00021428585381320998, @@ -13295,7 +13295,7 @@ 0.0034536384504556326, 1.0219740565421616, 0.14230208866334162, - 0.0000034607522944888557, + 3.4607522944888557e-06, 0.0008948379096681811, 1.1918442949862227, 0.4224720090152985, @@ -13319,7 +13319,7 @@ 0.379505710351215, 0.04804736114077823, 0.018926161782214495, - 0.00007079826049627675, + 7.079826049627675e-05, 0.2256097560481151, 0.14422736286851592, 0.03029031934041486, @@ -13454,7 +13454,7 @@ 0.016163575341260606, 0.0033884362508481143, 0.16717428315038643, - 0.000014022086968800128, + 1.4022086968800128e-05, 0.010511348063911363, 0.012782595072851783, 0.04677744379099467, @@ -13502,7 +13502,7 @@ 0.5337190473107196, 0.03514066158205324, 0.21841633296069093, - 0.00002799770311426146, + 2.799770311426146e-05, 0.0035743299293066215, 0.2886525495692123, 0.0002361118071194596, @@ -13552,7 +13552,7 @@ 0.09277613223137564, 0.004196366830944074, 0.04937508180038409, - 0.00005208049534825782, + 5.208049534825782e-05, 0.16688400504491227, 0.014510991850446027, 0.13727838266375458, @@ -13695,7 +13695,7 @@ 0.006911690943276298, 0.3278850494791402, 0.7287238222344438, - 0.00003161982797127493, + 3.161982797127493e-05, 1.7903942515655977, 0.033747867911173186, 1.0887262880763404, @@ -13806,7 +13806,7 @@ 0.017032753347700658, 0.10819350754652532, 0.07635754962107597, - 4.720076651680163e-7, + 4.720076651680163e-07, 0.13257647932461017, 0.0015736305321550584, 0.005062602892380193, @@ -13861,7 +13861,7 @@ 0.0003997208956144086, 3.6430248324576744, 4.315374983468133, - 0.00007465081431494341, + 7.465081431494341e-05, 2.3702802404040986, 2.4875933720473613, 4.238751501049985, @@ -13932,14 +13932,14 @@ 0.12884377091778848, 0.45350527664342116, 1.3383250835766, - 0.000003047038069794671, + 3.047038069794671e-06, 0.046155230627765706, 0.04345704527385812, 0.21496506713259997, 0.010971728644473754, 0.3681449089203887, 0.12095591183388035, - 0.000014533571009694057, + 1.4533571009694057e-05, 0.43683167649436533, 0.003961054815055465, 0.002594457624136788, @@ -14042,7 +14042,7 @@ 1.1755067590686328, 1.692552536701068, 0.008292017842472079, - 0.00008837910181512196, + 8.837910181512196e-05, 0.0010388011063882155, 0.52268289783404, 0.08289521198197039, @@ -14050,9 +14050,9 @@ 0.09831904474102832, 0.06665444896152177, 0.0011743773216012492, - 0.000003989948937286202, + 3.989948937286202e-06, 0.23966670389611294, - 0.00009396568391014351, + 9.396568391014351e-05, 0.7083530264126577, 0.379280036868932, 0.05899634912283012, @@ -14110,7 +14110,7 @@ 0.012032641276976222, 0.08457382662710584, 0.73534494099483, - 0.0000526813972937628, + 5.26813972937628e-05, 0.5109083285028833, 0.0011242101166246262, 0.0018688345123409381, @@ -14119,7 +14119,7 @@ 0.0075020470243941095, 0.00038200004553110315, 0.26298092501994424, - 0.000011549731265675906, + 1.1549731265675906e-05, 0.33417910089435754, 0.0867904320408933, 0.7020433764156192, @@ -14594,7 +14594,7 @@ 0.6766417031004891, 0.0030353502921928455, 0.52166759677021, - 0.0000011534388436087901, + 1.1534388436087901e-06, 0.1494000082288102, 0.06768454071199759, 0.11456736834367175, @@ -14945,13 +14945,13 @@ 0.06211911053832683, 0.12810408947533514, 0.009926192984207037, - 0.000017100299484364275, + 1.7100299484364275e-05, 0.17097265655211852, 1.7589894800913939, 0.042823064448460374, 0.10930672666497082, 0.007314017675982816, - 0.00007100057638853501, + 7.100057638853501e-05, 0.3543283102780241, 0.00815750397918031, 0.00725186857060821, @@ -14979,7 +14979,7 @@ 0.5356191175456438, 0.7669523057389738, 1.7027866477021951, - 0.000002756746937148935, + 2.756746937148935e-06, 0.3731529145352457, 0.9711025783145061, 2.1124949696707556, From f9073c1aab3e9f4fc833d1d886dec721d2e1637c Mon Sep 17 00:00:00 2001 From: Hahnbee Lee <55263191+hahnbeelee@users.noreply.github.com> Date: Tue, 10 Oct 2023 16:05:35 -0700 Subject: [PATCH 50/61] move final-formatting to action files --- .github/workflows/build-docs.yaml | 2 +- final-formatting.bash => action_files/final-formatting.bash | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename final-formatting.bash => action_files/final-formatting.bash (100%) diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index dafff2c65..cea36fb8c 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -22,7 +22,7 @@ jobs: nbdev_docs - name: Apply final formats shell: bash - run: bash final-formatting.bash + run: bash ./action_files/final-formatting.bash - name: Copy over necessary assets run: | cp nbs/mint.json _docs/mint.json diff --git a/final-formatting.bash b/action_files/final-formatting.bash similarity index 100% rename from final-formatting.bash rename to action_files/final-formatting.bash From 38a21b2f3acf5eb3bbf6427e2e3b82cb00401770 Mon Sep 17 00:00:00 2001 From: Hahnbee Lee <55263191+hahnbeelee@users.noreply.github.com> Date: Tue, 10 Oct 2023 17:19:45 -0700 Subject: [PATCH 51/61] move everything to mintlify folder --- .github/workflows/build-docs.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index cea36fb8c..8ff0084a6 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -37,11 +37,13 @@ jobs: cp _proc/docs/contribute/step-by-step.md _docs/docs/contribute/step-by-step.mdx cp _proc/docs/contribute/techstack.md _docs/docs/contribute/techstack.mdx rm -f _docs/index.html + mkdir mintlify + cp -r ./_docs ./mintlify - name: Deploy to Mintlify Docs uses: peaceiris/actions-gh-pages@v3 with: publish_branch: docs - publish_dir: ./_docs + publish_dir: ./mintlify # The following lines assign commit authorship to the official GH-Actions bot for deploys to `docs` branch. # You can swap them out with your own user credentials. user_name: github-actions[bot] From 82cb7f89bcff297ebcf22097e32fed1979a8e0f3 Mon Sep 17 00:00:00 2001 From: Hahnbee Lee <55263191+hahnbeelee@users.noreply.github.com> Date: Tue, 10 Oct 2023 18:47:50 -0700 Subject: [PATCH 52/61] Update build script --- .github/workflows/build-docs.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index 8ff0084a6..78b2519ff 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -37,13 +37,12 @@ jobs: cp _proc/docs/contribute/step-by-step.md _docs/docs/contribute/step-by-step.mdx cp _proc/docs/contribute/techstack.md _docs/docs/contribute/techstack.mdx rm -f _docs/index.html - mkdir mintlify - cp -r ./_docs ./mintlify - name: Deploy to Mintlify Docs uses: peaceiris/actions-gh-pages@v3 with: + github_token: ${{ secrets.GITHUB_TOKEN }} publish_branch: docs - publish_dir: ./mintlify + publish_dir: ./_docs # The following lines assign commit authorship to the official GH-Actions bot for deploys to `docs` branch. # You can swap them out with your own user credentials. user_name: github-actions[bot] From 6079a19df8f028c6ebfe3765465cd7f949d0d1b3 Mon Sep 17 00:00:00 2001 From: Hahnbee Lee <55263191+hahnbeelee@users.noreply.github.com> Date: Tue, 10 Oct 2023 18:49:34 -0700 Subject: [PATCH 53/61] remove rm -r index.html --- .github/workflows/build-docs.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index 78b2519ff..5c1e4eddf 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -36,7 +36,6 @@ jobs: cp _proc/docs/contribute/issues.md _docs/docs/contribute/issues.mdx cp _proc/docs/contribute/step-by-step.md _docs/docs/contribute/step-by-step.mdx cp _proc/docs/contribute/techstack.md _docs/docs/contribute/techstack.mdx - rm -f _docs/index.html - name: Deploy to Mintlify Docs uses: peaceiris/actions-gh-pages@v3 with: From 973515268f595487998c0c81f2b5cfb509e702e4 Mon Sep 17 00:00:00 2001 From: Hahnbee Lee <55263191+hahnbeelee@users.noreply.github.com> Date: Tue, 10 Oct 2023 19:54:25 -0700 Subject: [PATCH 54/61] Add md to extension --- .github/workflows/build-docs.yaml | 7 ------- nbs/_extensions/mintlify/_extension.yml | 4 +--- nbs/_extensions/mintlify/plotly.lua | 17 ----------------- 3 files changed, 1 insertion(+), 27 deletions(-) delete mode 100644 nbs/_extensions/mintlify/plotly.lua diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml index 5c1e4eddf..d50ea4104 100644 --- a/.github/workflows/build-docs.yaml +++ b/.github/workflows/build-docs.yaml @@ -29,13 +29,6 @@ jobs: cp nbs/imgs/logo/dark.png _docs/dark.png cp nbs/imgs/logo/light.png _docs/light.png cp nbs/favicon.svg _docs/favicon.svg - mkdir _docs/docs/contribute - cp _proc/docs/contribute/contribute.md _docs/docs/contribute/contribute.mdx - cp _proc/docs/contribute/docs.md _docs/docs/contribute/docs.mdx - cp _proc/docs/contribute/issue-labels.md _docs/docs/contribute/issue-labels.mdx - cp _proc/docs/contribute/issues.md _docs/docs/contribute/issues.mdx - cp _proc/docs/contribute/step-by-step.md _docs/docs/contribute/step-by-step.mdx - cp _proc/docs/contribute/techstack.md _docs/docs/contribute/techstack.mdx - name: Deploy to Mintlify Docs uses: peaceiris/actions-gh-pages@v3 with: diff --git a/nbs/_extensions/mintlify/_extension.yml b/nbs/_extensions/mintlify/_extension.yml index b70e3282e..8d00f060f 100644 --- a/nbs/_extensions/mintlify/_extension.yml +++ b/nbs/_extensions/mintlify/_extension.yml @@ -8,6 +8,7 @@ contributes: detect: - ["mint.json"] render: + - "**/*.md" - "**/*.qmd" - "**/*.ipynb" format: mintlify-md @@ -26,8 +27,5 @@ contributes: fig-width: 8 fig-height: 5 html-math-method: webtex - # shortcodes: - # - plotly.lua filters: - mintlify.lua - # - plotly.lua diff --git a/nbs/_extensions/mintlify/plotly.lua b/nbs/_extensions/mintlify/plotly.lua deleted file mode 100644 index ec2f828dc..000000000 --- a/nbs/_extensions/mintlify/plotly.lua +++ /dev/null @@ -1,17 +0,0 @@ --- local scriptCount = 0 --- local printItem = 4 -function script(scriptEl) - -- scriptCount = scriptCount + 1 - -- quarto.log.output('---Script El---') - -- quarto.log.output(scriptCount) - -- if printItem == scriptCount then - -- quarto.utils.dump(scriptEl) - -- end - quarto.log.output('---Script El---') -end - -return { - { - ['application/vnd.plotly.v1+json'] = script - } -} \ No newline at end of file From 4b68115da44a0be03fb9d9e5fa8d67c64cc8dd68 Mon Sep 17 00:00:00 2001 From: Hahnbee Lee <55263191+hahnbeelee@users.noreply.github.com> Date: Tue, 10 Oct 2023 20:00:38 -0700 Subject: [PATCH 55/61] delete reader --- nbs/_extensions/mintlify/_extension.yml | 1 - nbs/_extensions/mintlify/mintlify_reader.lua | 8 -------- 2 files changed, 9 deletions(-) delete mode 100644 nbs/_extensions/mintlify/mintlify_reader.lua diff --git a/nbs/_extensions/mintlify/_extension.yml b/nbs/_extensions/mintlify/_extension.yml index 8d00f060f..663084de9 100644 --- a/nbs/_extensions/mintlify/_extension.yml +++ b/nbs/_extensions/mintlify/_extension.yml @@ -18,7 +18,6 @@ contributes: # Ideally, we would forward the variants to the custom writer. variant: gfm+pipe_tables+tex_math_dollars+raw_html+all_symbols_escapable+backtick_code_blocks+space_in_atx_header+intraword_underscores+lists_without_preceding_blankline+shortcut_reference_links writer: mintlify_writer.lua - # reader: mintlify_reader.lua output-ext: mdx inline-includes: true preserve-yaml: true diff --git a/nbs/_extensions/mintlify/mintlify_reader.lua b/nbs/_extensions/mintlify/mintlify_reader.lua deleted file mode 100644 index 60d496cfe..000000000 --- a/nbs/_extensions/mintlify/mintlify_reader.lua +++ /dev/null @@ -1,8 +0,0 @@ --- function Reader(input) --- return pandoc.Pandoc(input:map( --- function (s) --- -- print(s) --- return pandoc.CodeBlock(s.text) --- end --- )) --- end \ No newline at end of file From e272e576e8bcd2fa2c66476fd9324f18ffcc9a24 Mon Sep 17 00:00:00 2001 From: Hahnbee Lee <55263191+hahnbeelee@users.noreply.github.com> Date: Tue, 10 Oct 2023 21:17:45 -0700 Subject: [PATCH 56/61] undo all mintlify assets --- .github/workflows/build-docs.yaml | 41 -- README.md | 334 +++++++------- action_files/final-formatting.bash | 11 - nbs/_extensions/mintlify/_extension.yml | 30 -- nbs/_extensions/mintlify/mintlify.lua | 71 --- .../mintlify/mintlify_renderers.lua | 3 - nbs/_extensions/mintlify/mintlify_utils.lua | 47 -- nbs/_extensions/mintlify/mintlify_writer.lua | 133 ------ nbs/_quarto.yml | 59 ++- nbs/custom.yml | 22 + nbs/favicon.png | Bin 208747 -> 0 bytes nbs/favicon.svg | 5 - nbs/favicon_png.png | Bin 177981 -> 0 bytes nbs/mint.json | 122 ----- nbs/styles.css | 431 ++++++++++++++++++ preview-mintlify-docs.bash | 27 -- settings.ini | 5 +- 17 files changed, 668 insertions(+), 673 deletions(-) delete mode 100644 .github/workflows/build-docs.yaml delete mode 100755 action_files/final-formatting.bash delete mode 100644 nbs/_extensions/mintlify/_extension.yml delete mode 100644 nbs/_extensions/mintlify/mintlify.lua delete mode 100644 nbs/_extensions/mintlify/mintlify_renderers.lua delete mode 100644 nbs/_extensions/mintlify/mintlify_utils.lua delete mode 100644 nbs/_extensions/mintlify/mintlify_writer.lua create mode 100644 nbs/custom.yml delete mode 100644 nbs/favicon.png delete mode 100644 nbs/favicon.svg delete mode 100644 nbs/favicon_png.png delete mode 100644 nbs/mint.json create mode 100644 nbs/styles.css delete mode 100644 preview-mintlify-docs.bash diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml deleted file mode 100644 index d50ea4104..000000000 --- a/.github/workflows/build-docs.yaml +++ /dev/null @@ -1,41 +0,0 @@ -name: "build-docs" -on: - push: - branches: ["main"] - workflow_dispatch: -jobs: - build-docs: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - with: - cache: "pip" - cache-dependency-path: settings.ini - - name: Install Dependencies - shell: bash - run: | - set -ux - python -m pip install --upgrade pip - pip install -Uq nbdev - test -f setup.py && pip install -e ".[dev]" - nbdev_docs - - name: Apply final formats - shell: bash - run: bash ./action_files/final-formatting.bash - - name: Copy over necessary assets - run: | - cp nbs/mint.json _docs/mint.json - cp nbs/imgs/logo/dark.png _docs/dark.png - cp nbs/imgs/logo/light.png _docs/light.png - cp nbs/favicon.svg _docs/favicon.svg - - name: Deploy to Mintlify Docs - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_branch: docs - publish_dir: ./_docs - # The following lines assign commit authorship to the official GH-Actions bot for deploys to `docs` branch. - # You can swap them out with your own user credentials. - user_name: github-actions[bot] - user_email: 41898282+github-actions[bot]@users.noreply.github.com diff --git a/README.md b/README.md index 72627afbe..96a610ead 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,32 @@ -# Nixtla [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Statistical%20Forecasting%20Algorithms%20by%20Nixtla%20&url=https://github.com/Nixtla/statsforecast&via=nixtlainc&hashtags=StatisticalModels,TimeSeries,Forecasting) [![Slack](https://img.shields.io/badge/Slack-4A154B?&logo=slack&logoColor=white)](https://join.slack.com/t/nixtlacommunity/shared_invite/zt-1pmhan9j5-F54XR20edHk0UtYAPcW4KQ) - -[![All Contributors](https://img.shields.io/badge/all_contributors-32-orange.svg?style=flat-square)](#contributors-) - - -- -+# StatsForecast β‘οΈ + + ## Installation -You can install `StatsForecast` with: +You can install +[`StatsForecast`](https://Nixtla.github.io/statsforecast/src/core/core.html#statsforecast) +with: -```python +``` python pip install statsforecast ``` -or +or -```python +``` python conda install -c conda-forge statsforecast -``` - +``` -Vist our [Installation Guide](https://nixtla.github.io/statsforecast/docs/getting-started/installation.html) for further instructions. +Vist our [Installation +Guide](./docs/getting-started/0_Installation.ipynb) for further +instructions. ## Quick Start **Minimal Example** -```python +``` python from statsforecast import StatsForecast from statsforecast.models import AutoARIMA @@ -53,144 +39,201 @@ sf.fit(df) sf.predict(h=12, level=[95]) ``` -**Get Started with this [quick guide](https://nixtla.github.io/statsforecast/docs/getting-started/getting_started_short.html).** +**Get Started with this [quick +guide](../nbs/docs/getting-started/1_Getting_Started_short.ipynb).** -**Follow this [end-to-end walkthrough](https://nixtla.github.io/statsforecast/docs/getting-started/getting_started_complete.html) for best practices.** +**Follow this [end-to-end +walkthrough](../nbs/docs/getting-started/2_Getting_Started_complete.ipynb) +for best practices.** -## Why? +## Why? -Current Python alternatives for statistical models are slow, inaccurate and don't scale well. So we created a library that can be used to forecast in production environments or as benchmarks. `StatsForecast` includes an extensive battery of models that can efficiently fit millions of time series. +Current Python alternatives for statistical models are slow, inaccurate +and donβt scale well. So we created a library that can be used to +forecast in production environments or as benchmarks. +[`StatsForecast`](https://Nixtla.github.io/statsforecast/src/core/core.html#statsforecast) +includes an extensive battery of models that can efficiently fit +millions of time series. ## Features -* Fastest and most accurate implementations of `AutoARIMA`, `AutoETS`, `AutoCES`, `MSTL` and `Theta` in Python. -* Out-of-the-box compatibility with Spark, Dask, and Ray. -* Probabilistic Forecasting and Confidence Intervals. -* Support for exogenous Variables and static covariates. -* Anomaly Detection. -* Familiar sklearn syntax: `.fit` and `.predict`. +- Fastest and most accurate implementations of + [`AutoARIMA`](https://Nixtla.github.io/statsforecast/src/core/models.html#autoarima), + [`AutoETS`](https://Nixtla.github.io/statsforecast/src/core/models.html#autoets), + [`AutoCES`](https://Nixtla.github.io/statsforecast/src/core/models.html#autoces), + [`MSTL`](https://Nixtla.github.io/statsforecast/src/core/models.html#mstl) + and + [`Theta`](https://Nixtla.github.io/statsforecast/src/core/models.html#theta) + in Python. +- Out-of-the-box compatibility with Spark, Dask, and Ray. +- Probabilistic Forecasting and Confidence Intervals. +- Support for exogenous Variables and static covariates. +- Anomaly Detection. +- Familiar sklearn syntax: `.fit` and `.predict`. ## Highlights -* Inclusion of `exogenous variables` and `prediction intervals` for ARIMA. -* 20x [faster](./experiments/arima/) than `pmdarima`. -* 1.5x faster than `R`. -* 500x faster than `Prophet`. -* 4x [faster](./experiments/ets/) than `statsmodels`. -* Compiled to high performance machine code through [`numba`](https://numba.pydata.org/). -* 1,000,000 series in [30 min](https://github.com/Nixtla/statsforecast/tree/main/experiments/ray) with [ray](https://github.com/ray-project/ray). -* Replace FB-Prophet in two lines of code and gain speed and accuracy. Check the experiments [here](https://github.com/Nixtla/statsforecast/tree/main/experiments/arima_prophet_adapter). -* Fit 10 benchmark models on **1,000,000** series in [under **5 min**](./experiments/benchmarks_at_scale/). - - -Missing something? Please open an issue or write us in [![Slack](https://img.shields.io/badge/Slack-4A154B?&logo=slack&logoColor=white)](https://join.slack.com/t/nixtlaworkspace/shared_invite/zt-135dssye9-fWTzMpv2WBthq8NK0Yvu6A) +- Inclusion of `exogenous variables` and `prediction intervals` for + ARIMA. +- 20x + [faster](https://github.com/Nixtla/statsforecast/tree/main/experiments/arima) + than `pmdarima`. +- 1.5x faster than `R`. +- 500x faster than `Prophet`. +- 4x + [faster](https://github.com/Nixtla/statsforecast/tree/main/experiments/ets) + than `statsmodels`. +- Compiled to high performance machine code through + [`numba`](https://numba.pydata.org/). +- 1,000,000 series in [30 + min](https://github.com/Nixtla/statsforecast/tree/main/experiments/ray) + with [ray](https://github.com/ray-project/ray). +- Replace FB-Prophet in two lines of code and gain speed and accuracy. + Check the experiments + [here](https://github.com/Nixtla/statsforecast/tree/main/experiments/arima_prophet_adapter). +- Fit 10 benchmark models on **1,000,000** series in [under **5 + min**](https://github.com/Nixtla/statsforecast/tree/main/experiments/benchmarks_at_scale). + +Missing something? Please open an issue or write us in +[![Slack](https://img.shields.io/badge/Slack-4A154B?&logo=slack&logoColor=white.png)](https://join.slack.com/t/nixtlaworkspace/shared_invite/zt-135dssye9-fWTzMpv2WBthq8NK0Yvu6A) ## Examples and Guides -π [End to End Walkthrough](https://nixtla.github.io/statsforecast/docs/getting-started/getting_started_complete.html): Model training, evaluation and selection for multiple time series - -π [Anomaly Detection](https://nixtla.github.io/statsforecast/docs/tutorials/anomalydetection.html): detect anomalies for time series using in-sample prediction intervals. +π [End to End +Walkthrough](https://nixtla.github.io/statsforecast/docs/getting-started/getting_started_complete.html): +Model training, evaluation and selection for multiple time series -π©βπ¬ [Cross Validation](https://nixtla.github.io/statsforecast/docs/tutorials/crossvalidation.html): robust modelβs performance evaluation. +π [Anomaly +Detection](https://nixtla.github.io/statsforecast/docs/tutorials/anomalydetection.html): +detect anomalies for time series using in-sample prediction intervals. -βοΈ [Multiple Seasonalities](https://nixtla.github.io/statsforecast/docs/tutorials/multipleseasonalities.html): how to forecast data with multiple seasonalities using an MSTL. +π©βπ¬ [Cross +Validation](https://nixtla.github.io/statsforecast/docs/tutorials/crossvalidation.html): +robust modelβs performance evaluation. -π [Predict Demand Peaks](https://nixtla.github.io/statsforecast/docs/tutorials/electricitypeakforecasting.html): electricity load forecasting for detecting daily peaks and reducing electric bills. +βοΈ [Multiple +Seasonalities](https://nixtla.github.io/statsforecast/docs/tutorials/multipleseasonalities.html): +how to forecast data with multiple seasonalities using an MSTL. -π [Intermittent Demand](https://nixtla.github.io/statsforecast/docs/tutorials/intermittentdata.html): forecast series with very few non-zero observations. +π [Predict Demand +Peaks](https://nixtla.github.io/statsforecast/docs/tutorials/electricitypeakforecasting.html): +electricity load forecasting for detecting daily peaks and reducing +electric bills. -π‘οΈ [Exogenous Regressors](https://nixtla.github.io/statsforecast/docs/how-to-guides/exogenous.html): like weather or prices +π [Intermittent +Demand](https://nixtla.github.io/statsforecast/docs/tutorials/intermittentdata.html): +forecast series with very few non-zero observations. +π‘οΈ [Exogenous +Regressors](https://nixtla.github.io/statsforecast/docs/how-to-guides/exogenous.html): +like weather or prices ## Models ### Automatic Forecasting -Automatic forecasting tools search for the best parameters and select the best possible model for a group of time series. These tools are useful for large collections of univariate time series. -|Model | Point Forecast | Probabilistic Forecast | Insample fitted values | Probabilistic fitted values | -|:------|:-------------:|:----------------------:|:---------------------:|:----------------------------:| -|[AutoARIMA](https://nixtla.github.io/statsforecast/src/core/models.html#autoarima)|β |β |β |β |β | -|[AutoETS](https://nixtla.github.io/statsforecast/src/core/models.html#autoets)|β |β |β |β |β | -|[AutoCES](https://nixtla.github.io/statsforecast/src/core/models.html#autoces)|β |β |β |β |β | -|[AutoTheta](https://nixtla.github.io/statsforecast/src/core/models.html#autotheta)|β |β |β |β |β | +Automatic forecasting tools search for the best parameters and select +the best possible model for a group of time series. These tools are +useful for large collections of univariate time series. + +| Model | Point Forecast | Probabilistic Forecast | Insample fitted values | Probabilistic fitted values | +|:-----------------------------------------------------------------------------------|:--------------:|:----------------------:|:----------------------:|:---------------------------:| +| [AutoARIMA](https://nixtla.github.io/statsforecast/src/core/models.html#autoarima) | β | β | β | β | +| [AutoETS](https://nixtla.github.io/statsforecast/src/core/models.html#autoets) | β | β | β | β | +| [AutoCES](https://nixtla.github.io/statsforecast/src/core/models.html#autoces) | β | β | β | β | +| [AutoTheta](https://nixtla.github.io/statsforecast/src/core/models.html#autotheta) | β | β | β | β | ## ARIMA Family + These models exploit the existing autocorrelations in the time series. -|Model | Point Forecast | Probabilistic Forecast | Insample fitted values | Probabilistic fitted values | -|:------|:-------------:|:----------------------:|:---------------------:|:----------------------------:| -|[ARIMA](https://nixtla.github.io/statsforecast/src/core/models.html#arima)|β |β |β |β |β | -|[AutoRegressive](https://nixtla.github.io/statsforecast/src/core/models.html#autoregressive)|β |β |β |β |β | +| Model | Point Forecast | Probabilistic Forecast | Insample fitted values | Probabilistic fitted values | +|:---------------------------------------------------------------------------------------------|:--------------:|:----------------------:|:----------------------:|:---------------------------:| +| [ARIMA](https://nixtla.github.io/statsforecast/src/core/models.html#arima) | β | β | β | β | +| [AutoRegressive](https://nixtla.github.io/statsforecast/src/core/models.html#autoregressive) | β | β | β | β | ### Theta Family -Fit two theta lines to a deseasonalized time series, using different techniques to obtain and combine the two theta lines to produce the final forecasts. -|Model | Point Forecast | Probabilistic Forecast | Insample fitted values | Probabilistic fitted values | -|:------|:-------------:|:----------------------:|:---------------------:|:----------------------------:| -|[Theta](https://nixtla.github.io/statsforecast/src/core/models.html#theta)|β |β |β |β |β | -|[OptimizedTheta](https://nixtla.github.io/statsforecast/src/core/models.html#optimizedtheta)|β |β |β |β |β | -|[DynamicTheta](https://nixtla.github.io/statsforecast/src/core/models.html#dynamictheta)|β |β |β |β |β | -|[DynamicOptimizedTheta](https://nixtla.github.io/statsforecast/src/core/models.html#dynamicoptimizedtheta)|β |β |β |β |β | +Fit two theta lines to a deseasonalized time series, using different +techniques to obtain and combine the two theta lines to produce the +final forecasts. + +| Model | Point Forecast | Probabilistic Forecast | Insample fitted values | Probabilistic fitted values | +|:-----------------------------------------------------------------------------------------------------------|:--------------:|:----------------------:|:----------------------:|:---------------------------:| +| [Theta](https://nixtla.github.io/statsforecast/src/core/models.html#theta) | β | β | β | β | +| [OptimizedTheta](https://nixtla.github.io/statsforecast/src/core/models.html#optimizedtheta) | β | β | β | β | +| [DynamicTheta](https://nixtla.github.io/statsforecast/src/core/models.html#dynamictheta) | β | β | β | β | +| [DynamicOptimizedTheta](https://nixtla.github.io/statsforecast/src/core/models.html#dynamicoptimizedtheta) | β | β | β | β | ### Multiple Seasonalities -Suited for signals with more than one clear seasonality. Useful for low-frequency data like electricity and logs. -|Model | Point Forecast | Probabilistic Forecast | Insample fitted values | Probabilistic fitted values | -|:------|:-------------:|:----------------------:|:---------------------:|:----------------------------:| -|[MSTL](https://nixtla.github.io/statsforecast/src/core/models.html#mstl)|β |β |β |β |β | +Suited for signals with more than one clear seasonality. Useful for +low-frequency data like electricity and logs. -### GARCH and ARCH Models -Suited for modeling time series that exhibit non-constant volatility over time. The ARCH model is a particular case of GARCH. +| Model | Point Forecast | Probabilistic Forecast | Insample fitted values | Probabilistic fitted values | +|:-------------------------------------------------------------------------|:--------------:|:----------------------:|:----------------------:|:---------------------------:| +| [MSTL](https://nixtla.github.io/statsforecast/src/core/models.html#mstl) | β | β | β | β | -|Model | Point Forecast | Probabilistic Forecast | Insample fitted values | Probabilistic fitted values | -|:------|:-------------:|:----------------------:|:---------------------:|:----------------------------:| -|[GARCH](https://nixtla.github.io/statsforecast/src/core/models.html#garch)|β |β |β |β |β | -|[ARCH](https://nixtla.github.io/statsforecast/src/core/models.html#arch)|β |β |β |β |β | +### GARCH and ARCH Models +Suited for modeling time series that exhibit non-constant volatility +over time. The ARCH model is a particular case of GARCH. + +| Model | Point Forecast | Probabilistic Forecast | Insample fitted values | Probabilistic fitted values | +|:---------------------------------------------------------------------------|:--------------:|:----------------------:|:----------------------:|:---------------------------:| +| [GARCH](https://nixtla.github.io/statsforecast/src/core/models.html#garch) | β | β | β | β | +| [ARCH](https://nixtla.github.io/statsforecast/src/core/models.html#arch) | β | β | β | β | ### Baseline Models + Classical models for establishing baseline. -|Model | Point Forecast | Probabilistic Forecast | Insample fitted values | Probabilistic fitted values | -|:------|:-------------:|:----------------------:|:---------------------:|:----------------------------:| -|[HistoricAverage](https://nixtla.github.io/statsforecast/src/core/models.html#historicaverage)|β |β |β |β |β | -|[Naive](https://nixtla.github.io/statsforecast/src/core/models.html#naive)|β |β |β |β |β | -|[RandomWalkWithDrift](https://nixtla.github.io/statsforecast/src/core/models.html#randomwalkwithdrift)|β |β |β |β |β | -|[SeasonalNaive](https://nixtla.github.io/statsforecast/src/core/models.html#seasonalnaive)|β |β |β |β |β | -|[WindowAverage](https://nixtla.github.io/statsforecast/src/core/models.html#windowaverage)|β ||||| -|[SeasonalWindowAverage](https://nixtla.github.io/statsforecast/src/core/models.html#seasonalwindowaverage)|β ||||| +| Model | Point Forecast | Probabilistic Forecast | Insample fitted values | Probabilistic fitted values | +|:-----------------------------------------------------------------------------------------------------------|:--------------:|:----------------------:|:----------------------:|:---------------------------:| +| [HistoricAverage](https://nixtla.github.io/statsforecast/src/core/models.html#historicaverage) | β | β | β | β | +| [Naive](https://nixtla.github.io/statsforecast/src/core/models.html#naive) | β | β | β | β | +| [RandomWalkWithDrift](https://nixtla.github.io/statsforecast/src/core/models.html#randomwalkwithdrift) | β | β | β | β | +| [SeasonalNaive](https://nixtla.github.io/statsforecast/src/core/models.html#seasonalnaive) | β | β | β | β | +| [WindowAverage](https://nixtla.github.io/statsforecast/src/core/models.html#windowaverage) | β | | | | +| [SeasonalWindowAverage](https://nixtla.github.io/statsforecast/src/core/models.html#seasonalwindowaverage) | β | | | | ### Exponential Smoothing -Uses a weighted average of all past observations where the weights decrease exponentially into the past. Suitable for data with clear trend and/or seasonality. Use the `SimpleExponential` family for data with no clear trend or seasonality. -|Model | Point Forecast | Probabilistic Forecast | Insample fitted values | Probabilistic fitted values | -|:------|:-------------:|:----------------------:|:---------------------:|:----------------------------:| -|[SimpleExponentialSmoothing](https://nixtla.github.io/statsforecast/src/core/models.html#simpleexponentialsmoothing)|β ||||| -|[SimpleExponentialSmoothingOptimized](https://nixtla.github.io/statsforecast/src/core/models.html#simpleexponentialsmoothingoptimized)|β ||||| -|[SeasonalExponentialSmoothing](https://nixtla.github.io/statsforecast/src/core/models.html#seasonalexponentialsmoothing)|β ||||| -|[SeasonalExponentialSmoothingOptimized](https://nixtla.github.io/statsforecast/src/core/models.html#seasonalexponentialsmoothingoptimized)|β ||||| -|[Holt](https://nixtla.github.io/statsforecast/src/core/models.html#holt)|β |β |β |β |β | -|[HoltWinters](https://nixtla.github.io/statsforecast/src/core/models.html#holtwinters)|β |β |β |β |β | +Uses a weighted average of all past observations where the weights +decrease exponentially into the past. Suitable for data with clear trend +and/or seasonality. Use the `SimpleExponential` family for data with no +clear trend or seasonality. +| Model | Point Forecast | Probabilistic Forecast | Insample fitted values | Probabilistic fitted values | +|:-------------------------------------------------------------------------------------------------------------------------------------------|:--------------:|:----------------------:|:----------------------:|:---------------------------:| +| [SimpleExponentialSmoothing](https://nixtla.github.io/statsforecast/src/core/models.html#simpleexponentialsmoothing) | β | | | | +| [SimpleExponentialSmoothingOptimized](https://nixtla.github.io/statsforecast/src/core/models.html#simpleexponentialsmoothingoptimized) | β | | | | +| [SeasonalExponentialSmoothing](https://nixtla.github.io/statsforecast/src/core/models.html#seasonalexponentialsmoothing) | β | | | | +| [SeasonalExponentialSmoothingOptimized](https://nixtla.github.io/statsforecast/src/core/models.html#seasonalexponentialsmoothingoptimized) | β | | | | +| [Holt](https://nixtla.github.io/statsforecast/src/core/models.html#holt) | β | β | β | β | +| [HoltWinters](https://nixtla.github.io/statsforecast/src/core/models.html#holtwinters) | β | β | β | β | + +### Sparse or Inttermitent -### Sparse or Intermittent Suited for series with very few non-zero observations -|Model | Point Forecast | Probabilistic Forecast | Insample fitted values | Probabilistic fitted values | -|:------|:-------------:|:----------------------:|:---------------------:|:----------------------------:| -|[ADIDA](https://nixtla.github.io/statsforecast/src/core/models.html#adida)|β ||||| -|[CrostonClassic](https://nixtla.github.io/statsforecast/src/core/models.html#crostonclassic)|β ||||| -|[CrostonOptimized](https://nixtla.github.io/statsforecast/src/core/models.html#crostonoptimized)|β ||||| -|[CrostonSBA](https://nixtla.github.io/statsforecast/src/core/models.html#crostonsba)|β ||||| -|[IMAPA](https://nixtla.github.io/statsforecast/src/core/models.html#imapa)|β ||||| -|[TSB](https://nixtla.github.io/statsforecast/src/core/models.html#tsb)|β ||||| +| Model | Point Forecast | Probabilistic Forecast | Insample fitted values | Probabilistic fitted values | +|:-------------------------------------------------------------------------------------------------|:--------------:|:----------------------:|:----------------------:|:---------------------------:| +| [ADIDA](https://nixtla.github.io/statsforecast/src/core/models.html#adida) | β | | | | +| [CrostonClassic](https://nixtla.github.io/statsforecast/src/core/models.html#crostonclassic) | β | | | | +| [CrostonOptimized](https://nixtla.github.io/statsforecast/src/core/models.html#crostonoptimized) | β | | | | +| [CrostonSBA](https://nixtla.github.io/statsforecast/src/core/models.html#crostonsba) | β | | | | +| [IMAPA](https://nixtla.github.io/statsforecast/src/core/models.html#imapa) | β | | | | +| [TSB](https://nixtla.github.io/statsforecast/src/core/models.html#tsb) | β | | | | + +## How to contribute -## π¨ How to contribute -See [CONTRIBUTING.md](https://github.com/Nixtla/statsforecast/blob/main/CONTRIBUTING.md). +See +[CONTRIBUTING.md](https://github.com/Nixtla/statsforecast/blob/main/CONTRIBUTING.md). ## Citing -```bibtex +``` bibtex @misc{garza2022statsforecast, author={Federico Garza, Max Mergenthaler Canseco, Cristian ChallΓΊ, Kin G. Olivares}, title = {{StatsForecast}: Lightning fast forecasting with statistical and econometric models}, @@ -199,64 +242,3 @@ See [CONTRIBUTING.md](https://github.com/Nixtla/statsforecast/blob/main/CONTRIBU url={https://github.com/Nixtla/statsforecast} } ``` - -## Contributors β¨ - -Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): - - - - -Statistical β‘οΈ Forecast
-Lightning fast forecasting with statistical and econometric models
- -[![CI](https://github.com/Nixtla/statsforecast/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/Nixtla/statsforecast/actions/workflows/ci.yaml) -[![Python](https://img.shields.io/pypi/pyversions/statsforecast)](https://pypi.org/project/statsforecast/) -[![PyPi](https://img.shields.io/pypi/v/statsforecast?color=blue)](https://pypi.org/project/statsforecast/) -[![conda-nixtla](https://img.shields.io/conda/vn/conda-forge/statsforecast?color=seagreen&label=conda)](https://anaconda.org/conda-forge/statsforecast) -[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://github.com/Nixtla/statsforecast/blob/main/LICENSE) -[![docs](https://img.shields.io/website-up-down-green-red/http/nixtla.github.io/statsforecast.svg?label=docs)](https://nixtla.github.io/statsforecast/) -[![Downloads](https://pepy.tech/badge/statsforecast)](https://pepy.tech/project/statsforecast) - -**StatsForecast** offers a collection of widely used univariate time series forecasting models, including automatic `ARIMA`, `ETS`, `CES`, and `Theta` modeling optimized for high performance using `numba`. It also includes a large battery of benchmarking models. -
/
/g' $file - else - sed -i -e 's/style="float:right; font-size:smaller"/style={{ float: "right", fontSize: "smaller" }}/g' $file - sed -i -e 's/
/
/g' $file - fi -done \ No newline at end of file diff --git a/nbs/_extensions/mintlify/_extension.yml b/nbs/_extensions/mintlify/_extension.yml deleted file mode 100644 index 663084de9..000000000 --- a/nbs/_extensions/mintlify/_extension.yml +++ /dev/null @@ -1,30 +0,0 @@ -title: Mintlify -author: Mintlify, Inc -organization: Mintlify -contributes: - project: - project: - type: default - detect: - - ["mint.json"] - render: - - "**/*.md" - - "**/*.qmd" - - "**/*.ipynb" - format: mintlify-md - formats: - md: - # Although we use a custom writer, we still need the variants here the lua filters to render correctly. - # Ideally, we would forward the variants to the custom writer. - variant: gfm+pipe_tables+tex_math_dollars+raw_html+all_symbols_escapable+backtick_code_blocks+space_in_atx_header+intraword_underscores+lists_without_preceding_blankline+shortcut_reference_links - writer: mintlify_writer.lua - output-ext: mdx - inline-includes: true - preserve-yaml: true - wrap: none - fig-format: retina - fig-width: 8 - fig-height: 5 - html-math-method: webtex - filters: - - mintlify.lua diff --git a/nbs/_extensions/mintlify/mintlify.lua b/nbs/_extensions/mintlify/mintlify.lua deleted file mode 100644 index a1e464013..000000000 --- a/nbs/_extensions/mintlify/mintlify.lua +++ /dev/null @@ -1,71 +0,0 @@ --- mintlify.lua - -local kQuartoRawHtml = "quartoRawHtml" -local rawHtmlVars = pandoc.List() - -function Pandoc(doc) - -- insert exports at the top if we have them - if #rawHtmlVars > 0 then - local exports = ("export const %s =\n[%s];"):format(kQuartoRawHtml, - table.concat( - rawHtmlVars:map(function(var) return '`'.. var .. '`' end), - "," - ) - ) - doc.blocks:insert(1, pandoc.RawBlock("markdown", exports .. "\n")) - end - - return doc -end - - --- strip image attributes (which may result from --- fig-format: retina) as they will result in an --- img tag which won't hit the asset pipeline -function Image(el) - el.attr = pandoc.Attr() - return el -end - --- header attributes only support id -function Header(el) - el.attr = pandoc.Attr(el.identifier) - return el -end - -Block = function(node) - if node.text ~= nil and string.find(node.text, "") - :format(kQuartoRawHtml, #rawHtmlVars-1) .. "\n" - return pandoc.RawBlock("html", html) - end -end diff --git a/nbs/_extensions/mintlify/mintlify_renderers.lua b/nbs/_extensions/mintlify/mintlify_renderers.lua deleted file mode 100644 index 2597fbbf1..000000000 --- a/nbs/_extensions/mintlify/mintlify_renderers.lua +++ /dev/null @@ -1,3 +0,0 @@ -local codeBlock = require('mintlify_utils').codeBlock - -return {} -- return an empty table as a hack to pretend we're a shortcode handler for now diff --git a/nbs/_extensions/mintlify/mintlify_utils.lua b/nbs/_extensions/mintlify/mintlify_utils.lua deleted file mode 100644 index 42e8776c7..000000000 --- a/nbs/_extensions/mintlify/mintlify_utils.lua +++ /dev/null @@ -1,47 +0,0 @@ --- local scriptCount = 0 --- local printItem = 5 - -function codeBlock(el, filename) - local lang = el.attr.classes[1] - -- scriptCount = scriptCount + 1 - -- if printItem == scriptCount then - -- quarto.utils.dump(el) - -- end - -- quarto.log.output('---Code block---') - -- quarto.utils.dump(el.output) - -- quarto.utils.dump({}) - -- quarto.log.output('------') - local title = filename or el.attr.attributes["filename"] or el.attr.attributes["title"] - local showLineNumbers = el.attr.classes:includes('number-lines') - if lang or title or showLineNumbers then - if not lang then - lang = 'text' - end - local code = "\n```" .. lang - if showLineNumbers then - code = code .. " showLineNumbers" - end - if title then - code = code .. " title=\"" .. title .. "\"" - end - code = code .. "\n" .. el.text .. "\n```\n" - - -- quarto.log.output('------') - -- quarto.log.output(code) - -- quarto.log.output('------') - -- docusaures code block attributes don't conform to any syntax - -- that pandoc natively understands, so return the CodeBlock as - -- "raw" markdown (so it bypasses pandoc processing entirely) - return pandoc.RawBlock("markdown", code) - - elseif #el.attr.classes == 0 then - el.attr.classes:insert('text') - return el - end - - return nil -end - -return { - codeBlock = codeBlock -} \ No newline at end of file diff --git a/nbs/_extensions/mintlify/mintlify_writer.lua b/nbs/_extensions/mintlify/mintlify_writer.lua deleted file mode 100644 index 9fa2d7110..000000000 --- a/nbs/_extensions/mintlify/mintlify_writer.lua +++ /dev/null @@ -1,133 +0,0 @@ -local codeBlock = require('mintlify_utils').codeBlock - -local reactPreamble = pandoc.List() - -function capitalizeFirstLetter(str) - return (str:gsub("^%l", string.upper)) -end - -function castToMintlifyCallout(str) - if str == "caution" or str == "danger" then - return "Warning" - else - return capitalizeFirstLetter(str) - end -end - -local function addPreamble(preamble) - if not reactPreamble:includes(preamble) then - reactPreamble:insert(preamble) - end -end - -local function jsx(content) - return pandoc.RawBlock("markdown", content) -end - -local function tabset(node, filter) - -- note groupId - local groupId = "" - local group = node.attr.attributes["group"] - if group then - groupId = ([[ groupId="%s"]]):format(group) - end - - -- create tabs - local tabs = pandoc.Div({}) - tabs.content:insert(jsx(" ")) - - -- iterate through content - for i = 1, #node.tabs do - local content = node.tabs[i].content - local title = node.tabs[i].title - - tabs.content:insert(jsx(([[ ")) - - -- ensure we have required deps - addPreamble("import Tabs from '@theme/Tabs';") - addPreamble("import TabItem from '@theme/TabItem';") - - return tabs -end - -function Writer(doc, opts) - local filter - filter = { - CodeBlock = codeBlock, - - DecoratedCodeBlock = function(node) - local el = node.code_block - return codeBlock(el, node.filename) - end, - - Tabset = function(node) - return tabset(node, filter) - end, - - RawBlock = function (rawBlock) - -- We just "pass-through" raw blocks of type "confluence" - if(rawBlock.format == 'plotly') then - quarto.utils.dump("Plotly in filter") - return pandoc.RawBlock('html', rawBlock.text) - end - - -- Raw blocks inclding arbirtary HTML like JavaScript are not supported in CSF - return "" - end, - - Callout = function(node) - local admonition = pandoc.Div({}) - local mintlifyCallout = castToMintlifyCallout(node.type) - admonition.content:insert(jsx("<" .. mintlifyCallout .. ">")) - if node.title then - admonition.content:insert(pandoc.Header(3, node.title)) - end - local content = node.content - if type(content) == "table" then - admonition.content:extend(content) - else - admonition.content:insert(content) - end - admonition.content:insert(jsx("" .. mintlifyCallout .. ">")) - return admonition - end - } - - doc = quarto._quarto.ast.walk(doc, filter) - - -- insert react preamble if we have it - if #reactPreamble > 0 then - local preamble = table.concat(reactPreamble, "\n") - doc.blocks:insert(1, pandoc.RawBlock("markdown", preamble .. "\n")) - end - - local extensions = { - yaml_metadata_block = true, - pipe_tables = true, - footnotes = true, - tex_math_dollars = true, - raw_html = true, - all_symbols_escapable = true, - backtick_code_blocks = true, - space_in_atx_header = true, - intraword_underscores = true, - lists_without_preceding_blankline = true, - shortcut_reference_links = true, - } - - return pandoc.write(doc, { - format = 'markdown_strict', - extensions = extensions - }, opts) -end diff --git a/nbs/_quarto.yml b/nbs/_quarto.yml index 37fb3652a..60097036f 100644 --- a/nbs/_quarto.yml +++ b/nbs/_quarto.yml @@ -1,8 +1,59 @@ project: - type: mintlify + type: website format: - mintlify-md: - code-fold: true + html: + theme: cosmo + fontsize: 1em + linestretch: 1.7 + css: styles.css + toc: true -metadata-files: [nbdev.yml] +website: + twitter-card: + image: "https://farm6.staticflickr.com/5510/14338202952_93595258ff_z.jpg" + site: "@Nixtlainc" + open-graph: + image: "https://github.com/Nixtla/styles/blob/2abf51612584169874c90cd7c4d347e3917eaf73/images/Banner%20Github.png" + google-analytics: "G-NXJNCVR18L" + repo-actions: [issue] + favicon: favicon_png.png + navbar: + background: primary + search: true + collapse-below: lg + left: + - text: "Get Started" + href: docs/getting-started/getting_started_short.html + - text: "NixtlaVerse" + menu: + - text: "StatsForecast β‘οΈ" + href: https://github.com/nixtla/statsforecast + - text: "MLForecast π€" + href: https://github.com/nixtla/mlforecast + - text: "NeuralForecast π§ " + href: https://github.com/nixtla/neuralforecast + - text: "HierarchicalForecast π" + href: https://github.com/nixtla/hierarchicalforecast + + - text: "Help" + menu: + - text: "Report an Issue" + icon: bug + href: https://github.com/nixtla/statsforecast/issues/new/choose + - text: "Join our Slack" + icon: chat-right-text + href: https://join.slack.com/t/nixtlaworkspace/shared_invite/zt-135dssye9-fWTzMpv2WBthq8NK0Yvu6A + right: + - icon: github + href: "https://github.com/nixtla/statsforecast" + - icon: twitter + href: https://twitter.com/nixtlainc + aria-label: Nixtla Twitter + + sidebar: + style: floating + body-footer: | + Give us a βΒ on [Github](https://github.com/nixtla/statsforecast) + +metadata-files: [nbdev.yml, sidebar.yml] diff --git a/nbs/custom.yml b/nbs/custom.yml new file mode 100644 index 000000000..1b2c854c2 --- /dev/null +++ b/nbs/custom.yml @@ -0,0 +1,22 @@ +website: + logo: https://github.com/Nixtla/styles/blob/b9ea432cfa2dae20fc84d8634cae6db902f9ca3f/images/Nixtla_Blanco.png + reader-mode: false + navbar: + collapse-below: lg + left: + - text: "Get Started" + href: examples/Getting_Started_with_Auto_Arima_and_ETS.ipynb + - text: "Experiments" + href: https://github.com/Nixtla/statsforecast/tree/main/experiments + - text: "Help" + menu: + - text: "Report an Issue" + icon: bug + href: https://github.com/nixtla/statsforecast/issues + - text: "Slack Nixtla" + icon: chat-right-text + href: https://join.slack.com/t/nixtlaworkspace/shared_invite/zt-135dssye9-fWTzMpv2WBthq8NK0Yvu6A + right: + - icon: twitter + href: https://twitter.com/nixtlainc + aria-label: Nixtla Twitter diff --git a/nbs/favicon.png b/nbs/favicon.png deleted file mode 100644 index 9fb85089d6ed81fee60833b5637849f4345291ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 208747 zcmeFac|4W*|37@8m?<&ZP^6JWDQosHr6g;qFeS299J24uX-v@&g_5i#nIcPM4W}r{ zR>_imCwtlV-|Kx{M>F%8?|uJs|L*&7e}0d1JsuO|oa?>3mgnpFdcH5mbzN<>b!)b) z!7yx{`cc&r7{+lM{r3Yi{AAftN(sLFc=@QIBZlqUf&OD~OHg*fu]]):format(pandoc.utils.stringify(title)))) - local result = quarto._quarto.ast.walk(content, filter) - if type(result) == "table" then - tabs.content:extend(result) - else - tabs.content:insert(result) - end - tabs.content:insert(jsx(" ")) - end - - -- end tab and tabset - tabs.content:insert(jsx("MtkVqK29o ze#Ex_L{)iC?#uptdtm-5jkE)jYvHbcT$F3$3jg>4`X7p`rp3R0c#!@xjBW#rZUe{+ zdK}PgfB=#n2Xq_I;{aKJ9tU(A;9)?=M0zgZfk3Z~bWEgUA{`S63(#}n|DasR8EU@5 z3j3jMCl7jhtzIw2f16>&%`0EIZoOOi_WResqyLtbjy#n3{`$%{J5F$~e7o|M!tof* z_>YU~e-epd|F}$4cQgIt2k<}i< $mK}QvK~W=;{z%yrOsL z|AmQ6*VgF#ie7^M8%r=fbLp8&&s=)uVsurUu8PwS$}zesPFKb0V(EW_o@Uy|W{$)o z=GilCU3+e#Z~uPL6PcdK^hEw|NaVj~E&86Gx%AAXXD&T+F?v`2zo#o-+8 MD=+Ylu`lEx){~nO}8;hd@3msVKz(NO>{{~>$?lPi+euvEDX3^w AxaP|7AD&FT2st6zFFPbV@*{1awM3rv%U` z&?y0(68t}=1poIBAklw|hu(V7afbdx@&C^rXA%!DIlA&J0R1!8=$}wW{{TJu#}Cp! zypjIdlJsXb=tsTuqh9(^Fa5xXt`5;ZF!}$(UqabFHPR c44y+)u~<-R~V#{rBf_ui^OjXL-{H#0^ZhA#Mf=J#270&@%-$105Xb;DB2I z|A!6^ge~acfZKr%4!9ZU%z+LL1TNtJ(!l{Y105W2Gtj{SH^cu6%wehC6CWD=)3BvF zyjY-E)JI<3VUDUC{emhRz~Ymy?J)g1R$ss7!@z3GmA_#{QQMkaKiDdX-&=iNnyYv4 zkXu vUjEz}f zXo)xDJuWxqhWo_I27N+@3z}@|-{t!cI)~&ZeR ^@umGX&W`t zW~rAH?jBR^U8p1m1J=tK=Rf6z-(;%x;s}Z`=M3ULBGoHLikEDf9OwUy*dnY?G2~DD z&udMj1(a$^#} BzqMwgSi1Fh1oOp;ojDS2FMV%=@;< zXU$v1*!dxT$$+R-PNPH^xZzMFr9#?4{`&KQ^x1tMcT0hn-mB-|>^2{dvh`_M%35r7 ztn>-(wjE#e7+ >P_u^r>B=}KeD}hUi#<= zhPC?#_LUFc&n)ANWt8w596V~hw$eZurdW9F@?+V>kdEHZ%w`^?rZJ7uN*U{_MM9c; zyu24PmRF(CUx*O;%giRyhIWCn{K~$;n65D)e(->bAsF{=DwBk1;zCL!+E3D#3$@N$ zV9VZh`}nvYJ$;?s*5-20vaMOrFyX1FzWQl7W6`-A_}@7z)u64q+(xWyAAi^7){gn8 zZi&5OU5^xD$#Jk`lA`6ju**Bg+{*e}+}0Q1r?Sr}6&GEewiQQKUAU>Q!_RY;cAEMeb~J9^)>1{+Zwh~qh2rX&+eOHd807;d6&T&_2lDU`jjH6 znjz(A>5g3Rn$?HaO?F-4p+CG;%qCs1ytVlrhZOF{T>?aqlufzhx<>Yq>J9t9#0rF8 zycLn(S`71+S}7X)aLY#vxVJcNo4HQ<)A`osi1Z-%Ej>0JPaVaweFEc;+Qc5N*2=yW zak#2JAO$|$09Jd2SZ%x8@IeWybh(?OKUTnxMNJirV=Ou4pDXp~wmf_q&k33SU|a-V zVUJv={jpQLDK6>m;L?0lrH5qS;2^#LjQTU7fwkxSP&Ved$`W?7OEN}O=b6HbseNTh zDNHYG@~fw)#t!cLc?~td4T}}bp+j{YtsHz=^EP$&U@NEUFQQeMRA0xRG0-*6C)s*- z%^OE2c8qx+3n)K3wGF~TmIpk~bxSX(UMnOZlUng)R0zVsJ%745)IayMYv|^P+_$rH zdH8y `nef69g>^$WnliWch^9Q+F$ha& zzgWRsJhX3%dz15Kk6f*_6*=4SaFnKvl|b68*rdod^!0>oh?izloLjvoI4_RxXYQGu zj1ZgD(Wa~BRUt3F$gT10Qz8`zi=n8a9w&?)ckQ!DzTsGERp{mBtjG<@y <&R9>1NuA*7=o_XKu1lbBQXY{pCVM$4De_7{Q|9YZ&V=k_1?0mH^7em8G7#NVng zTregrFrGCk#*;HIz^T6P?0S@;RPmqifNUSjZ0b`In9U#L8Izq>S9(O!JnI|-u{Fbl z63K-!EOJm{?1XKG+?eZr-luaxaPx~lKerqGs` `wSnhWpW!tq8sz@Z?`gj$ouwe zN!>Hp^Rwqqa0BLc>;e9_42Oz7w~LhdHAo%hjScn66z0INsd~3Ur>*is**X{Pxvi~X z<~SoUhdbT4>1;#KK3r{i+FK1RiK4s<&kw54JqS?SE6M?PS)E%1XK#*A9v=M#UN=`X zW~-@tFlxGYjbEp9nMFu2#PkysBh=I}?YoOpI*o^aCbj_XBT9}*(U3G-q0YA_<5FWM zN ik*z1@n)G4w2ruR<|-M@oerF2e9EvYab-n)EnT^0YpyN)^6rxD|m zcx1!-WeE#S>=a~T=Lly2n2?AOt?tCO@`P5a?@M_Uk1w2h{L-jz+s@gW-Og?2+snLA z!c3!t!7!gAgvXRh%-hA$PTGG&sJvxDge~o5dY)GP@uf~EB$K=l4?&dampp#e7e^gA z3s`X5`uXGOIQGrbmp$G6C!ec1Q1uqBfi3Q3EiL3vi%`$ahHVZvoIsPk;|T4LytYH;9_3@opBatJ`A?|Ee;>mi96uF&&jIT2(A%2QLq41M*|iRzZ(f=rR$ z#EWw(yqzJFYy!%>-0yZ2KQGT&UR7AxCs5DLY*~1+6aqy1Vq`HZOTY`!eOE}PXCaVb zBoo?5l2J!w0zx}Fa+}S$!oR+RGX+m;3FE@+q3^F$x>by2ClBV2hw3~R25a Dz}^3DsBU2>1iODkgq-so|mN5S>!=gbjQgp1CD7_n5=+GmL?sv_kfD zp};W?ETc}(-0gmcJODUdN$`)zTIq0ZrGatApI; S-nh4308mfWlpE|XEe+ZOFW)|Hb ^{?1t|OeN3Al{x1v zX&}oc7vE(~vj~KcNK?M%dpM;th9{=j?3(Ld#Tp1Vto<_=0Z{YLD=n^t|G@r-1|@Yq z%KTo6@ku`zJzGMM$tKrNpx(7_SH=M3T0>5jduT^Y^Gp7*1*KiN$LgyIOLFlM+wjWI zlB>FGdWU`9L}ua6`Ll0+bOrYo)ZVRd4vFvFNJ*TD>i#ye(48d@K_UHsloE3G4UF|s z$&xGF5KRe3dD{r5%t#k&{H}b;3Tqn@FV^s{NA?=qpClfU#3i=crKVIs9~KpW7B#bv z -Ne`pjL})bdGQK-TNx+$K)ANzOF(YK066 zj9xlKA$L)6M3jC-xRv~r#3t$0JYATxs)0xJXGTo7>MpC8!yAZ~1|O2+?QV&(U+jMz zbLI;@`)F`9i3lex+R7cjuV+kCNigEkpz *+AQsuL zeVMiTN@^(2rf^JWT;tlILxqGX($3Jfu>8F8{5AH4R?cv&dQ`l4En$toCi6nYim{jX zU_*Q@0=W|Vm@pOL>MQ5Ny{j&pynTRdj8R(76X~-2NxD?s(tbDZP-HOoxq}PH7Sx>N zH|G2Fm)ZVs#C9LB Aip-oV3U5d _ zcYA}+7QU|-eBw=5cqpmk@T)-qls>1eYbNV!p#s`umwA0L+fSKX4Cx*iSt$8&9K*bd zvg9hoX6EvwSGk=p5`YBAPefL3UnUZ%L5<`X1w+Mmt~ZhK(sbxut%_lVmJ-I=l7V-& zZA`=hUz&xK11uS$>{R%ZlwvlvY3g&IK#kKP&0oU=yqUCRR!S*NF%`C$g}{qAPBxtf z>saO#Ng1q3b7$v%W3d_EFXs0Lw)~~fY4MaZS_?Kw+fzW6T*X*=+hON5X*G>bi_Yj( zXTkA=c@0XqW9a#_y*Naic|zJ3diM2wek$4HsKXsvl3*&lL`KiYky-_EZ-joKRL<-z zlQJ6hmBuIsBqKz<|70Hf25xSNj^%P+jkU8E-{;Q|7zG3wp1j+UJ3>M`#IXIuVgikt zqAc7Z-m{RYf(Ojq7`_%F$M(rYhz5tA-Q|9!g)yyENig>Xgr6uImNwehD+}WR*ioX# zG(z_HT|;9H(NM;$PFi2x=SdZIWKbMJ)8{k_*`};eP5VAumL=8QR&wH+c%mU&Xg$ zRHaLi ~{M(hJk6&vqDUy>)d)6#6*X1I9DV9-k3zkaR_c>pYk!r2YMeFFqdZY!iig3 zs3Tyq2?(7 zXCy>at4j~$0(X{Xj8Qd+SHM^ zIM7g29OQY^wnD*sG+2aCam {pm3vpD0k5ZGyQs#JRDMzb)vk zn2;oo5TXTR`&V3nU`W3ftqW7U^$WMjG;aw$!X-e5owFN#B{0@j!CYe_J|OJ~^heBe znH$dWeU#1^z*Dl&xMteh8Q%}t%1yoRfjpCmZ`36gY%CBe)OoOr>uX`mCbca@6T%;_ zMMKf&buDk5zsYCP1cgSkKA((`ra_#5@vLZA#S2zo8H&E(oqOkXd!0!?VhZh!5YC6e z!PM3ZkrzYQYq_zu{-4VppGR^KrRCcbFcy4MWTMN=mCb%JauC)>5s#<{hwKK6VllnW zA#M8g>=+gk2{X9z?lgQz3L=WFTi&D5`2j=-v86MR$cE-_!Yn33wjU>J&?rXI5u$B? zTk}V;!nQ*p8HfoYu#E3k;V|LZ78>=vYR`DC_*N7gw& nHu31=TxD$fUg2mG{xHjoF}m9&G$r=58X(mlh|zZME}QS% zh`s3x$H|H@s`W07V+*c#x}g|S9cRRil#_zc7TT+c#B12hY=NyW21=+S0njMv71q0L zJ*Ds4O>+-d9|vQ=xwKHl<<(QZgbDXf(M;%e|EG3#&Wn+Tfbmr6$cpfq9KTiVvtY2~ z6a|QvwbkS+i(h{xNj@c}8~ncRsYuQ>428XdM#|`=25G3_ce)?sF;NN}LvgBxiUhT8 ze1Wq;hm^OJCyyYMvTTmm-nbCBdFc;W4COW|x@DwhWk%h;pUXZ2UL^vKQJ&UH+jTDS zHW +>;%RSmu@ni>vJ<;kd&k&flU;aVmX}rL6(jY+W@>5b!7u;z_ zyOWy$xlOF^FvZ)P> IrXa-C){JQ z_Qex6{N_FA=I{-}7^OfQ6|LsdI99A_m=rQ!>%0~-QRWU~n31F{m4R5Q=xf+x-V3)M zu)tRH!YIoeS1+S8jF`?h`7%@IMMh#lOF@14XoA;7QF;;8#1+P15RNwZ;a){}y}D9K z=>=@)j;{dU>3VUDvIxo2{#daM(RZOwD}W;AQ@mD!6Y^`vH#1ZZ8L+e;0prAqfBMoi zuo*J|x@-j)heu$H7NiRf6K$O|w}WwHXjyQi8W!z1b2BRf#c?u1rCkW#us0oOuaoOA z6R&H(L>vY;cqIiu4Z%4FwNM<#{IRHOoTkV_>=46LZ3sjwZY5PuqbNo!asq8TnhE0y zR%W&c`a=VAsr9UOMKE^m^a>zRW!H(m@`A$Cz@+>Tcs0aE;cHY0Kb~^MsFK!zM^UQm z*pQO11Pn;qDr6=*VLe3___^p8aU5by^fi0S4MPG3*r0mL!0vHi7_|iZ$#LC5^SUt* z_$3XY7P^oGFj%c9D5qUdMor+1Wa#WiH86b=6xtQr6&f~GnDT6Hms^lDBA)>>1MRh3 zv77~0nBhq)Z0NqPKz35iK?W?V3dn@E10O7EC=rkApE2r)m=M!glx5Pi4cv^m3DTBe z!6ji}&Lxet_wc?> -h)+U^4t%1dT8Waeqb>_fK<{`}7Y+2MdUxP*jU@;h% zHz-;#X4>AM)1vN7n9WtxlYjGU7G+eCILl6kIshxtZ_ _}7Huu?+1_dzc6gRU)b2ZZo9&jpL)g?q}&TF&;AaiEM zmOBz_HQF$2C#+edY#t2WU^=Q_uYpm9KS-B~3o+?-2mzBv0AOPC9eG^B^#-u47WOZ5 z^DwIk8N5|2kgeW&Ivb+~L8Cnc>;QpJS|5tH5Z})A6z>&$h5q;|vGvhf&=Y)8tFU&_ z1K)l3#%{k*#@owJ_F-dA?CRR
DLU?yBxSUYy2L!?-j z0c#o+Dqd~^Lzzx8EbxzPU@+lL4HZH4adnEBz-E&sucJ*-D7~Oi$j9S0Z5xq3w|iB? z{?U)p`oNT^GhmGjKmv-E+*>gbN5pW4u4jQja6FoUs^9X6#2Spunf#J)MK;&D-Ck$l zCD&PD0_5MALDLbs0AvN~7K^%%k&zYbsd}uU-5Wec9@t(cLUJ^KVIg~xXxVc+d=0~! z_Qs1Y7*#M?$!S@)g#p_!^)ihW8?(7)wR&WbA*=0pNE3JqN`Mj3ezkvz@>-QP&lb`w zU&)3UltQuwu~%d5JG~5yAi1Rzp?xs?bOak)*ZPQLiAW%Z< FzzfaQ1buT-yw{WODDT7>w)V(O-(NnH;e zvG&Mhr3*!WjzE9nbl!j&Yq&WmpawH~g#)+fqOJPl3S_3?-T%C70h`CVPX`TOSex6nw@=^O>3KY`-xCjZMi)5Gz0-TM1%J zJ%nITUMfFeiqQY;oP93OM0x&Km;&ssrh$jcM=_-_Gw{sTbYK@KHkzy;hW!C}8w5u~ zL{5V|Pbre&;gUeh+3^UX60Vpk!u`_&bB2T=U2b-m*+YFExAT=y0~SYJcHLMEP^`xq z|1E>H8umm|P8_sDzzSUCI*~)pPK#1yhhTDRg=2U@rVK-s!CZcW!rm@yX-{SsV=hV< zOhu&{?z%zTH5n~9dzP1h+PLqdH0qsH_M%wRLt#!%0cGa}S}BQL{SnRSe}0)S%tHxd zGX1>L{#q~_s7;tbn= UD zQe$r#x(9#_Guaq~?CXq~7_TEY72Sa9FMeSit{o+p6805zUIf(|zgGzQuvOUD0u(vw zpQw!3hQ3G%f{n_2@u;>&+p8nEk;!;fh~h~#EG-MFB tQNaB@-93MxUtNy{n~u=_YU z(u4LXO(mA>crh|Vpy)L5Y9hkepD+_iw1QSK5hiTjM0Tu;7P~R!2nB4ak_ONKln(=Q zO#;gL=uTgOjLb?@F49oJP1DB>MaE15uNAe3K9R&4{P_q&+1w#wqVLnBzPc^EV$ehY zg~ ;0& ;88fhfGP=8H srAEd9nSLfnDs;R%;)zQ1bg)Q3PUD+FG$XaKHIalujhYRtBLk!yUQ8t-pmr3b zQ`W{_348#@5X1pskLj0IjNQNvVqNz%4nlXkrHsgkWGg}tVC`+q&C#)%kSdh@ZX;{N zHpk>6J1J(YP}ulEPIaGT6yz-Gwl&gz&|gs7B!!r;g>aac2{YjY8C)Ry^(M^bO#%!E z^Y+m|bEh)|qZS_8(dNgYj36c5eG?cN5*GNSD4NwyDzKo hl}4 OPPEVf?hz(|o^)N}L6?yzuoeAy)yt8YGI_nyu_p0l)zE z*8RqW79d6hPi@|kL>ZdD&LylH^)*u;pyF#fY~_n!z}iN)m%$2FV`;p$k_*GUlop^K zMNfj@eyl-_K%lH*!;os&X7VsU$ J@Fw0{X9s!KB z$q(1J?TSG8&5=!1H?DjjegS&r43tXG{JCfb>_ujW-C#X#Jj1*tJ;IAh#DPJYR^F0y zSv3s~X;i>$KkBH?o`evJcTS%xfFZ&<>;?i@$z~`9@4~47L0S|D3pPC(ga+(1(2mBS z5Y)(-AOS(DOb2q0+P|1N*8(F1qE;dBCA3|rErA>$kb<;d>zgjB9<2$a6m+X5BD|mx zz^$z_X>*GVm||j9gawy1Onrc+AHiSV4#a`kCjNz0IArp6OkMStlPSv~=M8$(b5?;? z8-_P7R4(98T>{zoXt_p qLKDatcV%!Cj$gXcr88Z0ODXW z8w15Cb4!?E3B<2%pL59T0oNa)J0pz?7B4Dc`J*3+xSk>!sI=j{CHWO(fMXIy%;ggt zod9Z?jPhE{7%@Ui#&y1^QtTZY)pma8cl}_Q=GLwILW!aSL4m}8p%B28+o++(OnOWw z=T~6{!3>5J` P!C#G{`bb {73(+ZK!cIX~H{%SW_qs4YokY0G)HPStyBIZ0`+9 z7L}-6e>G)PW6x9Y3=!ak%-^X|k2|1xGUx+euW(~&i)>K$i;RI+eU$ctqmd$n5?jMi zkT$F%vdrapy-uhXj`3=QL2V)kQi _7?#m4H18~@@*Zd-`#$R89b>jTHtx!lUi z1zS@{pec!l;_2lT4;6w7YqxIfl`qT3gYu?1(N0in_J0q`0+7MW_|Zud5COG3A5I}U?)&Ja0*$7#r_?a22FUyR>aD1}*)-(Wj`G0iElCn| zZJbgIAOpkIKL6c#X~K}B=C``za9E(V>(%Id33xc9Lp%4Po2w78rdm*r`S5CI79#Uy z4y8C;Udn_c&1$5TDpqm%l?u>!R6}N&*TtVUU=1waqdAT58k5-4DR97%g?71}a5r^i zB?PZIFOov=b@B>CB#_uZz%&U3FM`qv(1>-p-t2anoM*w_kY>(Iff!4 L*R(l`bY|pxb{?D_j=Z z4I#${u9$L>FwTSfD^ko BLKhBFqVKP3-4UUSt%*5kVMU7(H8gTw9F0$TH TG}LfdII8+101BbsNQgjAy-xh@u~om$@F(n1W(Pim||KI=Y`%03={!!S*va8lWB- zI|`sW&4CSN!QpgwRt_VjGDiw%7_{cvL^MtPQV(J-9>=ILbSWo@5%tbxJ9g^G);HC5 zxB+|&3-k~QQGcLGBb-LcP^ECY6Y9Ae(sgfx=)r 5z#xO%iJ_((2Wi26)pMU&(((^}n~5lToP6Hd#1#iUq!6W3R4-{}x4AE5-($NF-W@ zE0Mw|`V?Oe! Jq*tUdYPr~M W9%DLC?u62ujPwD^6HL#VM@P$nVw@oWomi$Ux@&FZ_xgr9$)7{fcwn#pXS zYeTVcu3N|m-O!Rd5p=`v|Caw ~Chl_FpR!7lq;mas&~* zX+=b37VDo&5-5VR_Oz^c0Tggk#h|iif6GEe-8@Kwb(%rt_J6RfmE+rm{EIY=1Rjz& z1)-P&oaQ2&`$72Zm~`3S&Vr8mExDONawUO^L2!NSIWhB?AL0ZeWoFK6po<`sC6g#H zyZw4TIVMaobvo&1W$2=d+rm&gXwU?9fc3#O@D~n4ul=1_ozKLX6<08%(cNyPvOy51 zDF?>xqNcy3-~d)#KK=_Oeas8lA4Ciqr`r4JU!2P1q%CR@+Y@*Ma*fu_Gf>AbM9OfF zOfxiiha;=PQJpc7`!jjp!Sh^cDPY@MTx7yS&+6PRL!h)`CyIq;N!Nas#9W$0zsw=t z1XmLQp&(`qCaQ14x7U dfXGmS5ke)$hwF4&CaK8A;`V71uyMz~UiZaokQ=sg9mzU1N Y>RwO?h E%j{9-gokv~D4`_5 zV;h5`p|T8|COpvf z>AE1ms=&dzoQA_m2nVXnEZ@|~fny(^6>=`7GH=Pe6>&PtCX^>AP|hmSTg<94>hMJW z<6?8|klWFlWTMSWMS?y@SRT&mb&xQ+Zn;(c)lHk9k7aI=x|GG~A<$#tY29hW;qklB zgN-%*Lfgf5OwUVIh-Jt4RPnX!EUq}I<*e^|z *3o>y-T(yW zmmkh9PbqM(F=z1jMflyt-LAL|^88NVkMiG1iIP?;xt(i }|Zk zV>Y#to?J(GS4c*{?E&=D{_P2`R4X`x8Q!-%ijO+t=!XW0n-{{LQi$8%lPL+SwUpS! z5a-OP`dBOk)-il4`J|ue($gLcb1GW<$L)a&BR^qIloRKr_@#S;7*xtF`AxmyM{qeM z9y})Oik~5Sy!86 eo+r zby>AJOo16I@9ZheMg`8~@#!8mG@?qdP-2 6ud`;bv_^~u-$ z%dRs1g3VPfkej04@iI{?>{AZn7X9@;@t9VRo^}^U`c79??ANS){DQD!6AQ3xI?b|s zI$w9RZi`!1)Dy}ObX<@9n!WSgMShxdB5BTPGEmj*V}m7B{c+;FBD{F|NcssQK8~Jd zISey6ZUy6A2jgBy`g&J%9ZOt3>4w9WO8h8*GLlGJ#wl%u9i{^OmJVtRaTbvePIAE; zC_P|XonZemG|q*98?TQ!OTp-kaVNO~{BPjFz$?BSxfWUCg5l2zVG77NSizqsxq|#7 z9guM)IntHhT|6_g9m`AshaWCE>1Hj5sTdnBD=RN6FBsVm$M`qgQ&@}bi92b)$5G#n zEa@eRlY(cz-iCCC>%gTYHSIp!nPB9Tgpt!k-W 9_bCSB;XEk#YTXL=h7Sos}57epi$QY-f}+wiVy7fi!JQ!yc(E95u)q4}4jw z`~%1%(ZW|*s 8m(|tjVD&r92UpT}gP~zn# 7Pg!smi{9Nua2soy$LC? zH}bmwhpTNTk(;Q`^l O9-(Pg0XXn?JJwAI}H)HoCws8zPKvr*0 zv|3|vNy)xxN1w6hXvK2K3Hcp5g4ms86gt;&-|bjilz@h%Y@(&glyKs8{~Reul{>w= zs$(m8xkNN=^Jd!FQ+M}PFsYcq;zc0ms~BMEYMbAws`5l>_=Y!MuAX%rZk~6XpBna5 zpLb+P6G(WatEzdV zneV(Po|AV zSdANjKod#{c*or>wjM$TurkV{I(E~xLhs@y> kJa?nV+qqR(gik*yMktGB*uO9A zy8lt(&igGa=fqtqjrtyjRW)Z=Rhu+*GNidBymC{Gx{W&`$UhyD9Ik$LA~G)&IW%%} z#B+#;%KeCyUJmT5=C_@HH>mI3$-d;Ye8qR0B2z!M;&F5MB?J}e%1!S+HGk``=?iRg zBa0_E_15SpA4u!`iW$7X0Tl;2095l18Kf^`X`KYV-&B($1 pSr#F8bW-_^W>}rR9jv{jH z>p7vsVOsT2rj4#6r*)*{Dunaphn8zC`1w2Aue>~Urp?)Bp?^R>#b!6Q1uPc1qjLzQ z@LP+ES0y+&G91O-UO#2G%Nr~!P|milPYF*xs)%h)J<0Wl|6@GB`u4r>0t;hUnkI2ha1R7MYJ08nVYQnCl|Pcm769^5v?;^Zog3JZI FGp2doha{Jb3JH5DKMfZ`1l7DO4-rT2v$Eh&B=7e}qu}`c;XwYZS-} ze{{9E){&d?UF!gfNGG9~?J(tch3evP5n`+Nx_5@?d{@$_yeN1hR7XiJ=j@LR2EUy+ z&(B|nd*g3)Qdt ?*P9mtWi<6PSAa1SvzGH JQ h+zjP4017Lq+1?&OL36Po#CqPR6kQ^x( z`CY;w=wL)+-YMmoS6hSg=N`1VdsH)k&5~bSA43&Y>G=ZK>rmT^<;UYGF9xr7gnhic zmVv ;UwGU` zm gJUajf_|3rb3%^&>3xe$XQm1!W0svhwo^#~I?O6N zAYBCbl_K%XOt!gSabJ6jf%9}JdDu!OA*^uxH_jLBFJJepGC6+i>V5yafA~8`gktaW zG~%P)Ak+geJC%#qNGiv>i&78>Fq!inL!k{E#~UW!muq{~m$&9yPcL!q-N%jH*tn;* z!~gDEc!q|;)2I(`N}s1TH_DtV@D|~}#^*VdUaM8Q%0w8|K^4)4Cj^PtrlF -L~*4Wf2nJfcYPZ-}F2iaBQZ~h(-FvVm|xAugAXh1S`$; ztLPnPFo-&F-ci-20^t0PmRiYC!f?9rL@}v4sjXmEXuwRds7rwe@U=-QB=^Lw(==L8 z&>3zVh1{>xx|V&137fdD2ob fZose!PMW8%LtrWyQaEx{iWR8i9 f6i#Yr1+laXK`q1q5b}8V4(wsd{##YVcq;kw^zzbJ zF?&(w2U|?!;A1f!jtu}GX(C5BeY%hzFy2G7e0&-u$lv)9Ld@eA*nq#kteeSL$(|#v zMM-nH`qH`UFh9tYc#d>ol#>$u6!f0YVa#og<2(9B-7YPc^Lg~&=iJ}8i6RKZ1Tu=? zX|CtPYRm~!U6v(4->J}HOMw4VScg+aGHk`uCFMZJT04)XiqLs&YX=34{{ha4-B2)_ z>rNlZFMxODTlUqRbEqlqJ6tm6%dV7@_hAI%saYWor0WiiQ3S&9+#qr?@AXmDp|`w@ zaa)}a-q##H+3}%CM$xLXzPe2=qaH9u3uQisICtx>Y}k9Ue6sGNtX|~!g<;oi3&Z|y zvrO!YV(*1kW6oh~x=?CyK?#%RUkP9j8l&fZchRbXv%I1^i1EFa{9^<%(fUOlzl$!{ zkH_5oJP4jQiwyMV1Y(M*L^@x9r4(nWO}|)L%vPLB5>DtiqK?Tz`U6e>tEyz 80Qk6l1tQQiD7)THGN~ z%<`@J>IxShsg?3~26~R WWpKYp4Ni zxhqO^Q9d;Zun}cfMd$YYJ);MvwhAXm4jx&J8mbF4JgHPInIlMxi8#$E1>kelKI(An_gb>( z{}wJGCe+8&-F8us|}^2Fon#fscf@0kxRV5GTY=_hzmY$C?e?!R?pL au1#hf;?WALRMh%k z0RnHkYQ$bN)V;j)gzVLSt0hsyR7$0OH!Akabq?%s)IAZoZBN)^cZcQX^45uAwN@UE zBDcP1SGG@0>*GpqsFmcQR`GM4P$G>^nmnd?W-Da8YI3lDM1?xmIN-0AotJ~M-dCom z_n}VAcpVF0>wz5qy;xrDNg d&W6*mnY!X0mtFyV2(LPxu@k}YQ9OIwq}vTy#mXZ|Dx`E$7M z%N_gRw#vC=UBSa8FT j&Z?d4#GDFFoEPE;?yS`-fMt%n656%% zJeq4_6;V+p9yx5e;r|8j?arCDjqgN+hFWr6D(A@^Ow$KuJ_!djY>P7kf&@(D9U>9U z9!21=X`5f?Tlth`)i}OB;aeK>W12K&aLUE=9w=+R#Jh`*v;aFxb9{N7T1gN@#T|_z z=nr_NXLz@2FMS$p^=M<#agUdKzxL6qGvy4}Ty=)6|9m2 bb1f zdV$U9DY%7$a7)GK k){qA%ZqNzOS{N{Zg@z#}EA0R-MZ zi}2?%nz@08*#s-ia#;?In>ozj<;;N#)ee&y5N_9Hy!#*Y+04Hu8>k9Uf{p{*-vMz7 z#W*wKV1(7)rFY(*RYhMvcrTYu7cDQ=3>;qFzXgdyfqg*?)Ms3VGbCb;jkGxm9q#%2 zYXHYH*bQVKfQBXYv*Oa*y5QK{yXBa}9@OR8yRS^JV>6$oxU7BO$oQzY$5d^0vqSkn zydCy__5Ve2Nn1~I58u0sB6x8zN#FQR(UWw3w4$-^+_(&Rxoh6?T&90H!!u})pyc1i zX{&IU+(dT`3sjeRzkH}Jr`qOQr )9EM=Z-HG z4Nq6NL7=4r`XlCpf>~NmsOD3QtI~eYs!gs37L#P!yvD~q$gJ*H!OII0+wP$9a {tlB)jJ?AWR;n=~@_~>tHkmOZ~fX4C2;1Rz0 zIp6uJdoeLe!~Ky=PB%}Sm*wAA4Rcr^r4M+0VH{B;m-MtlIqc5^x=q3!TyR!V$)=Pz z*HPrzzBSgThyMsua*k<2o)Z5%T>G?KW3f5cs^sh+FZYbL%-4CkRu|4ainRUJd*UaI z7n-lXb*q7dbQwcbvN=6DQjq^%2w@)W` F;&S6)#A`hH zy9-ihWX>$5mX9=k{axlBlOX~aRPt|fgRXZ%sHQo_uTqOcXWLQH{QkNY@_?Dg9t z|EG?X; gf%E-E%TB9fP9p~|z>esq7VM-P7% z%LPLu4{noSf?5V4kluIRacflM3-a>eX(jJ5PP?3rYkC7u84c|J$G-KZFA)U({z4#% zA iJMHh~vILOe6&Fd{EFI-U=@mR<_TmoX0X@ZA`+gnyFZW$I-0xml6X8EzN zFtcdBS=(U_``+xL#o?D8Nerhofo_aX&spO_aQMCj_!t$q=0b@1{uEBcm3*dtzBLvD z#+hNjB~Rt^`Fwu7A@y#~VpXZWC_fwZ!KOW@aH_HQszl|mdqcC?a_k>RIXu}OJ-3^G z*(#$}5>anVUQ{Va!cM<+`%43rx #H8pYP%>OPXG+PL9jjxP z7uVY6kBfuEu%`@nn2>PTMO%mpX+t5s@v*|p^QQAlZGrxh14cil4IR5$$&oHj1D<#S zcvNhO5O3Edjuo)efNYz98hLwF@fy!$)VBH5kBahdQK NNr-QAe(pOW(VY(VbXQ07t)C4H;+$Np<8uhslAIkP^L$lMv5ogFP&h_i+B7aCT z2l=#u^IdXT)GA7y5m!%lQ5*gc1tU@Qbamuz94@JA7N@k{Vw-o(7#xhz7pj@z&Rm@| zRhfL?%eAlNK9}d?lOh||#HBz@-#C6%0?&dyYb@?Hji=?7>k8>*^qC|VbjEyE{=;7~ zwP338ibp8JoeL5md7)zts7@p}OhS8=zfQ#E1sef=7od_(MVVvl0NSxN$G~3H4a$vU zud0_4U7J1Tp*3L3H04(`XNI;n x`}d zMfV%lNpw_lUVhm&`$nelYsefYCiNJ}Y+5UH#c;-!4{cBOcVc_8cMx5PhnHLS2!|Pd zjOu}P%YE_O!1**{iJB^9&rQ_ K%9!Zu7)^WUKr8bl0TK6TW`~n zH+gtcbd~HiRKeZ=H!(2`1as1GQvMdroJUp^*A}(=6(4((RcVDR#%ocbHKS{skH@yt zfdcgfk3LXeNRM sH-IH?{|q&%{n$K e(JxQl8oxuxmtyDPY;@;aJ1`xxBS)%LROjUdJ|=QItS`_cJZjeS^~8 z`|$mW^l3#K+em17rz&1I1~*5xMxF4Ot<^U^piBOVdR*&pNdVB6IEyn6q6BFooc1HU zSYw;52u>q!{KuP}d;L;LZs+b-JVRwJd$3i1;Zvf|;>SokZ@0AT_A1N3<(v_6ygzpl z>g_Jhcb^pPw- 6dsWya>IfCxBTyx z@viQ-0lZgEG=iuZ-=*l(HK<)Mz^) El9!j9Gu;_jFRxFdEEeq9~6>;3n*@ETa08!jbr_d^9P kSV(eN0zQlh!`itBDoRDthiVv{ugU8a_f@kQ)t5vioNF3t^bv(a z41eDY-|D8RE3PfGulHI>r>}m`0?2w XQ!K%3an>jE2AEjfG4*Vt2})nmEP zZL+>_>Ur&?48z>%$Co`+HG9@EP$jqn92#l$!f7pmJ!vO sof0 zoOh{yTwT;#$=B*qeh5&&8y!Wy1|8;J#c?>f+;vr=v;lyJ7ZC#Q?XMs66{cQR2L;r4 zaX_DCz>aw$8gIjj3zSqubELkXzxE3fI2*U0;7B(iiVpAfOR VWdw?60gKtN#dPvqBnaY*>#itCZ5x?n@Ob%G`yJOr z!=2M%HC6s_Mk)!CGB<$0LX`IIu*ckPLv^=emp+azT1 X4?Hk2AoP$6_U zi)LQePWoa8lKwhcgsS`+Rb@ c4Ri|5znRm%osimR{rKrc6g#DWK*^2E-HkQM zUkBL9R!vM0It3&N{&Tq0JDi}~+tB3X2nDV+*Fa&m|10^<3Hb~kp*R-U1R>wtKCT@} zQ#);mBYx~o8=(su$N~JwBsQUQx}ezH`EYV?Qr}Xot8HG}*2?=VKnCz84V95S3AypS zH2jeVv8VSd)75o+-fr#9)!rkHR#Inwn1DLss2UZG>n%b49|$ooj*}L%J*V;00ZY)X zOe}!5`)Frxe)nmKt9j|ROi{ma+c)DNh#?C+hHP++LR#Z-F8{`>63*58-|6W;Iv6oq zBRtZWKQO63s<<>no((6 }6}uk2mZvAo0}at+hGKIv{$6wd`ktbcdHZxA`H$N%_VEInv^ z$3VSDYBPsEN|Swut*`D~WAWgtj*yA~|?}C7eDA5#Rd!9zQyzxq}(CihUt``nF4z nuFFP;|CYZ`A|Osb0T>MR*oTKu9DTjwV9 z{=>1W__IocDmb~e?J=JI<(fpeWWq5fI=+r8uR!xSHstoTEY4=zlH0cWWWSV%^Tki% zxT E0sgt4U-q?3eGMSbeATGFkj6tC&hrcIfbLub zV*B{9TQSZx$-2G%x!z~tG*CSJV|&qve8+Dr>^#{Wp|K0yDqUKXpcA`U;V~P)SCIfm z&U5e}2VBWN(a>Cbr9cMlO_&Sb3!z}DmAd(zh{5yavgg%BUqjf9T#F9?+(dte8xmNy zLwb!xjG?p1KJCSc4b_YJVIL!I$S}%RoD>RP-M{*8%<3EsY#Qx|W9|Ws`?^PfqE)XO zDjeOU?AeoQn>*4p%_^P4^Y)>^V{O$ELtF(p2UWu^Ubpw=skO@<9w}qb_G}}!o>BUG zU58bs^{4(H;IS~&CW5B(*TYNL9F65%$VLx3?7$DaFFQ?cO9K_6 Vk5Rc?tIOfH**N@Hj$viz?zK(v;`a+HsSB#8N^EhOmI=c|M>xK`U zizq++`bOn+!YhNEdY1mx3Z_f>4#=Q!>j(r_Ve82}z+Y#j&A{^-%2jWw-Q@?+8D9#B z@obY>ny|86$Zxx3DVO#QuU2r-jh9Kby;=}uC1 K %NPDjnXvRkg) zbf##wOYdGTkAb)zI<|l(2^){z4?GxQIi+|6XLf(Q)KPZ+wo^Dke?J>jrWR5hu1Wy9 z=CviPZ6iK5mPC^P9QM!zhdD!FbXvx3?W#qPcRWRXAHoYJ-eo8$O;+;yRt7TM(TB4E zMA6X$g%D0bg& aB5EHA2nP2m` wPLMmUe*x zdf$Ng* yEzoK5~ykGP6MA2%(UwBcBk-&Dl)f06d)@l>zf z`?y9GrJYJ;D$3AAgpAvXC*V;MH5fd(XG9!f~2P%=|QnRaEKL*`+dH}>>f z@4dG==RBY1`+J_x#~ Yu#_mBm4mE#ibuM!)oJ2=kL^_JsbJu zZdi&Y`X |@!mgk(*+^-RY zC`DOii`R9%2Bv&1^VUbfxBW60^rM)5E%FiAg`6FdZe91Wa-=`YmZtsCo(74WKD)yZ zKVFB*oPYW83_~>A$wv*`S>7urd0;x$Hx9mYGt_zg*_fRu?5z=LOwQtc$_it>9TSJ) zU%jXAMlTb)<$>^cWL}Ib1Ul<#O|H1Z$k@ M1|m1CZut B`$r+b mrVlUubf<)o8B+y$36+_N;h>#0C$pid zJ{{(;tuLQqBx5m{W{1+@+SabYfT1^={xS&ZkpvQza@{3>v86C5h_M|ZIwcdi1T|78 zW+er4`&{DA@)Mw2JeS%1H{F6GmL?#KYy@$XM~UYOF!&K50lNzzFAiZPhoVlF4M_%d z6XPkZ4x}&f60BSOLAjt>uYiY>Vo*qN8#NH&0*;#3#1_O3mZ18r#Y1E3Qi!93UJ6-j zU(y;7g_IO-9hDb~c;LT4lVuqe=u5T-WI`s3tiMBH{RB;qs3nrHoLDFL8Kt@$e5}#IK{zn+b(R zVkEa9r~36d9f2hTQ&Oqp+}-k^|Kl|Ua(_xbItJuSpss#fX6c+3E<=r2vG;=A8n4t< z4WWw`S%Jk5fPCVO5@lS#VVn5ckGRW2FNEC(CZd?Q&hZn!dw|jAt2FAffvV_-Nvvn6 zz506+P2QZYCUnBIDAhlf(tka-{K|G$4Kz-d8#IAc=+sY1E~Mlc6SIX(7808;*li$L z%d83tNhjUfe0k-XWV1AeBG&Dy;c&D@1|jDht+ZlRn%4<=x~ZJAIm&T9H381r&1m1R z(Zm~e^lxSlYqW+*^1wB*0-r>&`w?mZHS`eH288#a{E{FFaj!0^>Y0$y0 $uP)#8Cw{j;;R}4IEn2H*U2DFOsJR5$>MHd&+j|5A+&n!ynn_;HM;G`P)|2Y zx@~D1e=Gzv4=s@gp?KEcYG~+G@}4rq5<2;wDVY8vxSZayUxFr42-4}X`w<8>(U6Ve zcCt$!(O&qXUN05Whp*Kt8wRr(N-j(BDA8m;hA4VPD7*w>9MFBU4+v#zrGf_{sNU*X zr{%CrE+YSMi_T}hZIG=g3w(&m6iYNU1?JMJiQ5YqCDz&aBiXR=E6&8V-Qv!IgpZu| z;m3Dp^`MWTYW^3gHP-kvt-Wy0UDY&Vk+7mIG7J_eIT#q^xm3hm`tvd0albfZ_!ERp z%T>CMEe-x#NYwyZ2I>yqKVBfMQ#SPdyb$NBGSqx9qU7>{<_1dcaZd^Ay=-R`o$pT~ z7C;_M(?}*+#z{Ps!X9pJIA&SqI`v#5S!fGH=oTB-=@k1Fhj>DGR#$f6gA-pLRq@hh zb>Hf$IQbDBEBz{Vqv!s3UU!1=Fu1Z`YY?&tHMmC@Pkh9EG-keLCHjweP jKRCb`(mymysNVScd)%i$HPqxFj^x_ zG(
yJ5Z)$ah}6tD+dx7!?sX|6%mh}6~)Wc`v)x)RcN6& z|CBC_$V&sN+@z-WmrF27Gb?LaJpXJ4O)QIUTU)3JB;g@^p;%-hpre}Lz0;BRXu%%~ z54p~*`in#1LOvV00ZptxGdHoUlYKc)$#ugyK8 ^-a?PQdD|OqA9M{C2 zOWR}}S!HqJxIn t~xBC0#Ca5FUmPo1`){<}pxchEoogbVwdSP@^5PnjqI(HpT%zA)35 zG}O^U!px1=axY_rN?(_23kN*o?Kd0agDc4?M|08(mQUn)w%r~r@F)x)zo?L)Iy}C< z=J62?%Ynw8GCPyS8lj28w_PO%B2Z!9$^NIfKANww{NvE;_6JQDkZ)$FV5Ql@xv!!) zANU(;y ix44#mn^$-dFKeW_%n${ztSV)|7t@JR>F@ zMPK~MyVUDf (cf!6^Z`?J)qJ)~iom?An!?H25jbw}~`N8hs-Wc68ztGKoS5Qarm~y2U zvg_6 q^?|GBoYLh(rJm> )S}?;TD`^3Ol+!p^{aU5sZ4mX7T8<7XOsk$*>6G*4VrJo?gpoznA2){z4m$u9B< zsu&kONmxb?*6W8$eEz6D86BH?DYF@0eLJD9v=U~Dgw^zSBd0PkFCTd!KHz*jUf1I| zW{ACasY=$E@9wCkAjFuV=KD3}XX_k@Uw0s1Wp;lPb?n|pU$ Nz5BSEb`dSId-V9oyA*Skj)GP1wOb4;a zBy?G5MsQJMD!6bfgHr!W0Jjcxd+YYlw)YLIc5Wid@hE(y|Izg|KTY6Ze@Hd%fP?+> zoisPu1+!3FTejd4pPw#oD14&k-Ab^(yTO jAXmtdpMe>t2Wdl(<4y(YI|djgIQ)3~wa54pOzTZN?yQHf-20;8?S>k= zz{!GPZZ1k29=)LJJ>H@|@g-~1XqfH7J^%az)N>7&-|H)~) 6zX5s;TPY;TM>d zyw;K_7hPwYwS3**Kn8`#z3*zMotw1!t;+Oo-Pt_htawzh^4geA!mIo8kv+6ndW*z| zk^3+|=IWGs7KLT`(t(Vd8Quas&$RGx#nL^4vBs|S%cjuL+adCiF^iU>5CFO=Y~H |ljVOO{`b<%9#tE#g}0 zFDsay<@TtzHOWmmuO+O1IBD7cRWkCO8A_EOt5^ OC}m| pq(S)}3;nD0LqmUr+ctP@ z7YH%bNKoxeZQmT)K0nhPP9cW7nXXi3vX#Gl6}qi*rAUsU5jS0he~f&$&t86-GwS-{ zS{?_g8X`URDkRS^ZN=wd#ePNm@J8eSZm$X)sY)8{s!z5PmK!u6fe92+2$PUi=Mz-% z*(M}sfR5VKcBW8$ZlOt1h%BS`XcfD|&V98%UxzMI6Rs(PLHI4ZM5!)y=zD^J4%8{H zEzhGI4+BtN%I%cnKmz9eE73>r)vmFmnoB_*6c*xQ7G @h5gmXO>Z#5IDS=)U&pz zuNq1@&K5)1ufg{|K|V51D|fFzuJ^^=R_BYj$UWz|mRs2E^ZOnW+4nyfT#Yqb?Ofi} zXymvVs#asoZVu(BJjQ3HrGTW!Hnz>7U&?SFi_mjF3s%aC4qz 884E!Y1^^^QT#+@LoB CQI zC(d`nWkmB(3wEKFweZsZgBpA(vanO7?jMq{q{>6OGQ*d$Za2pf*9vb8`+i!n>j?nK z{k(ms^X$Fs)DU;wPKT1lOSv$(cFKi)!mj@K2d=di28`=#=5?+3A+c{ybC!{8ag=)! za)mzzg|AgZ=Su}ICH>v{xqH`I+-`z6Ym5Ul* t+Zox*$S#}t30jnp^JI`ezj4x5QReMGliF!E{N;+QcJgE~f)NT$?GIoXt>So@ z>5w!=Z+EhxX(2IE&i>x>P+OO>AO 3hD6)G|(dg@>#jsBWorGfsnawPU zmA(NLB$T7|z})k>K>UIso27A!^ l%WSK?}X+#*u})81CylxaNA&g?h ?S?8if z^7*W#3Kp5ZZgtX(mG^kNoJzSofUTxt*HcId%LYsLI=Hzg+fs2w?cfAI4-fn|&vZX5 zhrj>wcJYdB&&1ffO*4`DjuL1b?C7U#6SD82e6XD&eij9rzm+M#g6NsWV5Y z-~8P#j?rQ{BIuf{lnan?5d5U*JEjx%w7&20 znOueZU+4u(oT_E 6gr3Ei2}6WR^Z^lmo!!G~FRxq7Q@4q+ zuFmhtUds#5&a~J$@0G^?k)Ue-hp))>l=U@lxiaJ3+uDV=Z#BhY=I#SA7_}oS3cpmb z5#+Hy2QjB$7~rpPvEE+2o7#;$p_79I 6dus`}=QjnLRV&1WJOCN`TpU8ZTpry`%y+3hy^v7xu_G z`l7whsCAr>8Y_xBJG>nsY2^k3TSD94<`I13S8Br0p7rlbJeNhiLjB@kYp7c<#}MJ} zrdT=SuV Y)h(&kVbS-UbTb*D+KURV5NYY9nA z2%c`|MkMb2I~CwP&`0y-Ubo+*KjWAEv{EpVsc8`CKd$-y!^CHv7X>bfk7*f-63{X` z`Y4~$pG6tKWANNYPNX0%na=8yUoRHum?AU@zoxu$$H7L%HKM8^>Fp!LKabHU$MM!c zJ`KycrhE0d+{ZAfWT9T-kOTzz{NW^s17U>HO#<&&WdI>`-to12MV((3MHZ3d{k~nG z(TPgv*4OOZBaN$!^rF};2UBJSTJa}#y=`w>^5!A_yvfkfy>I*vk!mdokqp?e)9HS- zM&X5QZHH~ed2=lNe4V%f4|eYqXmnLcP#wQaHjuqBS%6hofh+FjK?cQw>DEg#CT9 z47vT<+PMn!D#7=N#tIVNtBlGk#xO@$?|lk%WZhbel{BdL<$8X@ d0^fJ z3HGJIcatIiiE#`*PE-E=iP>CyPEszSxmO0t3ZT}V;>lF)+zNoA5BaO+vDV^Yz5Y?4 zDGF0)(p(UEmfvLN+56%_J8#h^iJHLVsRZ;Zd=SKTaWu8RJ4O$vWrR|=n~sS`nA9Iz z!@Y{)$_c8z*~hWEIvrj^M_34C%t8cv&qAhL@_iT}Z5`uB+8qd`P4CZCeghmGNM(<7 zLE3 cbOBOc=svCd{F-10x^e3G3<}Hv1!R zAVPzK@}DSL2eea55bnHOgQt_z-~FxYX4gW8_t;RK X zc?QR- &-5DG98dTm)_iS2bb0H?TZfaNQ1S3= JaJ<+{SML7Pd&+5glOTk OaIrTf> QkBsgirUZ~mw#0|Q|YOl+nCBuCB%HIPk=$##L^tVWkJ;NJ @W+396a0`W9q}1p=sdn??&V4RnRJaX$nA4oFPP=)|v=M ztX7;5{#u@>VXvv%#%M98A@)%YYKyODyKfyxZ8_hkMB`V6!c9n(;l+Jf1c48ap^ns| z9E~CO_C!lxkyRa198=n(R-h9f F1z;}PiLe$vMMZzE?vfRGDza=L zDxQp6zSkDqa;INiv9h!>mO;2UMOjRGRr-*kHKq(3bp<&C{MnN1?|cb9qv+(cF7S6) z+pPzlwXcYK`U~2#>$)x)S6CoT5cu>MTAA|)PHi(w(F^eBJ@Uv&Sxe%hH3WMFq?{c` z3X6X3x0M&a@LWwNp>C*mO?PaD*BHu*jAbEL*_y6o6aSnLfc{mFB@`vaC`__{e9iSB zjZ>A+w}nw(4$WZp@KP>(s3Cv?Gf-F-SaMb%bi?Mn%+NaL|Clh=l^w;xZ(GI8=y|Dg z4@Uff5SdM(YuW_u1N ?^`)zk^0auQ&zrBXe09ZwY eUT~5naLYh4)j`P@7Gsgf>#ih|bwGXnY3f QqT= zV2-6Ik8PY=e;1>#NWq2;HE&~g2sGY41$23CvJ5vbgsB}?D_y$o;L#aL+#GT1-?6H4 z=l0b-tI41Ye!AzcccFXB=*bN=&K$qeAnydMx&OP6*HSaL*B~pVIOu!bGu8v}nz5E{ z4wN5A8%NnGr7UME10EP&-eD05lwAV48yocm)ojVe^)-rD9amm>VM*Yxyqhf^mUU1k zAFO)|@x8u=q3+LSf4%LrnHJ_3O{C~Y)HLvV6}p?JKNcuFF^c{9&cD^1>)S$?$3`LW z(|V_ymK7w5=hO)i_XTw`o5Okg3!A*)jlWRG4qX Z}p-!^wJp7?89KmhJFXfwKwB zC=_y@yjSE};+b6Y)7xcmKmLA-5#kz_q}Z~zcqca5r2xv X0tP~Ym-*Vz5Wv8p`+PNg0~%lFZq*k+vP7?XFu zbi?9_V_L~ZX;|e-0>Y~DASpLo7IDs 7;u0z{xezE?UCQUL^eQ%t~jyx7LDw>Kh(2;gRFc5wP{xbm$ zzDNF#rk0EN(WAUra*|xKMGYL+y6n Lq&)_1tE59wXYt=r0tI!ORAjJWxKvc z6_Wsiyrd!_a%K>wVxVUxW?06`!FyfZT@@QB`4CWAu-EY8b5X#BVoB{C%6$$eDL_di zzMYF~u4}=#KvBm^l~ir0VZH=MH(tKq_V$o%>G+u-@5cDzcR{-&)&f((q*LB^D2c-3 z4Ak^@1vgy~HU`qw2kOeyofFh>3c#Am3Tp6`B_Of@#3&2Dkj4 {AZ3#hfz=hq8#aCqVS0QY>3kjrX zL`*_^3@B47&}Df+;t|`FkuXTt5Af&T5_)+%f~CCu53 1 zPV+eK(PzcIl7WutW!AEl9WjRg+b)8QmUfRH(u%Q}hjuQ!Gy
!E7mAVEWZB;xeK$ko@Lw2yuoqEVRS{7d zBr>=ceI#tro7|t}H6B#_vr1w4!U-1|RRMPXxDsXqimANQ?4U|_*$lP25?&kj{bpOf z9IN;`i$YR%j(nut`20RL0a0zJ&l&3y4I1A)I!-aAkbdB>++?>P*-m9!)rgxJa@;5! zqH*)O*jYH*3%an@Jp)wb=oz$9X|YxuXZjP0!Eexn&l-;J=+4I_29bY0ST?jT804N~ zzj`=^DO55dpOxXho0E2K1)aKB)@C+sMdFJ=6nA4ua99+Y$DN(;8>@{V0ED&+i1te= z6(<+rNJQ3BN+M;fl}VziQm}Q5k*D7ssmZD18*1KgipQmmYvDgwU#+)<;?$$AyVfEv zhKk@`aA5lB#y9%R$+LaE1k> -R+`V;HqU`9BV}`e6zd`cn|@7E#u0W% z(uKD!Ghi6rq2lFTXi* z>K2921BwvK^z8B$vD^jISXgDQT9zZoFwM}dOTCG;y*)D;R7w=`UL<556W$Q=N&Pru z1ZNuRL|M)$Hy(JN(tu$*xfTgYk?T1}bCTsF?P>BK6}B4@^|Rp-zN~+a#j7s2P`u)2 zTIdk(izvDj#l+rwegm>idn9R6RJpr0B1L(PiI1rBAr`=P7o^LJhKTa_*UZbq_X`nc zvRQia-Ou=@MlcK-bW p>|#{+Fl8MZwcJv3Rz1 zVwUcq39-gPW;ZXX_#p=lGRA`n_Fe_*!?f+DHv}`OmO#-!V&55ZMlrWq5A9MIxEX{R z(W}(39x!O^uJ;haOj}`am4@CkcRaSJo;wYQBnSPckG|t!o*~`c!^HWURrUh~(JUWC zw0Lb{e_Q?%MTWj2?2Fzj2ZD(8+_&4u%Or89`OYT2Me{s^Mx|ekVNXv0d#^O@sl=0} zdY@1w!#2LK?_UrNbL(x}tFic^e;nGAD;KaPv+Cp@hU7WQvhP~05P7OJ!2c0YQvU`$ z)wZK9u2$lw~V=CnYdiLVs HfNkjE_9$pkq{T(2k2 zmK>k9-aw-pyh15*?F)xgEFLMYdIlr0`>Eu9bOZ7te# zPFuzAimc3TpV9YkW@I&yr1Hsz%DV9o^2hQ$zqD4b&U3tvCYjo(D${4`e(+tt5RJ3} zqTv`Ep5yjp5v5e#)-D8~m@1VqGAOVLR5XEDKx _$_@${LDdPNaq|Dp!J)A>wj`fjMJG^Mo~>r^Q<6j!|W3AI{7ukOsgU z{X Epcb^uf8-q+9wwD_JgYBaWWGj{nFu0|e 5R3)O8RgCtsaYR#gZi7F&1QvzoWIcAfo!sTnD9+qiE?o zw|8~53HdH24$YLPk=Y!i2p|EJRbzdPFzfo-$GR Yr2|WJF}u?GwpK5- zAkPgC3f>}1@k+byPi&PiBK;xO2Mfdfn}>O}f#jn!aw8qxYL}S)ZG>|lw0XAF-rz0Q zme5i0XJ>41qcCEYXKOm08`N;5debEpFk2L<^ u_MdPotmOoOK0$RCA<#9y)y@)Qc6IBZ$jhR3S&lPVA z#|HIdR+e@$*tr9GmYrAYl@wcc3WS&<#vQeWuC G@2hH5k`$%kIgcPyt4b*duvmG}6jP(fin(0yJoO%eLtggj?^iKoeR^JzwD zxS$33z3lZ2$*mwST~>-^JDMAnAJ!fs#tZ4QW#=mJJ(rKXVy=JEb&}kIl^g09ymxQI z^XyL0MFRcr{L}m2f10j}JV4lv-lk}5-WgHbZeE^$@c7D1n|LQ9_g4P+x$rQ|;zQ!L zk;a>C)*FTEAynqp*V^4V`Y8Py2 qwIA 8`f>%wxMHR8ZqDhx0Jt9lF-dGzS+p z2UoL2XOpimgnjo!+#j0T#>9@6q0wa?x+KG=D<+LXwWipc>wwY-Ow>KrWB`oL*Yr4c z_Lo%AH^<#GCC{0f-f9jq4#tR;KurLx5wX&llX8H0$+)lzA7{sUfcn^Y-1cN4qYjXO z4ywsc?I;3VFwb oiGZl~0xurW{nP)#Z&W9u z>?=6fdgdanynaq6nns%X9s{ZrhJ2b?S~gj2opiUS`+K3|z%RrLAHVY&IoZ|+8-y(c z?C1ja !}cWFmH3WZ~wB zo$RJ8J(EsX1C$!1QxWabP#y6fb_!_O*}Z}4uH|N2jAP5Z^(C4szIFF-YAC#D_$C#v zlLBzY)R7t0qx8z|Oy%=VW8%qwBo>g%{`K$zZ35HV^XJFqD4DET-g5-}Pu-qKC?U`N zPeoBn2*RBuA@yv;OOF?Kx&@1|$0{5FfqU{if+;NuFkM!4ALbr(I|yNnMr6|=Q!@9x zs@)e6ds#lx>w)wdGj|DyD!NSTBSWtwqgwUwM(pdUoe@_9cs#=L0Qy9K(N*9a)ne5{ z58f4Jt$b6L9d99yNvjv=^n%J%0gT?p^%|{t7EXo69-az3++eY2&W#;%&if{A0B5u^ z_7#zxViRbTgYwj S{OmaTS6ZZ^3P*+;fMj|Ug zVD%VZTc((M&9%cc5Z^gqjAnmjjDQP{_1`Qm;5`R1Wj}d^;yiT7cG8G9x)0U*641&Q znYV#vakMF*{AK5o)QmlMHW$Y?z405RlL{#xwt*gVyJeR^ &l1Xgg6~N}Mrtz>J!6Jw+4j0APWgStII5P5oMn1PlPJ^h&p! ztvF(HwcmtDYl{IjD<}X&37!|)9Ug8r*v?XXl0)eW!Y65JUmNI0?bu3aoZD>QX6pPL zL$axu^bXYfWP9Eu%MV{4UVv@?t@=^-YsCD5kad?=bFAs|_pCuTVUL=3g#nf@zmx~2 zC5S#gHtzt+4!Zs*@@lbDYO%AIY+rodXyykgDLW3~=2#{lxp)9Xcyr?+yQ$LYJ~w0c zb_e8^VOJw5nR5WNJAfMqxTC*paE6Ts=n%ULoZ7=Ktb!+V7BnJX{Id=@)}JVkGI8(i zH6>)T87-gRAQXRy+H2dmDkF1 ^DxXHy{p*{ 2l)U@{=$faSt{QY&Kt;_cJbUMSCW5kLEzDkO_*k9Um8?jYNt3~$DbB`r3rT(-^0MCPjE!<(sSBti?q(uxu_wG VQx zg1hyio7X@324^Fu$JQ6le{1X1BSo8%e$-}qS#w(?s}$(G|Hf>#(p{W$>OHW42r X^XU&h-qu zH@$wbt|t0aa9tb>8u0`s*_%s?ZP}=+2p%oxFVPelh=C~cO558XI=Xdbr{}pT7$J{I z5B&T^`@@Jhh#ceFqU#opQ(zmL>0}&jsQ-z?K72^Y1?W64L#c#8)W(eXP+t*KFFx1F zQsNY&=i~$2avUzQz>Tn*HnI$D#QU`% &Ohs z;nNAK4S#KmIa@h8i<9d`Dbo{Wo_)L~9m=B*bU^H)R!f+GV}g@R(UMr3Yd )4 z)Fc%J$#o|R6IU2;@iX|4ksj^3S(8#!N%IL+3InPL33?*KCKsxJG0W}wGS4P#d|^hA z4Ih}mt1~oI9)z@a69*wp#*o 0 zYSKxnwoV&_T7G5859>vqOjxBzllp5A8Qx^HP-cf0QaktP>_%+`odb)c{htrEqG7ye z;$zHtOG(5-)op2ujwPq{-p1C(xt!tFx)2&r{}r0^ {sZCdQbc z4g??~uqw=PUq#_3yrv!G$OUMpOZamspKm8D&miW?j`Q#V@Z+O@kdClk&32O1OxP2E zx~mJo;SJvRmA~xNdRv2QJ#Nbqp3B`h!YD7Uy|Fr!^*PeT`m<7dwfC7v8#s}j(q{Kn z)51f+WQR)L!w2J_z!Q(b#PDbf7Q}f)Ma9&&_&7fqB1VR6W$$f`|B@pAcggi){oT9N zUPSa9UA-5DktF~8V=nA>tgn{fL+!w4{s%u(ejyg%Zyh5$=Z_( 9lIR1k{^0}qg#w2bFZEwo|@zFL~o%}$; z+2QJ+)NwZOHGxO2Camrlxt^v(?$t)7=UGwNFj-!ZbM(sfHer7rkC2D+-v^SPuN7Zm zP7&Z}y7(h`auZtcZSsc2#DFWu_@sz0gTy%91CQ}n?e%_o6-Y2_@}$l{52Nhjxn2{} z5AKC;HEqAAaF_>2A+cfNYfX$+W-~vzTh36r=uq`l#RGzz-XT4@37|eTxIr9vQEsI` zZ}Tl&K9VSz>;I^shcv;`J^!(Hq^Id_YUs0%9&+VJ!Ds!;{9w6j2i<`8$wmyo{u^WB zv(VS<5odn!x##7dCC)`QuY3aJDg?JMy6nuik^ZQ@CBw#-WSyw@=)pGhsQCrPIP=;E zj`!ma>H|Ryw!Yxeod0t^zI%mDh}=*;|E)pqx}9qt6r93t0ga7(SSW#tWt~<5VgR~c zE<)%R@2>4_VCow=VTGNI%@W-G@uFu&$9-v{s7q7{A@xJNEF|#!Aq_rELx9zCX?J+> zfMZs{VANE=g(nN;v-G<$bW=*&mo5|yQyU`lG4b0rJ2x4Q?A>_rs)Od5dy6l27L-+& zpS>fsrRyzcAOF3Ux8>e%FQ$J|^oyU*PF{!29;`f7q5d=-c iaHlf-)aaOS_sxUxppFYm(5K8g@)0suST^iOxD!~K~ z=Eo;rC6-_4M0smkUtpS0X8&ZM>b!K0+g56t!%*$9DDmJI1gjNoqojMQ%myYRmAkxJ z*@AZ2+cB?_P;JGdaQ$V3T8&k|(kbXR)RgAD1*pK@uapU5lh^SPxu0v#wk~emx-jAe zAo;?{e%mg+G#;!+88C@2@wtty! !Q=PrvC&ZWjn3mGzWf@syDdok;k$^D z=@7XV=O2=JF?+0*&OH@_I{BdGq+97RQ{AE|5|M@YX)dcU)oj%9)IREUg7Wge;KJ!= zS9TyI@kRR{p01>k+H^=Bji5!_j?SqQR%jvK>kEwkZe7*6T>_IUQ^x8fJp2xbfCm5- zy!}yBmt6~)JE!s50eUTHD?ly|^?K$-<%js|^;Ucn$Ps#7O}f+7y3oPnp}Z2AhQ0Cd z;~$(G>^lOdLr&Won4voaTCTjPP+!q&^c`-yc_pTg|6B{ux`PIdUCV`@#*>BPT0&W6 z(_eG9sAXRV(1Tw%avYJ;ED+Fx!Cap!;%gJ0@yx)%=}F^CJpbQ_;UQBSZG}}DE$F>9 za7<{@Xn!y=17;FRSN!H+zMf{&odARU0ri&g8wG6@Ce%zr=rO uspRNTPj^E9^e0 zU9J@0xAWeAm}&)cgPz7=uEsa;p9oxJQqZZDGPK5x!eD64=1?=GJDt`Ei%1}a5J|VP zn;CHvP;S!Cv~&@T$NW!gN)h==vg9}Wip1hTC?b&O)R;m?6NP+5mYo*epLI5fM_V0- z@pA?4+XGDGS5Da{UL$f!d ^QB%#GQfRj2*2vpVI-fQNEi9)rQP#j*8Hzd>41c5 zw@jW9yom|&4c_>l;h@v-ky)2!JEPk}N8(BE%DiS0xioLo1k dpiKM5%0&b(s!wq3s_D3qXY?hN+CEusv)x_0fA_+Ibp4=ByIxJX@^rex;cizLFBZtD zepOrYzeS9P6LS-q!+(0n&2^P|e~>86H)CH1jk6z2txd);`doka29yR77uIrXyY-6K z2?%J6qsS-RUsW&juWSj0%v#>&D^h|( hO*;Ot0Or=3C-n}&&2-B9uuao~J zVXBYK`YeZyk*d%CQJ2IbHT}~;YDI!upiR>hBGXf`*g^W*I$`lJ5CalH1XO}cRSuoV zk{+c;o}u&|KVxdSq2{OG?YE|lJ+48LjP83^xrfKy8_YY2->P%rQcX}P5Ke6SfWAGt zbDRa$;C0NTEgyf5yL9v(rfIS!I5l*rf=;TS7oqb*P6xUJ%)r;MVk%PNEu8|AfuQq+ z>X{cF(}e*G|3N`E4fcxLFc$hE8$Z=tM(8d}l^Hv*q4RJ$m3|B)W-^uQak2`m%LVkX zH-vapf-(E>(!y}=ZwBv}hwt5(k8tt{5597M<5TPF>-ox?s^vd$d&$5Y{>lh)KO{yr zZg4TTguMOvg6+&i+ `9~5&hkYA{TRbQR4KIDmN2K}OpYD-@tkWoe&mS8i)kj9^1LFn?>A%of1FxJ+3sA+ zx$i@Rx}~__AkUw1_HJ8~G-u;jgr)6!mbj>IrDdQu;R!|8@^+3#UrS-_ zPJy> OGmc9*pdu7PCzkv6;eL%IWGb;x2ahcwfOuh#Z zW@n=Ndu-0 2DttWE;@mbQ2W&*pNHjCMTs#wdh44@tgys(|(3?ihpSTn}U$n z%FW}vVqk=}7T*`tMo14Y&Fzd;K$gl56D@r5R0-(^U7csR9UZiAAw|K~a=c7xbZ?-> z|Ar(N%mHrdC#b#89x93VSTu#J)TTxWp6X!6oK-ZEu;XNSYM_VQ$O2r^tFL~7Thuo{ zCPlG#n$`%KQ=i`@aB=CLDp+Z30S&GHKfpP;;I}EZbhn|9{YiH9 Fv<2t~xZUbh1W&-Sj-;@QrxT0`Z&Gb=snfLJyuMeVf z#He^;w|(=Lw9w+=b#?dub{T~s#PS#7^sJbkmX$%K#=X}6$3%s?suy5)G^iI7NPd)0 z3QVf4SIk*wZ XoGW zp)9ZJBbb>J-G_JQa2+g_(ca3y_vtB3JNIdzHvv0go|m_O=nr5?jmrNq=Lep`)HG^! zAsSjYmX#Vt9q-vsxE?LD4(hESg1J{>d+7^2gRrC8rzd{|m(PR6YZxepNV1~f<20WA zUleqDTzYts>^$wog^WAj5thtNO+C)OuaUi^g2bjWygFfqJ_DnAm}d7doS|J3K)*j( zI1xFr*XRF|ehvF=J7hetye6KlWy`T^wH%Ns1}`I)@~beTOBck~e229jS+tM02o`IR z+WNm?X1@<{Tr5Co0EO> |esm~Pp|#>C+4THDJZ-S4um3T1~&Yq%cT#3%IU)BSzN>)4&P&f8@_(H8I7`?WW(f9XzjcN#*lY%jdDZ z7x1#To=48ilbjlyaL&C>4)|fMGhr(-*jwIZ-k#gUhF#+waAyN-dK%9)3)rYLjVBck zN4{xLn;i8uB)1TH$k~)(r#n?sp7XV}sF||eS!>I8O1ImHk(zHNU}J;4Z;j-7<=wK7 zfAwkUIhO?29zhMBWnTdKjyqL9ByA3GjCwRn#ISxmp)*~*sTHn_pnywi8Ho-XOrfLj z2R I%0=k6N}0dLOWPSfQ@e)|hQO4{vVW*I1kq^7`WU zxZN%1Z(&6*$HsOwUVFEgv2570LVAy$#!x;5nBNlGyG~fN!Ns6HEGHV~i4wMdu(K7- zvBxQp{x1s~f31= 5b@p~S83#pux1wh5E~kEm(64z-C-+J5nm-=vtgjz|iBnGVrhbk-D8>1h0T zTM&1PFFm)>qhr$km`Ul<1dim#igT}cmo3drnho|p#cl%Tlm#14zhe6ZhQ^G>YxW*_ z*h0io_u6Xe-BkMMwCu|8{QFofr^kN5Z?^}|myEGDZ0_50WXb%lt$IS;Cg?*2Gb5dj z;koMx+b@4DiEyLroOh}Cncit!Ow4#hnI%w`9ZD|$hzSYfMa{UoH!!v_1v1fYj+~_r z;+YvuPH4jr_`vgwHMk2uH|~E~938rU)HpPB&S|6T$ydC6FMn!0XmXp}QgxfZdqV1y z(80;+xT&kcUp9G2xdz0olh!nk!vB5Ah8`W=UGC#m?@ip7?kiaF_IH0evPL+mg|}ZX zrP=665z1@@j#SHWp 6Gur_4ce;w^3-=0di)srWxjH>x)9kQdX!#mQ!$>p-gD9u(SG&U}h( za>5RF75S;#L61%et3y1;6&0OxTgf=3f;F22aeRl)-ex;ANR092+&Xsll%S;cl~7W{ z-tk!H-0_`dPu^B|NGbVOea%KKI#2AAWpsU6brLuF@>=NIlzR)BJ#(shR`2mAi-`R} zo(pB(jnzm#rttK8A*=lal4zpA1AnGw1JZqk0l(W_?q)CLAN*tlQfb4o@6PbcdpBO< zF7@6}+f=Rhft%L|S_37dHE^ttu`Qrj_xNqPGxe#Mkdlz~A%vIbMbW$El3oH 4l&t19v_F3>n}xIC~aVn{YtJK*W!+czdP9&ww;Rj;X2 zoJRvO+fkHs_d^WHZ8K_V1qQCH<#q-86yI@#)!a_fc@({QA%CX)tnZF5ELYcBeCIm3 z5qplQ?`&^cX rKkHViwfK?nk%q>VKHt;djVg9!p{o zSC1zx!|%$}*MHz2-(bq@v-b@bs=9`*Ozx&P