@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix tabular: <http://ua.be/sdo2l/vocabulary/base/tabular#> .
@prefix base: <http://ua.be/sdo2l/vocabulary/base#> .

# The namespace for fse shacl shapes.
@prefix tabular-shapes: <http://ua.be/sdo2l/vocabulary/tabular-shapes#> .

tabular-shapes:outlier_detection
	a sh:NodeShape ;
	sh:targetClass tabular:Cell ;
	sh:property [
		sh:path tabular:holdsContent ;
    	sh:severity sh:Warning ;
    	sh:sparql [
      	a sh:SPARQLConstraint ;
      	sh:message "We have detected outliers in the data of Sensor_00" ;
      	sh:prefixes [
      		sh:declare [
				sh:prefix "tabular" ;
				sh:namespace "http://ua.be/sdo2l/vocabulary/base/tabular#"^^xsd:anyURI ;
				] ] ,
	 		[ sh:declare [
				sh:prefix "owl" ;
				sh:namespace "http://www.w3.org/2002/07/owl#"^^xsd:anyURI ;
			] ]  ,
			[ sh:declare [
				sh:prefix "rdf" ;
				sh:namespace "http://www.w3.org/1999/02/22-rdf-syntax-ns#"^^xsd:anyURI ;
			] ] ,
			[ sh:declare [
				sh:prefix "xsd" ;
				sh:namespace "http://www.w3.org/2001/XMLSchema#"^^xsd:anyURI ;
			] ] ,
			[ sh:declare [
				sh:prefix "afn" ;
				sh:namespace "http://jena.apache.org/ARQ/function#"^^xsd:anyURI ;
			] ];
      	sh:select """
			SELECT ?table $this ?avg
			WHERE {
			  ?table rdf:type tabular:TabularData .
			  ?table tabular:hasRows ?header .
			  ?table owl:sameAs <http://ua.be/drivetrain/description/artifacts/artifacts#drivetrain-sensor-data-v1> .
			  ?header rdf:type tabular:HeaderRow .
			  ?header tabular:hasCell ?headerCell .
			  ?headerCell tabular:holdsContent "sense_00" .
			  ?headerCell tabular:hasColumnPosition ?cPos .
			  ?table tabular:hasRows ?rows .
			  ?rows rdf:type tabular:Row .
			  ?rows tabular:hasHeadingModifier "no" .
			  ?rows tabular:hasCell $this .
			  $this tabular:hasColumnPosition ?cPos.
			  $this $PATH ?content .
			  {
			  SELECT ?table ?avg ?count ( afn:sqrt( sum( ((xsd:double(?content)) - ?avg) * ((xsd:double(?content)) - ?avg) ) / (?count - 1) ) as ?stddev )
			  WHERE {
			    ?table rdf:type tabular:TabularData .
			    ?table owl:sameAs <http://ua.be/drivetrain/description/artifacts/artifacts#drivetrain-sensor-data-v1> .
			  	?table tabular:hasRows ?header .
			    ?header rdf:type tabular:HeaderRow .
			    ?header tabular:hasCell ?headerCell .
			    ?headerCell tabular:holdsContent "sense_00" .
			    ?headerCell tabular:hasColumnPosition ?cPos .
			    ?table tabular:hasRows ?rows .
			    ?rows rdf:type tabular:Row .
			    ?rows tabular:hasHeadingModifier "no" .
			    ?rows tabular:hasCell ?cells .
			    ?cells tabular:hasColumnPosition ?cPos.
			    ?cells tabular:holdsContent ?content .
			    {
			      SELECT ?table (avg(xsd:double(?content)) as ?avg) (count(*) as ?count)
			      WHERE {
			  	    ?table rdf:type tabular:TabularData .
			      	?table owl:sameAs <http://ua.be/drivetrain/description/artifacts/artifacts#drivetrain-sensor-data-v1> .
			  	    ?table tabular:hasRows ?header .
			      	?header rdf:type tabular:HeaderRow .
			      	?header tabular:hasCell ?headerCell .
			       	?headerCell tabular:holdsContent "sense_00" .
			      	?headerCell tabular:hasColumnPosition ?cPos .
			        ?table tabular:hasRows ?rows .
			        ?rows rdf:type tabular:Row .
			        ?rows tabular:hasHeadingModifier "no" .
			        ?rows tabular:hasCell ?cells .
			        ?cells tabular:hasColumnPosition ?cPos.
			        ?cells tabular:holdsContent ?content .
			      }
			      GROUP BY ?table
			    }
			  }
			  GROUP BY ?table ?avg ?count
			  }
			}
			HAVING ((abs((xsd:double(?content))-?avg)/?stddev) >= 2 )
        	"""
    	]
  	] ;
	sh:closed false .
