// // Copyright 2022 SenX S.A.S. // // This program is free software: you can redistribute it and/or modify it // under the terms of the GNU Affero General Public License as published // by the Free Software Foundation, version 3. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see // { 'name' 'dashboardSpec' 'desc' 'Comsumes a GTS and a subsequence length to compute the matrix profile and return a spec for a dashboard showing motifs and discords.' } 'info' STORE 0 MACROTTL <% !$info INFO SAVE 'context' STORE <% // Code of the actual macro [ 'gts' 'len' 'bucketspan' ] STORE // // Matrix profile stuff // // matrix profile (PROFILE will check that $gts is bucketized). $gts $len MP.PROFILE 'profile' STORE // adjusted for viz (value above 100 are replaced with 100) [ $profile 100.0 mapper.le 0 0 0 ] MAP [ NaN NaN NaN 100.0 ] FILLVALUE SORT 0 GET 'adj_profile' STORE // motifs $len 4.0 / CEIL TOLONG $bucketspan * 'exclusion_zone' STORE $profile 10 $exclusion_zone @senx/profile/motifs 'motifs' STORE [ $motifs true mapper.replace 0 0 0 ] MAP 0 GET 'motifs_annotations' STORE // top-1 motif $motifs SIZE 0 > <% $motifs VALUESORT 0 ATINDEX 0 GET 'tick' STORE $gts $tick $len $bucketspan * + $len $bucketspan * TIMECLIP %> <% NULL %> IFTE 'top-1' STORE // top-2 motif $motifs SIZE 1 > <% $motifs VALUESORT 1 ATINDEX 0 GET 'tick' STORE $gts $tick $len $bucketspan * + $len $bucketspan * TIMECLIP %> <% NULL %> IFTE 'top-2' STORE // top-3 motif $motifs SIZE 2 > <% $motifs VALUESORT 2 ATINDEX 0 GET 'tick' STORE $gts $tick $len $bucketspan * + $len $bucketspan * TIMECLIP %> <% NULL %> IFTE 'top-3' STORE // discords $profile 10 $exclusion_zone @senx/profile/discords 'discords' STORE [ $discords true mapper.replace 0 0 0 ] MAP 0 GET 'discords_annotations' STORE // top-1 discord $discords SIZE 0 > <% $discords RVALUESORT 0 ATINDEX 0 GET 'tick' STORE $gts $tick $len $bucketspan * + $len $bucketspan * TIMECLIP %> <% NULL %> IFTE 'top-1d' STORE // top-2 discord $discords SIZE 1 > <% $discords RVALUESORT 1 ATINDEX 0 GET 'tick' STORE $gts $tick $len $bucketspan * + $len $bucketspan * TIMECLIP %> <% NULL %> IFTE 'top-2d' STORE // top-3 discord $discords SIZE 1 > <% $discords RVALUESORT 2 ATINDEX 0 GET 'tick' STORE $gts $tick $len $bucketspan * + $len $bucketspan * TIMECLIP %> <% NULL %> IFTE 'top-3d' STORE // // Dashboard spec // { 'title' $gts NAME 'description' $gts LABELS ->JSON 'tiles' [ { 'type' 'area' 'title' 'Data' 'x' 0 'y' 0 'w' 12 'h' 1 'data' $gts } { 'type' 'area' 'title' 'Matrix Profile' 'x' 0 'y' 1 'w' 12 'h' 1 'data' $adj_profile } { 'type' 'annotation' 'title' 'Motifs' 'x' 0 'y' 2 'w' 6 'h' 1 'data' $motifs_annotations 'globalParams' { 'xMin' $profile FIRSTTICK } } { 'type' 'annotation' 'title' 'Discords' 'x' 6 'y' 2 'w' 6 'h' 1 'data' $discords_annotations } { 'type' 'area' 'title' 'Most typical motif' 'x' 0 'y' 3 'w' 6 'h' 1 'data' $top-1 } { 'type' 'area' 'title' '2nd most typical motif' 'x' 0 'y' 4 'w' 6 'h' 1 'data' $top-2 } { 'type' 'area' 'title' '3rd most typical motif' 'x' 0 'y' 5 'w' 6 'h' 1 'data' $top-3 } { 'type' 'area' 'title' 'Most atypical discord' 'x' 6 'y' 3 'w' 6 'h' 1 'data' $top-1d } { 'type' 'area' 'title' '2nd most atypical discord' 'x' 6 'y' 4 'w' 6 'h' 1 'data' $top-2d } { 'type' 'area' 'title' '3rd most atypical discord' 'x' 6 'y' 5 'w' 6 'h' 1 'data' $top-3d } ] } %> <% // catch any exception RETHROW %> <% // finally, restore the context $context RESTORE %> TRY %>