Correlate
EXPLORATORY WORKBENCH · nothing here is a finding
'; echo '

Overlay any public streams on one time axis, lag one against another, and export the combined series. Multi-stream overlays are indexed to their own range (single axis, no dual scales); the tooltip carries true values and units.

'; $streams=db()->query("SELECT s.code,s.label FROM streams s WHERE s.visibility='public' ORDER BY s.label")->fetchAll(); $sel = $_GET['s'] ?? ['wx_temp','ac_impact_activity']; $sel = array_slice(array_filter((array)$sel), 0, 4); $from=$_GET['from']??date('Y-m-d',strtotime('-30 days')); $to=$_GET['to']??date('Y-m-d'); $lag=(int)($_GET['lag']??0); echo '
'; for($i=0;$i<4;$i++){ echo '
'; } echo '
'; echo '
'; echo '
'; $out=[]; $slot=0; foreach($sel as $i=>$code){ if(!$code) continue; $s=stream_by_code($code); if(!$s||!visible($s)) continue; $rows=series($s,$from.' 00:00:00',$to.' 23:59:59'); if($i===1 && $lag!==0){ $rows=array_map(function($r)use($lag){$r['ts']=date('Y-m-d H:i:s',strtotime($r['ts'])+$lag*3600);return $r;},$rows); } $out[]=['label'=>$s['label'].($i===1&&$lag?' (lag '.$lag.'h)':''),'slot'=>$slot++,'data'=>array_map(fn($r)=>[substr($r['ts'],0,16),(float)$r['value']],$rows),'unit'=>$s['unit'],'mode'=>$s['mode']]; } if($out){ $tags=''; foreach($out as $o){ $tags.=$o['mode']==='live'?'LIVE DATA ':'PLACEHOLDER DATA '; } echo '

Overlay '.$tags.'

true,'series'=>$out])).'\'>
'; } echo '

Pre-built views

'; $pre=[['Birds vs construction vs weather','s[]=ac_impact_activity&s[]=cx_machine_days&s[]=wx_wind'], ['Footfall vs wildlife detections','s[]=ff_paths&s[]=th_detections'], ['Occupancy vs resource use','s[]=ops_occupancy&s[]=res_energy'], ['Sky brightness vs installation activity','s[]=sky_mpsas&s[]=grim_sessions']]; foreach($pre as [$t,$qs]) echo '

'.h($t).'

'; echo '
'; page_footer();