Index: trunk/ippMonitor/raw/czartool_labels.php
===================================================================
--- trunk/ippMonitor/raw/czartool_labels.php	(revision 42276)
+++ trunk/ippMonitor/raw/czartool_labels.php	(revision 42736)
@@ -89,5 +89,5 @@
         "pstamp",
         "registration",
-        "stack",
+//        "stack",
         "stdscience",
         "summitcopy");
@@ -134,5 +134,4 @@
 }
 
-
 $debug = 0;
 $table = "<table bgcolor=\"#FFFFFF\" width=\"100%\" align=\"middle\" border=\"1\" cellspacing=\"0\" cellpadding=\"4\" style=\"font-size:80%\">\n";
@@ -183,8 +182,5 @@
 echo "<table border=\"0\">";
 // timer begin for main page
-$time = microtime();
-$time = explode(' ', $time);
-$time = $time[1] + $time[0];
-$mainstart = $time;
+$mainstart = microtime(true);
 
 # headers
@@ -210,4 +206,5 @@
 $hsttime1 = date("Y-m-d H:i:s", strtotime("$lastUpdateTime"));
 $utctime1 = gmdate("Y-m-d H:i:s", strtotime("$lastUpdateTime"));
+$mjdday = getMJD();
 
 echo "<br>";
@@ -249,5 +246,5 @@
           <td>".getNightlyScienceStatus($czardb, $proj)."</td></tr>"; 
 echo "<tr><td>Czardb last update time</td> 
-          <td> $hsttime1 (HST), $utctime1 (UTC)</td></tr>";
+          <td> $hsttime1 (HST), $utctime1 (UTC), $mjdday (MJD)</td></tr>";
 echo "</table><br>";
 
@@ -258,103 +255,87 @@
 # XXX EAM : 2017.09.17 : debugging slowness
 # CCL : 2019.11.09 : debugging slowness
-//createSummitDataTable($projectdb); // this is slow because of the join between summitExp and rawExp, but not the major one
-createSummitDataTable2($projectdb, $pass, $proj); // this is slow because of the join between summitExp and rawExp, but not the major one
-
-createChunkDataTable($projectdb);  // this is another part for slowness during nightly processing
-
-createDatesTable($czardb, $proj); 
+createSummitDataTable2($projectdb, $pass, $proj, $debug); // this is slow because of the join between summitExp and rawExp, but not the major one
+
+createChunkDataTable($projectdb, $debug);  // this is another part for slowness during nightly processing
+
+// createDatesTable($czardb, $proj); what is this for?
 
 // Database status
-// timer begin for Database status
-$time = microtime();
-$time = explode(' ', $time);
-$time = $time[1] + $time[0];
-$start = $time;
-
 echo $table;
-echo "<tr>";
-createTableTitle("Database status (update fix log <a href=\"http://svn.pan-starrs.ifa.hawaii.edu/trac/ipp/wiki/Replication_Issues\"><font color=\"blue\">here</a>)", 2);
-  
-echo "<tr>";
-createTableColumnHeader("Database");
-createTableColumnHeader("Status (sec behind master)");
-// gpc dbs
-showDatabaseStatus($HOST_GPC1, $USER_GPC1, $PASSWORD_GPC1, $LABEL_GPC1);
-showReplicationsStatus($REPL_HOST_GPC1, $REPL_USER_GPC1, $REPL_PASSWORD_GPC1, $REPL_LABEL_GPC1);
-showReplicationsStatus($REPL_HOST_GPC1_SECONDARY, $REPL_USER_GPC1_SECONDARY, $REPL_PASSWORD_GPC1_SECONDARY, $REPL_LABEL_GPC1_SECONDARY);
-showReplicationsStatus($REPL_HOST_GPC1_TERTIARY, $REPL_USER_GPC1_TERTIARY, $REPL_PASSWORD_GPC1_TERTIARY, $REPL_LABEL_GPC1_TERTIARY);
-// nebulous dbs
-showDatabaseStatus($HOST_NEBULOUS, $USER_NEBULOUS, $PASSWORD_NEBULOUS, $LABEL_NEBULOUS);
-//showReplicationsStatus($REPL_HOST_NEBULOUS, $REPL_USER_NEBULOUS, $REPL_PASSWORD_NEBULOUS, $REPL_LABEL_NEBULOUS);
-showReplicationsStatus($REPL_HOST_NEBULOUS_SECONDARY, $REPL_USER_NEBULOUS_SECONDARY, $REPL_PASSWORD_NEBULOUS_SECONDARY, $REPL_LABEL_NEBULOUS_SECONDARY);
-showReplicationsStatus($REPL_HOST_NEBULOUS_TERTIARY, $REPL_USER_NEBULOUS_TERTIARY, $REPL_PASSWORD_NEBULOUS_TERTIARY, $REPL_LABEL_NEBULOUS_TERTIARY);
-showReplicationsStatus($REPL_HOST_NEBULOUS_QUATERNARY, $REPL_USER_NEBULOUS_QUATERNARY, $REPL_PASSWORD_NEBULOUS_QUATERNARY, $REPL_LABEL_NEBULOUS_QUATERNARY);
-// other dbs
-showDatabaseStatus($HOST_PSTAMP, $USER_PSTAMP, $PASSWORD_PSTAMP, $LABEL_PSTAMP);
-showReplicationsStatus($REPL_HOST_DATASTORE, $REPL_USER_DATASTORE, $REPL_PASSWORD_DATASTORE, $REPL_LABEL_DATASTORE);
-
-// timer finished
-echo "<tr><th colspan=2>";
-$time = microtime();
-$time = explode(' ', $time);
-$time = $time[1] + $time[0];
-$finish = $time;
-$total_time = round(($finish - $start), 3);
-echo "loading in $total_time seconds.";
-echo "</th></tr>";
+    // timer begin
+    $start = microtime(true);
+    echo "<tr>";
+    createTableTitle("Database status (update fix log <a href=\"http://svn.pan-starrs.ifa.hawaii.edu/trac/ipp/wiki/Replication_Issues\"><font color=\"blue\">here</a>)", 2);
+      
+    echo "<tr>";
+    createTableColumnHeader("Database");
+    createTableColumnHeader("Status (sec behind master)");
+    // gpc dbs
+    showDatabaseStatus($HOST_GPC1, $USER_GPC1, $PASSWORD_GPC1, $LABEL_GPC1);
+    showReplicationsStatus($REPL_HOST_GPC1, $REPL_USER_GPC1, $REPL_PASSWORD_GPC1, $REPL_LABEL_GPC1);
+    showReplicationsStatus($REPL_HOST_GPC1_SECONDARY, $REPL_USER_GPC1_SECONDARY, $REPL_PASSWORD_GPC1_SECONDARY, $REPL_LABEL_GPC1_SECONDARY);
+    showReplicationsStatus($REPL_HOST_GPC1_TERTIARY, $REPL_USER_GPC1_TERTIARY, $REPL_PASSWORD_GPC1_TERTIARY, $REPL_LABEL_GPC1_TERTIARY);
+    // nebulous dbs
+    showDatabaseStatus($HOST_NEBULOUS, $USER_NEBULOUS, $PASSWORD_NEBULOUS, $LABEL_NEBULOUS);
+    //showReplicationsStatus($REPL_HOST_NEBULOUS, $REPL_USER_NEBULOUS, $REPL_PASSWORD_NEBULOUS, $REPL_LABEL_NEBULOUS);
+    showReplicationsStatus($REPL_HOST_NEBULOUS_SECONDARY, $REPL_USER_NEBULOUS_SECONDARY, $REPL_PASSWORD_NEBULOUS_SECONDARY, $REPL_LABEL_NEBULOUS_SECONDARY);
+    showReplicationsStatus($REPL_HOST_NEBULOUS_TERTIARY, $REPL_USER_NEBULOUS_TERTIARY, $REPL_PASSWORD_NEBULOUS_TERTIARY, $REPL_LABEL_NEBULOUS_TERTIARY);
+    showReplicationsStatus($REPL_HOST_NEBULOUS_QUATERNARY, $REPL_USER_NEBULOUS_QUATERNARY, $REPL_PASSWORD_NEBULOUS_QUATERNARY, $REPL_LABEL_NEBULOUS_QUATERNARY);
+    // other dbs
+    showDatabaseStatus($HOST_PSTAMP, $USER_PSTAMP, $PASSWORD_PSTAMP, $LABEL_PSTAMP);
+    showReplicationsStatus($REPL_HOST_DATASTORE, $REPL_USER_DATASTORE, $REPL_PASSWORD_DATASTORE, $REPL_LABEL_DATASTORE);
+    
+    // end time
+    echo "<tr><th colspan=2>";
+    $total_time = round((microtime(true) - $start), 3);
+    echo "loading in $total_time seconds.";
+    echo "</th></tr>";
 echo "</table><br>";
 
 
 // critical machines status
-// timer begin for critical machines
-$time = microtime();
-$time = explode(' ', $time);
-$time = $time[1] + $time[0];
-$start = $time;
-
-$PingStatus = "<font style=\"BACKGROUND-COLOR: yellow\"  color=\"red\">DOWN</font>";
 echo $table;
-echo "<tr>";
-createTableTitle("Critical machine status", 3);
-
-echo "<tr>";
-createTableColumnHeader("Hostname");
-createTableColumnHeader("Status");
-createTableColumnHeader("Loading time");
-showPingStatus($HOST_GATEWAY, $LABEL_GATEWAY);
-showPingStatus($HOST_GATEWAY_SECONDARY, $LABEL_GATEWAY_SECONDARY);
-showPingStatus($HOST_PROXY, $LABEL_PROXY);
-showPingStatus($HOST_APACHE1, $LABEL_APACHE1);
-showPingStatus($HOST_APACHE2, $LABEL_APACHE2);
-showPingStatus($HOST_APACHE3, $LABEL_APACHE3);
-showPingStatus($HOST_APACHE4, $LABEL_APACHE4);
-showPingStatus($HOST_APACHE5, $LABEL_APACHE5);
-showPingStatus($HOST_APACHE6, $LABEL_APACHE6);
-showPingStatus($HOST_APACHE_BACKUP1, $LABEL_APACHE_BACKUP1);
-showPingStatus($HOST_APACHE_BACKUP2, $LABEL_APACHE_BACKUP2);
-showPingStatus($HOST_HOME, $LABEL_HOME);
-showPingStatus($HOST_HOME_BACKUP, $LABEL_HOME_BACKUP);
-showPingStatus($HOST_NAGIOS, $LABEL_NAGIOS);
-showPingStatus($HOST_SVN, $LABEL_SVN);
-showPingStatus($HOST_CONFLUENCE, $LABEL_CONFLUENCE);
-showPingStatus($HOST_MAILMAN, $LABEL_MAILMAN);
-//  echo "<td>ippc70 (apache node) <td> $PingStatus <td> 0 seconds ";  // comment out if ippc70 is back
-// timer finished
-echo "<tr><th colspan=3>";
-$time = microtime();
-$time = explode(' ', $time);
-$time = $time[1] + $time[0];
-$finish = $time;
-$total_time = round(($finish - $start), 3);
-echo "loading in $total_time seconds.";
-echo "</th></tr>";
+    // start time
+    $start = microtime(true);
+    
+    $PingStatus = "<font style=\"BACKGROUND-COLOR: yellow\"  color=\"red\">DOWN</font>";
+
+    echo "<tr>";
+    createTableTitle("Critical machine status", 3);
+    
+    echo "<tr>";
+    createTableColumnHeader("Hostname");
+    createTableColumnHeader("Status");
+    createTableColumnHeader("Loading time");
+    showPingStatus($HOST_GATEWAY, $LABEL_GATEWAY);
+    showPingStatus($HOST_GATEWAY_SECONDARY, $LABEL_GATEWAY_SECONDARY);
+    showPingStatus($HOST_PROXY, $LABEL_PROXY);
+    showPingStatus($HOST_APACHE1, $LABEL_APACHE1);
+    showPingStatus($HOST_APACHE2, $LABEL_APACHE2);
+    showPingStatus($HOST_APACHE3, $LABEL_APACHE3);
+    showPingStatus($HOST_APACHE4, $LABEL_APACHE4);
+    showPingStatus($HOST_APACHE5, $LABEL_APACHE5);
+    showPingStatus($HOST_APACHE6, $LABEL_APACHE6);
+    showPingStatus($HOST_APACHE_BACKUP1, $LABEL_APACHE_BACKUP1);
+    showPingStatus($HOST_APACHE_BACKUP2, $LABEL_APACHE_BACKUP2);
+    showPingStatus($HOST_HOME, $LABEL_HOME);
+    showPingStatus($HOST_HOME_BACKUP, $LABEL_HOME_BACKUP);
+    showPingStatus($HOST_NAGIOS, $LABEL_NAGIOS);
+    showPingStatus($HOST_SVN, $LABEL_SVN);
+    showPingStatus($HOST_CONFLUENCE, $LABEL_CONFLUENCE);
+    showPingStatus($HOST_MAILMAN, $LABEL_MAILMAN);
+
+    // end time
+    echo "<tr><th colspan=3>";
+    $total_time = round((microtime(true) - $start), 3);
+    echo "loading in $total_time seconds.";
+    echo "</th></tr>";
 echo "</table><br>";
 
-createServersTable($pass, $proj,$selectedMode,$czardb, $servers, $selectedLabel, $selectedStage, $plotType); // this was the major slowness part due to large table in czardb
-
-# pantasks server status, if requested
-if ($selectedServer && !$serverCmd) showServerStatus($selectedServer, $proj);
-
-#2nd table column for space
+createServersTable($pass, $proj,$selectedMode,$czardb, $servers, $selectedLabel, $selectedStage, $plotType); 
+    # pantasks server status, if requested
+    if ($selectedServer && !$serverCmd) showServerStatus($selectedServer, $proj);
+
+#2nd table column empty contnets
 echo "<td style=height:200px;width: 10px;text-align:top;\"><br>";
 
@@ -362,41 +343,41 @@
 echo "<td style=height:200px;width:600px;text-align:top;\"><br>";
 # plots
-if ($selectedStage == "all_stages" & $selectedLabel == "all") { 
-   # with all stages and all labels, the rate query is too slow so I use the old method until it get improved. CCL 20210117
-   # gnuplots
-   # time series plot
-   echo "<img src=\"czartool_getplot.php?mode=$selectedMode&type=t&label=$selectedLabel&proj=$proj&stage=$selectedStage&plottype=linear\"><br><br>";
-   echo "<img src=\"czartool_getplot.php?mode=$selectedMode&type=t&label=$selectedLabel&proj=$proj&stage=$selectedStage&plottype=log\"><br><br>";
-   # rate series plot
-   echo "<img src=\"czartool_getplot.php?mode=$selectedMode&type=rt&label=$selectedLabel&proj=$proj&stage=$selectedStage&plottype=linear\"><br><br>";
-   #for dev version
-   # google chart
-   # time series plot
-   #echo Gettimeseries($czardb, $selectedMode, $selectedLabel, $proj, $selectedStage);
-   # rate series plot
-   #echo Getrate($czardb, $selectedMode, $selectedLabel, $proj, $selectedStage);
+if ($selectedStage == "all_stages" && $selectedLabel == "all") {
+    // Use old method with gnuplots as the rate query is slow with all stages and labels
+    displayImage("t", $selectedMode, $selectedLabel, $proj, $selectedStage, "linear");
+    displayImage("t", $selectedMode, $selectedLabel, $proj, $selectedStage, "log");
+    displayImage("rt", $selectedMode, $selectedLabel, $proj, $selectedStage, "linear");
+
+    // Uncomment for dev version with Google Charts
+    // echo Gettimeseries($czardb, $selectedMode, $selectedLabel, $proj, $selectedStage);
+    //echo Getrate($czardb, $selectedMode, $selectedLabel, $proj, $selectedStage);
 } else {
-   # google chart
-   # time series plot
-   echo Gettimeseries($czardb, $selectedMode, $selectedLabel, $proj, $selectedStage);
-   # rate series plot
-   echo Getrate($czardb, $selectedMode, $selectedLabel, $proj, $selectedStage);
+    // Use Google Charts for specific stage and label
+    echo Gettimeseries($czardb, $selectedMode, $selectedLabel, $proj, $selectedStage);
+    echo Getrate($czardb, $selectedMode, $selectedLabel, $proj, $selectedStage);
+}
+
+// Helper function to generate image tags for plots
+function displayImage($type, $mode, $label, $proj, $stage, $plottype) {
+    $src = "czartool_getplot.php?mode=" . urlencode($mode) .
+           "&type=" . urlencode($type) .
+           "&label=" . urlencode($label) .
+           "&proj=" . urlencode($proj) .
+           "&stage=" . urlencode($stage) .
+           "&plottype=" . urlencode($plottype);
+    echo "<img src=\"$src\"><br><br>";
 }
 
 # data quality timeseries
-echo getDataQuality($projectdb);
+echo getDataQuality2($projectdb); // new version of data quality plots
+
 # storage timeseries
 echo getSpaces($czardb);
 # storage plot
-echo getHosts($czardb);
+ echo getHosts($czardb);
 
 # timer for main page end
 echo "<tr><th colspan=3>";
-$time = microtime();
-$time = explode(' ', $time);
-$time = $time[1] + $time[0];
-$finish = $time;
-$total_time = round(($finish - $mainstart), 3);
-echo "overall loading in $total_time seconds.";
+echo "overall loading in " . round((microtime(true) - $mainstart), 3) . " seconds.";
 echo "</th></tr>";
 echo "</table>";
@@ -457,25 +438,28 @@
 #
 ###########################################################################
-function createChunkDataTable($projectdb) {
+function createChunkDataTable($projectdb, $debug) {
 
     // timer start
-    $time = microtime();
-    $time = explode(' ', $time);
-    $time = $time[1] + $time[0];
-    $start = $time;
+    $start = microtime(true);
 
     // function begin
     #First find the reference exposure ID to speed up the subsequent queries
+    $mjdDay  = getMJD();
+    $expname = "o{$mjdDay}%";
+
     $date = gmdate("Y-m-d");
-    $sql = "SELECT MAX(exp_id) FROM rawExp WHERE dateobs >= date_sub('$date', interval 20 day) AND dateobs <= date_sub('$date', interval 10 day)";
+    $sql = "SELECT MIN(exp_id) FROM rawExp WHERE exp_name like '$expname' ";
+    if ($debug) {echo "$sql<br>";}
     $qry = $projectdb->query($sql);
+
     if (dberror($qry)) {
-        print "*** WARNING: no data in period 10-20 days before requested date (query will be slower) **\n";
-        $refExpID = 0; 
-    }
-    $qry->fetchInto($refExpID);
-    if ($refExpID[0] = 'NULL') {
-        $refExpID[0] = 0;
-    }
+        echo "*** WARNING: No data for tonight **\n";
+        $refExpID = 0;
+    } else {
+        $qry->fetchInto($refExpID);
+        $refExpID = isset($refExpID[0]) ? $refExpID[0] : 0;
+    }
+    // Print the result of the query
+    if ($debug) {echo "The first exp_id of tonight is: $refExpID<br>";}
 
     #do a query of raw/chip/cam/warp counts for this night, split by chunk. 
@@ -485,7 +469,7 @@
     $query .= "    count(if(rawExp.comment LIKE '%visit 2%',1,NULL)) AS Nvis2,count(if(rawExp.comment LIKE '%visit 3%',1,NULL)) AS Nvis3,";
     $query .= "    count(if(rawExp.comment LIKE '%visit 4%',1,NULL)) AS Nvis4, count(if(camProcessedExp.sigma_ra <= 5 AND camProcessedExp.sigma_dec <= 5 AND camProcessedExp.quality = 0,1,NULL)) AS Ncamgood,";
-    $query .= "    count(if(camProcessedExp.sigma_ra > 5 OR camProcessedExp.sigma_dec > 5 OR camProcessedExp.quality > 0,1,NULL)) AS Ncambad";
+    $query .= "    count(if(camProcessedExp.fwhm_major > 12 OR camProcessedExp.sigma_ra > 5 OR camProcessedExp.sigma_dec > 5 OR camProcessedExp.quality > 0,1,NULL)) AS Ncambad";
     $query .= "    FROM rawExp LEFT JOIN chipRun USING (exp_id) LEFT JOIN camRun USING (chip_id) JOIN camProcessedExp USING (cam_id) LEFT JOIN fakeRun USING (cam_id) LEFT JOIN warpRun USING (fake_id)";
-    $query .= "    WHERE dateobs like '$date%' AND exp_id > $refExpID[0] AND exp_type = 'OBJECT' AND rawExp.comment like '%visit%'";
+    $query .= "    WHERE exp_name like '$expname' AND exp_type = 'OBJECT' AND rawExp.comment like '%visit%'";
     $query .= "    AND (obs_mode LIKE '%SS%' OR obs_mode LIKE '%BRIGHT%') AND obs_mode NOT LIKE 'ENGINEERING' AND obs_mode NOT LIKE 'MANUAL'";
     $query .= "    GROUP BY chunk ORDER BY dateobs) as suba ";
@@ -495,11 +479,13 @@
     $query .= "      (SELECT substr(comment, 1, position(' ' in comment)) AS chunk,count(warpSkyfile.quality) AS Nwarpskycell,count(if(warpSkyfile.quality > 0,1,NULL)) AS Nwarpskycellbad";
     $query .= "      FROM rawExp LEFT JOIN chipRun USING (exp_id) LEFT JOIN camRun USING (chip_id) LEFT JOIN fakeRun USING (cam_id) LEFT JOIN warpRun USING (fake_id) JOIN warpSkyfile USING (warp_id)";
-    $query .= "      WHERE dateobs like '$date%' AND exp_id > $refExpID[0] AND exp_type = 'OBJECT' AND rawExp.comment like '%visit%'";
+    $query .= "      WHERE exp_name like '$expname' AND exp_type = 'OBJECT' AND rawExp.comment like '%visit%'";
     $query .= "      AND (obs_mode LIKE '%SS%' OR obs_mode LIKE '%BRIGHT%') AND obs_mode NOT LIKE 'ENGINEERING' AND obs_mode NOT LIKE 'MANUAL'";
     $query .= "      GROUP BY exp_name) as subc";
     $query .= "    GROUP BY chunk) AS subb ";
     $query .= "ON suba.chunk=subb.chunk";
-
+ 
+    if ($debug) {echo "$query<br>";}
     $qry = $projectdb->query($query);
+
     if (dberror($qry)) {
         echo "<b>error querying SQL table</b><br>\n";
@@ -512,5 +498,6 @@
     echo $table;
     echo "<tr>";
-    createTableTitle("Status of last night's chunks", 10);
+    $mjdday = getMJD();
+    createTableTitle("Status of night $mjdday chunks", 10);
     echo "<tr>";
     createTableColumnHeader("Chunk");
@@ -556,7 +543,9 @@
         $query1 = "SELECT suba.chunk, SUM(IF(suba.Nvisits = 2,1,NULL)) as totvis2, SUM(IF(suba.Nvisits = 3 OR suba.Nvisits = 4,2,NULL)) as totvis34 FROM";
         $query1 .= "    (SELECT substr(comment, 1, position(' ' in comment)) AS chunk,count(distinct(comment)) AS Nvisits FROM";
-        $query1 .= "    rawExp LEFT JOIN chipRun USING (exp_id) LEFT JOIN camRun USING (chip_id) WHERE dateobs like '$date%'";
-        $query1 .= "    AND exp_id > $refExpID[0] AND exp_type = 'OBJECT' AND rawExp.comment like '%visit%' AND (obs_mode LIKE '%SS%' OR obs_mode LIKE '%BRIGHT%') AND obs_mode NOT LIKE 'ENGINEERING' AND obs_mode NOT LIKE 'MANUAL'";
+        $query1 .= "    rawExp LEFT JOIN chipRun USING (exp_id) LEFT JOIN camRun USING (chip_id) ";
+        $query1 .= "    WHERE exp_name like '$expname'";
+        $query1 .= "    AND exp_type = 'OBJECT' AND rawExp.comment like '%visit%' AND (obs_mode LIKE '%SS%' OR obs_mode LIKE '%BRIGHT%') AND obs_mode NOT LIKE 'ENGINEERING' AND obs_mode NOT LIKE 'MANUAL'";
         $query1 .= "    AND substr(comment, 1, position(' ' in comment)) LIKE '$chunkname%' group by object) as suba group by chunk;";
+
         $qry1 = $projectdb->query($query1);
         while ($qry1->fetchInto($row)) {$NexpWWdiff = $row[1] + $row[2];}
@@ -565,5 +554,6 @@
         $query2 = "     SELECT diff_id,warp1,stack1,warp2,stack2 FROM ";
         $query2 .= "           diffInputSkyfile JOIN warpRun ON (warp1=warp_id OR warp2=warp_id) JOIN fakeRun USING (fake_id) JOIN camRun USING (cam_id) JOIN camProcessedExp USING (cam_id) JOIN chipRun USING (chip_id) JOIN rawExp USING (exp_id)";
-        $query2 .= "           WHERE rawExp.dateobs LIKE '$date%' AND exp_id > $refExpID[0] AND exp_type = 'OBJECT' AND rawExp.comment like '%visit%' AND (obs_mode LIKE '%SS%' OR obs_mode LIKE '%BRIGHT%')";
+        $query2 .= "           WHERE exp_name like '$expname'";
+        $query2 .= "           AND exp_type = 'OBJECT' AND rawExp.comment like '%visit%' AND (obs_mode LIKE '%SS%' OR obs_mode LIKE '%BRIGHT%')";
         $query2 .= "            AND obs_mode NOT LIKE 'ENGINEERING' AND obs_mode NOT LIKE 'MANUAL' AND substr(comment, 1, position(' ' in comment)) LIKE '$chunkname%' GROUP By diff_id";
         $qry2 = $projectdb->query($query2);
@@ -670,9 +660,9 @@
         $query .= " JOIN camRun USING (chip_id)";
         $query .= " JOIN camProcessedExp USING (cam_id)";
-        $query .= " WHERE dateobs LIKE '$date%'";
-        $query .= " AND exp_id > $refExpID[0]"; 
+        //$query .= " WHERE dateobs LIKE '$date%' AND exp_id > $refExpID"; 
+        $query .= " WHERE exp_name like '$expname'";
         $query .= " AND exp_type = 'OBJECT'";
         $query .= " AND (obs_mode LIKE '%SS%' OR obs_mode LIKE '%BRIGHT%') AND obs_mode NOT LIKE 'ENGINEERING' AND obs_mode NOT LIKE 'MANUAL'";
-        $query .= " AND (camProcessedExp.quality > 0 OR camProcessedExp.sigma_ra > 5 OR camProcessedExp.sigma_dec > 5)";
+        $query .= " AND (camProcessedExp.fwhm_major > 12 OR camProcessedExp.quality > 0 OR camProcessedExp.sigma_ra > 5 OR camProcessedExp.sigma_dec > 5)";
         $query .= " ORDER BY comment";
 
@@ -710,5 +700,5 @@
         $query = "SELECT exp_name,warp_id,count(warpSkyfile.quality) AS Nwarpskycell,count(if(warpSkyfile.quality > 0,1,NULL)) AS Nwarpskycellbad, comment";
         $query .= "      FROM rawExp LEFT JOIN chipRun USING (exp_id) LEFT JOIN camRun USING (chip_id) LEFT JOIN fakeRun USING (cam_id) LEFT JOIN warpRun USING (fake_id) JOIN warpSkyfile USING (warp_id)";
-        $query .= "      WHERE dateobs like '$date%' AND exp_id > $refExpID[0]";
+        $query .= "      WHERE exp_name like '$expname'";
         $query .= "      AND (obs_mode LIKE '%SS%' OR obs_mode LIKE '%BRIGHT%') AND obs_mode NOT LIKE 'ENGINEERING' AND obs_mode NOT LIKE 'MANUAL'";
         $query .= "      GROUP BY exp_name ORDER BY comment";
@@ -747,8 +737,10 @@
         $query = "     SELECT diff_id,warp1,stack1,warp2,stack2,exp_name,comment FROM ";
         $query .= "           diffInputSkyfile JOIN warpRun ON (warp1=warp_id OR warp2=warp_id) JOIN fakeRun USING (fake_id) JOIN camRun USING (cam_id) JOIN camProcessedExp USING (cam_id) JOIN chipRun USING (chip_id) JOIN rawExp USING (exp_id)";
-        $query .= "           WHERE rawExp.dateobs LIKE '$date%' AND exp_id > $refExpID[0] AND (obs_mode LIKE '%SS%' OR obs_mode LIKE '%BRIGHT%') AND obs_mode NOT LIKE 'ENGINEERING' AND obs_mode NOT LIKE 'MANUAL'";
+        $query .= "           WHERE exp_name like '$expname'";
+        $query .= "           AND (obs_mode LIKE '%SS%' OR obs_mode LIKE '%BRIGHT%') AND obs_mode NOT LIKE 'ENGINEERING' AND obs_mode NOT LIKE 'MANUAL'";
         $query .= "           GROUP By diff_id";
+        if ($debug) {echo "$query<br>";}
+
         $qry1 = $projectdb->query($query);
-
         while ($qry1->fetchInto($row)) {
             #distinguish between WW and WS diffs based on stack2
@@ -811,6 +803,5 @@
     $query .= " JOIN chipRun USING (exp_id)";
     $query .= " JOIN camRun USING (chip_id)";
-    $query .= " WHERE dateobs LIKE '$date%'";
-    $query .= " AND exp_id > $refExpID[0]"; 
+    $query .= " WHERE exp_name like '$expname'";
     $query .= " AND exp_type = 'OBJECT'";
     $query .= " AND (obs_mode LIKE '%SS%' OR obs_mode LIKE '%BRIGHT%') AND obs_mode NOT LIKE 'ENGINEERING' AND obs_mode NOT LIKE 'MANUAL'";
@@ -826,6 +817,6 @@
             $query .= " JOIN chipRun USING (exp_id)";
             $query .= " JOIN camRun USING (chip_id)";
-            $query .= " WHERE dateobs LIKE '$date%' AND comment LIKE '$row[1]'";
-            $query .= " AND exp_id > $refExpID[0]"; 
+            $query .= " WHERE exp_name like '$expname'";
+            $query .= " AND comment LIKE '$row[1]'";
             $query .= " AND exp_type = 'OBJECT'";
             $query .= " AND (obs_mode LIKE '%SS%' OR obs_mode LIKE '%BRIGHT%') AND obs_mode NOT LIKE 'ENGINEERING' AND obs_mode NOT LIKE 'MANUAL'";
@@ -863,13 +854,9 @@
 
 
-    // timer finished
+    // End timer
     echo "<tr><th colspan=10>";
-    $time = microtime();
-    $time = explode(' ', $time);
-    $time = $time[1] + $time[0];
-    $finish = $time;
-    $total_time = round(($finish - $start), 3);
-    echo "loading in $total_time seconds.";
-    $start= $finish;
+    $total_time = round(microtime(true) - $start, 3);
+    echo "<center>loading in $total_time seconds<br></center>";
+
     echo "</th></tr>";
     echo "</table></br>";
@@ -914,9 +901,7 @@
         $selectedState, $selectedLabel, $selectedStage, $plotType) {
 
-    // timer start
-    $time = microtime();
-    $time = explode(' ', $time);
-    $time = $time[1] + $time[0];
-    $start = $time;
+    // Start timer
+    $start = microtime(true);
+
 
     // function begin
@@ -1010,6 +995,6 @@
             }
           }
-      // echo "getStateAndFaults $db, $thisLabel, $proj, $selectedState, $stage, $str, $anyFaults<br>";
       getStateAndFaults($db, $thisLabel, $proj, $selectedState, $stage, $str, $anyFaults);
+      //echo "getStateAndFaults $db, $thisLabel, $proj, $selectedState, $stage, $str, $anyFaults<br>";
 
       $cellcolor = 0;
@@ -1045,13 +1030,9 @@
     echo "</tr>\n";
 
-    // timer finished
+    // End timer
     echo "<tr><th colspan=11>";
-    $time = microtime();
-    $time = explode(' ', $time);
-    $time = $time[1] + $time[0];
-    $finish = $time;
-    $total_time = round(($finish - $start), 3);
-    echo "loading in $total_time seconds.";
-    $start= $finish;
+    $total_time = round(microtime(true) - $start, 3);
+    echo "<center>loading plot in $total_time seconds<br></center>";
+
     echo "</th></tr>";
     echo "</table><br>";
@@ -1204,8 +1185,5 @@
 
     // timer start
-    $time = microtime();
-    $time = explode(' ', $time);
-    $time = $time[1] + $time[0];
-    $start = $time;
+    $start = microtime(true);
 
     // function begin
@@ -1223,13 +1201,8 @@
 
     // timer finished
-#    echo "<tr><th colspan=11>";
-    $time = microtime();
-    $time = explode(' ', $time);
-    $time = $time[1] + $time[0];
-    $finish = $time;
-    $total_time = round(($finish - $start), 3);
-#    echo "loading in $total_time seconds.";
-    $start= $finish;
-#    echo "</th></tr>";
+    echo "<tr><th colspan=11>";
+    $total_time = round((microtime(true) - $start), 3);
+    echo "loading in $total_time seconds.";
+    echo "</th></tr>";
     echo "</table><br>";
 
@@ -1272,13 +1245,8 @@
 ###########################################################################
 function createServersTable($pass, $proj, $selectedMode, $db, $servers, $selectedLabel, $selectedStage, $plotType) {
-
-    // timer start
-    $time = microtime();
-    $time = explode(' ', $time);
-    $time = $time[1] + $time[0];
-    $start = $time;
-
-    // function begin
-    // set up table columns
+    // Start the timer
+    $start = microtime(true);
+
+    // Display table header
     global $table;
     echo $table;
@@ -1286,14 +1254,18 @@
     createTableTitle("Pantasks server status", 3);
     echo "<tr>";
-    createTableColumnHeader("Server");
-    createTableColumnHeader("Alive?");
-    createTableColumnHeader("Running?");
+
+    // Define column headers in an array for flexibility
+    $columnHeaders = array("Server", "Alive?", "Running?");
+    foreach ($columnHeaders as $header) {
+        createTableColumnHeader($header);
+    }
     echo "</tr>\n";
 
     foreach ($servers as &$server) {
-
         getServerStatus($db,$proj, $server, $alive, $running);
 
         echo "<tr>\n";
+
+        // Generate the link once and pass it to the cell function
         $link = "czartool_labels.php?pass=".$pass
             ."&proj=".$proj
@@ -1304,19 +1276,15 @@
             ."&plottype=".$plotType;
 
+        // Display server row cells
         createFormattedTableCell(1, $link, $server, 0, 0);
         createFormattedTableCell(0, "", $alive ? "yes" : "NO", !$alive, 0);
         createFormattedTableCell(0, "", $running ? "yes" : "NO", !$running, 0);
+
         echo "</tr>\n";
     }
 
-    // timer finished
+    // Display loading time
     echo "<tr><th colspan=5>";
-    $time = microtime();
-    $time = explode(' ', $time);
-    $time = $time[1] + $time[0];
-    $finish = $time;
-    $total_time = round(($finish - $start), 3);
-    echo "loading in $total_time seconds.";
-    $start= $finish;
+    echo "loading in " . round((microtime(true) - $start), 3) . " seconds.";
     echo "</th></tr>";
     echo "</table><br>\n";
@@ -1515,16 +1483,21 @@
 #
 ###########################################################################
-function createSummitDataTable2($projectdb, $pass, $proj) {
+function createSummitDataTable2($projectdb, $pass, $proj, $debug) {
 
     // timer start
-    $time = microtime();
-    $time = explode(' ', $time);
-    $time = $time[1] + $time[0];
-    $start = $time;
-
-    // function begin
-    $date = gmdate("Y-m-d");
-    $datem1 = gmdate("Y-m-d",strtotime ( "-1 day") );
-    $datetime = gmdate("H:i:s");
+    $start = microtime(true);
+
+    // Define constants
+    $mjdDay = getMJD();
+    $expname = "%{$mjdDay}%";
+
+    $mjdDaym1 = $mjdDay - 1;
+    $expnamem1 = "%{$mjdDaym1}%";
+
+    $mjdDaym5 = $mjdDay - 5;
+    $expnamem5 = "o{$mjdDaym5}%";
+
+    $currentDate = gmdate("Y-m-d H:i:s");
+    $previousDate = gmdate("Y-m-d", strtotime("-1 day"));
 
     // set up the table
@@ -1533,27 +1506,41 @@
     echo $table;
     echo "<tr>";
-    createTableTitle("Data status tonight $date <br> current time $datetime (UTC)", 4);
+      createTableTitle("Data status for night $mjdDay  <br> current time UT: $currentDate", 4);
     echo "<tr>";
-
-    createTableColumnHeader("Exposure type");
-    createTableColumnHeader("<a href=\"czartool_labels.php?pass=".$pass."&proj=".$proj."&label=all&stage=summitExp\"><font color=\"blue\">summitExp status</font></a>");
-    createTableColumnHeader("<a href=\"czartool_labels.php?pass=".$pass."&proj=".$proj."&label=all&stage=downloadExp\"><font color=\"blue\">downloadExp status</font></a>");
-    createTableColumnHeader("<a href=\"czartool_labels.php?pass=".$pass."&proj=".$proj."&label=all&stage=rawExp\"><font color=\"blue\">rawExp </a>/
-                             <a href=\"czartool_labels.php?pass=".$pass."&proj=".$proj."&label=all&stage=newExp\"><font color=\"blue\"> newExp</font></a>");
-    $sql = "SELECT summitExp.exp_type,pzDownloadExp.state,rawExp.state,COUNT(*) FROM summitExp 
-            LEFT JOIN pzDownloadExp USING (summit_id) LEFT JOIN rawExp on summitExp.exp_name = rawExp.exp_name 
-            WHERE summitExp.dateobs like '$date%' group by summitExp.exp_type,pzDownloadExp.state,rawExp.state";
+      createTableColumnHeader("Exposure type");
+      createTableColumnHeader("<a href=\"czartool_labels.php?pass=".$pass."&proj=".$proj."&label=all&stage=summitExp\"><font color=\"blue\">summitExp status</font></a>");
+      createTableColumnHeader("<a href=\"czartool_labels.php?pass=".$pass."&proj=".$proj."&label=all&stage=downloadExp\"><font color=\"blue\">downloadExp status</font></a>");
+      createTableColumnHeader("<a href=\"czartool_labels.php?pass=".$pass."&proj=".$proj."&label=all&stage=rawExp\"><font color=\"blue\">rawExp </a>/
+                               <a href=\"czartool_labels.php?pass=".$pass."&proj=".$proj."&label=all&stage=newExp\"><font color=\"blue\"> newExp</font></a>");
+
+    $sql = "
+        SELECT sum_type, pzstate, rawstate, count(*), sum_exp, pz_exp, raw_exp 
+        FROM 
+          (SELECT summitExp.exp_type as sum_type, pzDownloadExp.state as pzstate, rawExp.state as rawstate, summitExp.exp_name as sum_exp, pzDownloadExp.exp_name as pz_exp, rawExp.exp_name as raw_exp
+           FROM summitExp
+           LEFT JOIN pzDownloadExp USING (summit_id)
+           LEFT JOIN rawExp ON summitExp.exp_name = rawExp.exp_name
+           WHERE summitExp.summit_id >= (
+               SELECT COALESCE(MIN(summit_id), 0) 
+               FROM summitExp 
+               WHERE exp_name LIKE '$expnamem5'
+            ) 
+            AND summitExp.exp_name LIKE '$expname' ORDER BY summitExp.dateobs desc) as sub 
+        GROUP BY sum_type, pzstate, rawstate";
+    if ($debug) {echo "$sql<br>";}
+
     $qry = $projectdb->query($sql);
     while ($qry->fetchInto($tmp)) {
-        if ($tmp[1] == NULL) { 
-          echo  "<tr><td>$tmp[0]<td> null <td> null <td bgcolor=\"yellow\"> <font color=\"red\">$tmp[3]";
+        list($expType, $downloadState, $rawState, $count, $summit_exp, $pz_exp, $raw_exp) = $tmp;
+        if ($downloadState == NULL) { 
+          echo  "<tr><td> $expType ($summit_exp) <td> loading imfiles <td> null <td bgcolor=\"yellow\"> <font color=\"red\">$count";
         } else {
-          if ($tmp[1] == 'run') { 
-            echo  "<tr><td>$tmp[0]<td> loading <td> null <td bgcolor=$columnHeaderColor> <font color=\"red\">$tmp[3]"; 
+          if ($downloadState == 'run') { 
+            echo  "<tr><td> $expType ($summit_exp) <td> summit_copy ($pz_exp) <td> saving ($pz_exp) <td bgcolor=$columnHeaderColor> <font color=\"red\">$count"; 
           } else {
-            if ($tmp[2] == NULL) { 
-              echo  "<tr><td>$tmp[0] <td> $tmp[1] <td> loading <td bgcolor=$columnHeaderColor> <font color=\"blue\">$tmp[3]";
+            if ($rawState == NULL) { 
+              echo  "<tr><td> $expType ($summit_exp) <td> $downloadState ($pz_exp) <td> registering ($pz_exp) <td bgcolor=$columnHeaderColor> <font color=\"blue\">$count";
             } else {
-              echo  "<tr><td>$tmp[0]<td> $tmp[1] <td> downloaded <td> $tmp[3]";
+              echo  "<tr><td> $expType ($summit_exp) <td> $downloadState ($pz_exp) <td> $rawState ($raw_exp) <td> $count";
             }
           }
@@ -1561,35 +1548,85 @@
     }
 
-    echo "<tr><th colspan=4>Last night $datem1 (UTC)";
-    $sql = "SELECT summitExp.exp_type,pzDownloadExp.state,rawExp.state,COUNT(*) FROM summitExp 
-            LEFT JOIN pzDownloadExp USING (summit_id) LEFT JOIN rawExp on summitExp.exp_name = rawExp.exp_name 
-            WHERE summitExp.dateobs like '$datem1%' group by summitExp.exp_type,pzDownloadExp.state,rawExp.state";
+    echo "<tr><th colspan=4>Last night $previousDate (UTC), $mjdDaym1 (MJD)";
+    $sql = "
+        SELECT sum_type, pzstate, rawstate, count(*), sum_exp, pz_exp, raw_exp 
+        FROM 
+          (SELECT summitExp.exp_type as sum_type, pzDownloadExp.state as pzstate, rawExp.state as rawstate, summitExp.exp_name as sum_exp, pzDownloadExp.exp_name as pz_exp, rawExp.exp_name as raw_exp
+           FROM summitExp
+           LEFT JOIN pzDownloadExp USING (summit_id)
+           LEFT JOIN rawExp ON summitExp.exp_name = rawExp.exp_name
+           WHERE summitExp.summit_id >= (
+               SELECT COALESCE(MIN(summit_id), 0) 
+               FROM summitExp 
+               WHERE exp_name LIKE '$expnamem5'
+            ) 
+            AND summitExp.exp_name LIKE '$expnamem1' ORDER BY summitExp.dateobs desc) as sub 
+        GROUP BY sum_type, pzstate, rawstate";
+    // $sql = "
+    //     SELECT summitExp.exp_type, pzDownloadExp.state, rawExp.state, COUNT(*)
+    //     FROM summitExp
+    //     LEFT JOIN pzDownloadExp USING (summit_id)
+    //     LEFT JOIN rawExp ON summitExp.exp_name = rawExp.exp_name
+    //     WHERE summitExp.summit_id >= (
+    //         SELECT COALESCE(MIN(summit_id), 0) 
+    //         FROM summitExp 
+    //         WHERE exp_name LIKE '$expnamem5'
+    //     ) 
+    //     AND summitExp.exp_name LIKE '$expnamem1'
+    //     GROUP BY summitExp.exp_type, pzDownloadExp.state, rawExp.state";
+    if ($debug) {echo "$sql<br>";}
+
     $qry = $projectdb->query($sql);
     while ($qry->fetchInto($tmp)) {
-        if ($tmp[1] == NULL) { 
-          echo  "<tr><td>$tmp[0]<td> null <td> null <td bgcolor=\"yellow\"> <font color=\"red\">$tmp[3]";
+        list($expType, $downloadState, $rawState, $count, $summit_exp, $pz_exp, $raw_exp) = $tmp;
+        if ($downloadState == NULL) { 
+          echo  "<tr><td> $expType ($summit_exp) <td> loading imfiles <td> null <td bgcolor=\"yellow\"> <font color=\"red\">$count";
         } else {
-          if ($tmp[1] == 'run') { 
-            echo  "<tr><td>$tmp[0]<td> loading <td> null <td bgcolor=$columnHeaderColor> <font color=\"red\">$tmp[3]"; 
+          if ($downloadState == 'run') { 
+            echo  "<tr><td> $expType ($summit_exp) <td> summit_copy ($pz_exp) <td> saving ($pz_exp) <td bgcolor=$columnHeaderColor> <font color=\"red\">$count"; 
           } else {
-            if ($tmp[2] == NULL) { 
-              echo  "<tr><td>$tmp[0] <td> $tmp[1] <td> loading <td bgcolor=$columnHeaderColor> <font color=\"blue\">$tmp[3]";
+            if ($rawState == NULL) { 
+              echo  "<tr><td> $expType ($summit_exp) <td> $downloadState ($pz_exp) <td> registering <td bgcolor=$columnHeaderColor> <font color=\"blue\">$count";
             } else {
-              echo  "<tr><td>$tmp[0]<td> $tmp[1] <td> downloaded <td> $tmp[3]";
+              echo  "<tr><td> $expType ($summit_exp) <td> $downloadState ($pz_exp) <td> $rawState ($raw_exp) <td> $count";
             }
           }
         }
     }
-    // timer finished
+    //while ($qry->fetchInto($tmp)) {
+    //    list($expType, $downloadState, $rawState, $count) = $tmp;
+    //    if ($downloadState == NULL) { 
+    //      echo  "<tr><td> $expType <td> null <td> null <td bgcolor=\"yellow\"> <font color=\"red\">$count";
+    //    } else {
+    //      if ($downloadState == 'run') { 
+    //        echo  "<tr><td> $expType <td> loading <td> null <td bgcolor=$columnHeaderColor> <font color=\"red\">$count"; 
+    //      } else {
+    //        if ($rawState == NULL) { 
+    //          echo  "<tr><td> $expType <td> $downloadState <td> loading <td bgcolor=$columnHeaderColor> <font color=\"blue\">$count";
+    //        } else {
+    //          echo  "<tr><td> $expType <td> $downloadState <td> download ($rawState) <td> $count";
+    //        }
+    //      }
+    //    }
+    //}
+
     echo "<tr><th colspan=4>";
-    $time = microtime();
-    $time = explode(' ', $time);
-    $time = $time[1] + $time[0];
-    $finish = $time;
-    $total_time = round(($finish - $start), 3);
-    echo "loading in $total_time seconds.";
-    $start= $finish;
+    // End timer
+    $total_time = round(microtime(true) - $start, 3);
+    echo "<center>loading in $total_time seconds<br></center>";
+
     echo "</th></tr>";
     echo "</table><br>";
+}
+
+function formatState($state) {
+    // Formats display of the state for better readability
+    if (is_null($state)) {
+        return "<span style='color: red;'>null</span>";
+    } elseif ($state == 'run') {
+        return "<span style='color: red;'>loading</span>";
+    } else {
+        return $state;
+    }
 }
 ###########################################################################
@@ -1608,5 +1645,5 @@
     echo "<script type=\"text/javascript\" src=\"loader.js\"></script>";
     echo "<br><div class=\"chartWithOverlay\" style=\"position: relative; width: 640px\">"; 
-    echo "  <div id=\"disk_div\" style=\"width:640px; height:1200px\"></div>";
+    echo "  <div id=\"disk_div\" style=\"width:640px; height:4000px\"></div>";
     echo "  <div class=\"overlay\" style=\"position: absolute; width: 100px; top: 35px; right: 20px;\">";
     echo "    <div style=\"font-size: 12px; height: 14px; border: 1px solid; background-color: #00ff00\"><center>Free</div>";
@@ -1686,7 +1723,8 @@
    echo "     },";
    echo "     bar: { groupWidth: '95%' },";
-   echo "     chartArea: {left:70, top:30, right:20, bottom:40},";
-   echo "     fontSize: 12,";
-   echo "     isStacked: true";
+   echo "     chartArea: {left:100, top:30, right:20, bottom:40},";
+   echo "     fontSize: 15,";
+   echo "     isStacked: true,";
+   echo "     colors: ['#76A7FA', '#FF5733', '#C70039', '#900C3F', '#581845']";
    echo "   };";
    echo "   var chart = new google.visualization.BarChart(document.getElementById('disk_div'));";
@@ -1821,14 +1859,18 @@
 
     $date = gmdate("Y-m-d");
-    $sql = "SELECT MAX(exp_id) FROM rawExp WHERE dateobs >= date_sub('$date', interval 20 day) AND dateobs <= date_sub('$date', interval 10 day)";
+    $sql = "SELECT MAX(exp_id) FROM rawExp WHERE dateobs BETWEEN DATE_SUB('$date', INTERVAL 20 DAY) AND DATE_SUB('$date', INTERVAL 10 DAY)";
+    if ($debug) {echo "$sql<br>";}
     $qry = $db->query($sql);
+
     if (dberror($qry)) {
-        print "*** WARNING: no data in period 10-20 days before requested date (query will be slower) **\n";
+        echo "*** WARNING: No data in the period 10-20 days before requested date (query will be slower) **\n";
         $refExpID = 0;
-    }
-    $qry->fetchInto($refExpID);
-    if ($refExpID[0] = 'NULL') {
-        $refExpID[0] = 0;
-    }
+    } else {
+        $qry->fetchInto($refExpID);
+        $refExpID = isset($refExpID[0]) ? $refExpID[0] : 0;
+    }
+    // Print the result of the query
+    if ($debug) {echo "The result of MAX(exp_id) is: $refExpID<br>";}
+    {echo "The result of MAX(exp_id) is: $refExpID<br>";}
 
     #Query for the needed data
@@ -1838,4 +1880,6 @@
 #    $sql.= " WHERE (rawExp.dateobs > utc_date() - INTERVAL 14 hour) and (rawExp.dateobs < utc_date() + INTERVAL 10 hour)";
     $sql.= " WHERE (rawExp.dateobs > utc_date())";
+#    $sql.= " WHERE (rawExp.dateobs > '2024-10-24')";
+#    $sql.= " AND (rawExp.dateobs < '2024-10-25')";
     $sql.= " AND exp_id > $refExpID[0]";
     $sql.= " AND exp_type = 'OBJECT' AND camRun.state like 'full' ORDER BY dateobs asc;";
@@ -1843,4 +1887,5 @@
     $qry = $db->query($sql);
     if (dberror($qry)) {echo "<b>error with $sql </b><br>\n";}
+#    echo "<b>error with $sql </b><br>\n";
     while ($qry->fetchInto($row)) {
         $DQarray[] = $row;
@@ -2044,10 +2089,10 @@
 
         #define new zeropoints
-        if(substr($row[5],0,1) == 'g') {$col_string = 'blue'; $zpt_off = $zp - 25.013;}
-        if(substr($row[5],0,1) == 'r') {$col_string = 'red'; $zpt_off = $zp - 24.840;}
-        if(substr($row[5],0,1) == 'i') {$col_string = '#6a3d9a'; $zpt_off = $zp - 24.711;}
-        if(substr($row[5],0,1) == 'z') {$col_string = 'green'; $zpt_off = $zp - 24.30;}
-        if(substr($row[5],0,1) == 'y') {$col_string = 'cyan'; $zpt_off = $zp - 23.57;}
-        if(substr($row[5],0,1) == 'w') {$col_string = 'grey'; $zpt_off = $zp - 26.000;}
+        if(substr($row[5],0,1) == 'g') {$col_string = '#00f000'; $zpt_off = $zp - 25.013;}
+        if(substr($row[5],0,1) == 'r') {$col_string = '#f00000'; $zpt_off = $zp - 24.840;}
+        if(substr($row[5],0,1) == 'i') {$col_string = '#f05000'; $zpt_off = $zp - 24.711;}
+        if(substr($row[5],0,1) == 'z') {$col_string = '#0050a0'; $zpt_off = $zp - 24.300;}
+        if(substr($row[5],0,1) == 'y') {$col_string = '#ffe000'; $zpt_off = $zp - 23.570;}
+        if(substr($row[5],0,1) == 'w') {$col_string = '#808080'; $zpt_off = $zp - 26.060;}
 
         $tt_string1 = sprintf('time: %s\n zeropoint: %s\n filter: %s\n exp_time: %s\n comment: %s', $timestamp, $zp,$row[5],$row[6],$row[7]);
@@ -2101,4 +2146,7 @@
 }
 
+
+
+
 ###########################################################################
 #
@@ -2108,8 +2156,5 @@
 function Gettimeseries($db, $selectedMode, $selectedLabel, $proj, $selectedStage) {
     // timer start
-    $time = microtime();
-    $time = explode(' ', $time);
-    $time = $time[1] + $time[0];
-    $start = $time;
+    $start = microtime(true);
 
     // google chart javascript source code
@@ -2512,11 +2557,5 @@
  
     // timer end
-    $time = microtime();
-    $time = explode(' ', $time);
-    $time = $time[1] + $time[0];
-    $finish = $time;
-    $total_time = round(($finish - $start), 3);
-    $start= $finish;
-    echo "<center>loading in $total_time seconds</center>";
+    echo "<center> loading in " . round((microtime(true) - $start), 3) . " seconds. </center>";
 }
 
@@ -2994,4 +3033,370 @@
 }
 
+
+###########################################################################
+#
+# Get data quality
+#
+###########################################################################
+function getDataQuality2($db) {
+    // Start timer
+    $start = microtime(true);
+
+    $mjdDay  = getMJD();
+    $expname = "o".$mjdDay."%";
+
+    $sql = "SELECT SUBTIME(dateobs, '10:00:00') AS time, 
+                   round(( 367*YEAR(dateobs)- FLOOR((7 * (YEAR(dateobs) + FLOOR((MONTH(dateobs) + 9) / 12))) / 4) + FLOOR(275 * MONTH(dateobs) / 9) 
+                   + DAY(dateobs) + 1721013.5 + (HOUR(dateobs) / 24.0) + (MINUTE(dateobs) / 1440.0) + (SECOND(dateobs) / 86400.0) - 2400000.5), 5) AS MJD, 
+                   filter, comment, ra*180/pi() as RA, decl*180/pi() as DECL, exp_name, alt, az, fwhm_major, fwhm_minor, zpt_obs, zpt_stdev, rawExp.exp_id 
+            FROM rawExp JOIN chipRun using (exp_id) JOIN camRun using (chip_id) JOIN camProcessedExp using (cam_id) 
+            WHERE rawExp.exp_name like '$expname'
+               AND exp_type = 'OBJECT' 
+               AND camRun.state like 'full' 
+               AND camProcessedExp.fault = 0 
+               AND camProcessedExp.zpt_obs != 0; ";
+
+    $DQarray = array();
+    $qry = $db->query($sql);
+    if (dberror($qry)) {
+        echo "<b>Error with $sql</b><br>\n";
+        return;
+    }
+    
+    while ($qry->fetchInto($row)) {
+        $DQarray[] = $row;
+    }
+    
+    // Ensure $DQarray is not empty
+    if (empty($DQarray)) {
+        echo "<center><b> No data for MJD: $mjdDay </b></center>";
+        return; // Stop execution if no data to encode
+    }
+    
+    // Convert data array to JSON for easier handling in JavaScript
+    $dataJson = json_encode($DQarray);
+    
+    if ($dataJson === false) {
+        echo "<b>Error encoding JSON:</b> " . json_last_error_msg(); // Display any JSON encoding errors
+        return; // Stop execution if JSON encoding fails
+    }
+    
+    echo "<script>console.log(" . json_encode($dataJson) . ");</script>"; // Log JSON output to console for debugging
+
+echo <<<HTML
+<script type="text/javascript" src="loader.js"></script>
+
+<script type="text/javascript">
+    google.charts.load('current', {packages: ['corechart']});
+
+    // Use the encoded JSON directly in JavaScript
+    const dataArray = JSON.parse('{$dataJson}'); // Directly parse the PHP JSON string
+
+    // draw FWHM vs MJD
+    function drawFWHMChart() {
+        var data = new google.visualization.DataTable();
+            data.addColumn('number', 'MJD');
+            data.addColumn('number', 'FWHM_major');
+            data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}});
+            data.addColumn('number', 'FWHM_minor');
+            data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}});
+            data.addColumn('number', 'seeing ~ 1"');
+            data.addColumn('number', 'seeing ~ 3"');
+
+        const rows = dataArray.map(row => {
+            const [timestamp, mjd, filter, comment, ra, dec, exp_name, alt, az, iq_fwhm_maj, iq_fwhm_min, zpt_obs, zpt_stdev, exp_id] = row;
+
+            return [
+                parseFloat(mjd),      // Position Angle
+                parseFloat(iq_fwhm_maj),         // RA_offset (AST_R0)
+                "expname: "+exp_name+"<br>exp_id: "+exp_id+"<br>HST: "+timestamp+"<br>RA: "+ra+"<br>DEC: "+dec+"<br>filter: "+filter+"<br>comment: "+comment,
+                parseFloat(iq_fwhm_min),        // Dec_offset (AST_D0)
+                "expname: "+exp_name+"<br>exp_id: "+exp_id+"<br>HST: "+timestamp+"<br>RA: "+ra+"<br>DEC: "+dec+"<br>filter: "+filter+"<br>comment: "+comment,
+                4,
+                12
+            ];
+        });
+
+        data.addRows(rows);
+
+        const options = {
+            title: 'FWHM (MJD)',
+            titleTextStyle: {color: 'black', fontSize: 15},
+            width: '100%',
+            height: 480,
+            legend: { position: 'top', alignment: 'center' },
+            series: {
+                0: { color: '#0000ff', pointSize: 3, lineWidth: 1 },
+                1: { color: '#33a532', pointSize: 3, lineWidth: 1 },
+                2: { color: 'red', lineWidth: 2, pointSize: 0 },
+                3: { color: 'red', lineWidth: 2, lineDashStyle: [8, 4], pointSize: 0 }
+            },
+            intervals: { color: 'red', lineWidth: 2, style: 'sticks' },
+            hAxis: {
+                title: 'MJD',
+                gridlines: {count: -1}
+            },
+            vAxis: {
+                title: 'FWHM (pixels)',
+            },
+            tooltip: { isHtml: true }, // Render tooltips as HTML
+            chartArea: {left: '8%', top: 60, right: '5%', bottom: 50}, // Adjust left and right
+            fontSize: 12,
+        };
+
+        const chart = new google.visualization.LineChart(document.getElementById('dq_div_fwhm'));
+        chart.draw(data, options);
+    }
+
+    // draw zoomed zerpoint vs mjd
+    function drawZOOMZPTChart() {
+        var data = new google.visualization.DataTable();
+        data.addColumn('number', 'MJD');
+
+        // Add columns for each filter type to handle separate colors
+        data.addColumn('number', 'g (24.563, 25.013)');
+        data.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn('number', 'r (24.750, 24.840)');
+        data.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn('number', 'i (24.611, 24.711)');
+        data.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn('number', 'z (24.240, 24.300)');
+        data.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn('number', 'y (23.320, 23.570)');
+        data.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn('number', 'w (26.000, 26.300)');
+        data.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn({type: 'number', role: 'interval'});
+
+        const rows = dataArray.map(row => {
+            const [timestamp, mjd, filter, comment, ra, dec, exp_name, alt, az, iq_fwhm_maj, iq_fwhm_min, zpt_obs, zpt_stdev, exp_id] = row;
+
+            // Initialize all filter values as null
+            let zp_g = null, zp_r = null, zp_i = null, zp_z = null, zp_y = null, zp_w = null;
+
+            // Set the zeropoint offset based on filter and assign it to the correct series
+            switch (filter[0]) {
+                case 'g':
+                    zp_g = zpt_obs - 24.563;
+                    break;
+                case 'r':
+                    zp_r = zpt_obs - 24.750;
+                    break;
+                case 'i':
+                    zp_i = zpt_obs - 24.611;
+                    break;
+                case 'z':
+                    zp_z = zpt_obs - 24.240;
+                    break;
+                case 'y':
+                   zp_y = zpt_obs - 23.320;
+                    break;
+                case 'w':
+                    zp_w = zpt_obs - 26.000;
+                    break;
+            }
+
+            return [
+                parseFloat(mjd), // MJD value
+                zp_g, "expname: "+exp_name+"<br>exp_id: "+exp_id+"<br>HST: "+timestamp+"<br>RA: "+ra+"<br>DEC: "+dec+"<br>filter: "+filter+"<br>comment: "+comment,  parseFloat(zp_g - zpt_stdev), parseFloat(zp_g - zpt_stdev*-1),
+                zp_r, "expname: "+exp_name+"<br>exp_id: "+exp_id+"<br>HST: "+timestamp+"<br>RA: "+ra+"<br>DEC: "+dec+"<br>filter: "+filter+"<br>comment: "+comment,  parseFloat(zp_r - zpt_stdev), parseFloat(zp_r - zpt_stdev*-1),
+                zp_i, "expname: "+exp_name+"<br>exp_id: "+exp_id+"<br>HST: "+timestamp+"<br>RA: "+ra+"<br>DEC: "+dec+"<br>filter: "+filter+"<br>comment: "+comment,  parseFloat(zp_i - zpt_stdev), parseFloat(zp_i - zpt_stdev*-1),
+                zp_z, "expname: "+exp_name+"<br>exp_id: "+exp_id+"<br>HST: "+timestamp+"<br>RA: "+ra+"<br>DEC: "+dec+"<br>filter: "+filter+"<br>comment: "+comment,  parseFloat(zp_z - zpt_stdev), parseFloat(zp_z - zpt_stdev*-1),
+                zp_y, "expname: "+exp_name+"<br>exp_id: "+exp_id+"<br>HST: "+timestamp+"<br>RA: "+ra+"<br>DEC: "+dec+"<br>filter: "+filter+"<br>comment: "+comment,  parseFloat(zp_y - zpt_stdev), parseFloat(zp_y - zpt_stdev*-1),
+                zp_w, "expname: "+exp_name+"<br>exp_id: "+exp_id+"<br>HST: "+timestamp+"<br>RA: "+ra+"<br>DEC: "+dec+"<br>filter: "+filter+"<br>comment: "+comment,  parseFloat(zp_w - zpt_stdev), parseFloat(zp_w - zpt_stdev*-1)
+            ];
+        });
+
+        data.addRows(rows);
+
+        const options = {
+            title: 'Zeropoint zoom-in (MJD)',
+            titleTextStyle: { color: 'black', fontSize: 15 },
+            width: '100%',
+            height: 480,
+            legend: { position: 'top', alignment: 'start', maxLines: 3 },
+            series: {
+                0: { color: '#00f000', pointSize: 10, pointShape: 'circle',   linewidth: 1},  // 'g' filter
+                1: { color: '#f00000', pointSize: 10, pointShape: 'triangle', linewidth: 1},  // 'r' filter
+                2: { color: '#f05000', pointSize: 10, pointShape: 'square',   linewidth: 1},  // 'i' filter
+                3: { color: '#0050a0', pointSize: 10, pointShape: 'diamond',  linewidth: 1},  // 'z' filter
+                4: { color: '#ffe000', pointSize: 10, pointShape: 'star',     linewidth: 1},  // 'y' filter
+                5: { color: '#808080', pointSize: 10, pointShape: 'polygon',  linewidth: 1},  // 'w' filter
+            },
+            intervals: { color: 'red', lineWidth: 1, style: 'sticks' },
+            hAxis: {
+                title: 'MJD',
+                gridlines: { count: -1 }
+            },
+            vAxis: {
+                title: 'Zeropoint (mag)',
+                viewWindow: {   min: -1.00, max: .5    },
+            },
+            tooltip: { isHtml: true },
+            chartArea: { left: '9%', top: 60, right: '5%', bottom: 50 },
+            fontSize: 12,
+        };
+
+        const chart = new google.visualization.LineChart(document.getElementById('dq_div_zoomzpt'));
+        chart.draw(data, options);
+    }
+
+    // draw zeropoint vs mjd
+    function drawZPTChart() {
+        var data = new google.visualization.DataTable();
+        data.addColumn('number', 'MJD');
+
+        // Add columns for each filter type to handle separate colors
+        data.addColumn('number', 'g' );
+        data.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn('number', 'r' );
+        data.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn('number', 'i' );
+        data.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn('number', 'z' );
+        data.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn('number', 'y' );
+        data.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn('number', 'w' );
+        data.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}});
+        data.addColumn({type: 'number', role: 'interval'});
+        data.addColumn({type: 'number', role: 'interval'});
+
+        // Count occurrences of each filter
+        const filterCounts = { g: 0, r: 0, i: 0, z: 0, y: 0, w: 0 };
+       const rows = dataArray.map(row => {
+            const [timestamp, mjd, filter, comment, ra, dec, exp_name, alt, az, iq_fwhm_maj, iq_fwhm_min, zpt_obs, zpt_stdev, exp_id] = row;
+
+            // Initialize all filter values as null
+            let zp_g = null, zp_r = null, zp_i = null, zp_z = null, zp_y = null, zp_w = null;
+
+            // Increment the count for the filter
+            if (filterCounts.hasOwnProperty(filter[0])) {
+                filterCounts[filter[0]] += 1;
+            }
+
+            // Set the zeropoint offset based on filter and assign it to the correct series
+            switch (filter[0]) {
+                case 'g':
+                    zp_g = zpt_obs - 0.0;
+                    break;
+                case 'r':
+                    zp_r = zpt_obs - 0.0;
+                    break;
+                case 'i':
+                    zp_i = zpt_obs - 0.0;
+                    break;
+                case 'z':
+                    zp_z = zpt_obs - 0.0;
+                    break;
+                case 'y':
+                    zp_y = zpt_obs - 0.0;
+                    break;
+                case 'w':
+                    zp_w = zpt_obs - 0.0;
+                    break;
+            }
+
+            return [
+                parseFloat(mjd), // MJD value
+                zp_g, "expname: "+exp_name+"<br>exp_id: "+exp_id+"<br>HST: "+timestamp+"<br>RA: "+ra+"<br>DEC: "+dec+"<br>filter: "+filter+"<br>comment: "+comment,  parseFloat(zp_g - zpt_stdev), parseFloat(zp_g - zpt_stdev*-1),
+                zp_r, "expname: "+exp_name+"<br>exp_id: "+exp_id+"<br>HST: "+timestamp+"<br>RA: "+ra+"<br>DEC: "+dec+"<br>filter: "+filter+"<br>comment: "+comment,  parseFloat(zp_r - zpt_stdev), parseFloat(zp_r - zpt_stdev*-1),
+                zp_i, "expname: "+exp_name+"<br>exp_id: "+exp_id+"<br>HST: "+timestamp+"<br>RA: "+ra+"<br>DEC: "+dec+"<br>filter: "+filter+"<br>comment: "+comment,  parseFloat(zp_i - zpt_stdev), parseFloat(zp_i - zpt_stdev*-1),
+                zp_z, "expname: "+exp_name+"<br>exp_id: "+exp_id+"<br>HST: "+timestamp+"<br>RA: "+ra+"<br>DEC: "+dec+"<br>filter: "+filter+"<br>comment: "+comment,  parseFloat(zp_z - zpt_stdev), parseFloat(zp_z - zpt_stdev*-1),
+                zp_y, "expname: "+exp_name+"<br>exp_id: "+exp_id+"<br>HST: "+timestamp+"<br>RA: "+ra+"<br>DEC: "+dec+"<br>filter: "+filter+"<br>comment: "+comment,  parseFloat(zp_y - zpt_stdev), parseFloat(zp_y - zpt_stdev*-1),
+                zp_w, "expname: "+exp_name+"<br>exp_id: "+exp_id+"<br>HST: "+timestamp+"<br>RA: "+ra+"<br>DEC: "+dec+"<br>filter: "+filter+"<br>comment: "+comment,  parseFloat(zp_w - zpt_stdev), parseFloat(zp_w - zpt_stdev*-1),
+
+            ];
+        });
+      data.addRows(rows);
+
+        // Include counts in the title using string concatenation
+        const countsTitle = 'Zeropoint (MJD) g: ' + filterCounts.g + ', r: ' + filterCounts.r + ', i: ' + filterCounts.i + ', z: ' + filterCounts.z + ', y: ' + filterCounts.y + ', w: ' + filterCounts.w;
+
+
+        console.log(countsTitle);
+
+        const options = {
+            title: countsTitle,
+            titleTextStyle: { color: 'black', fontSize: 15 },
+            width: '100%',
+            height: 480,
+            legend: { position: 'top', alignment: 'center' },
+            series: {
+                0: { color: '#00f000', pointSize: 10, pointShape: 'circle',   linewidth: 1},  // 'g' filter
+                1: { color: '#f00000', pointSize: 10, pointShape: 'triangle', linewidth: 1},  // 'r' filter
+                2: { color: '#f05000', pointSize: 10, pointShape: 'square',   linewidth: 1},  // 'i' filter
+                3: { color: '#0050a0', pointSize: 10, pointShape: 'diamond',  linewidth: 1},  // 'z' filter
+                4: { color: '#ffe000', pointSize: 10, pointShape: 'star',     linewidth: 1},  // 'y' filter
+                5: { color: '#808080', pointSize: 10, pointShape: 'polygon',  linewidth: 1},  // 'w' filter
+            },
+            intervals: { color: 'red', lineWidth: 1, style: 'sticks' },
+            hAxis: {
+                title: 'MJD',
+                gridlines: { count: -1 }
+            },
+            vAxis: {
+                title: 'Zeropoint (mag)'
+            },
+            tooltip: { isHtml: true },
+            chartArea: { left: '9%', top: 60, right: '5%', bottom: 50 },
+            fontSize: 12,
+        };
+
+        const chart = new google.visualization.LineChart(document.getElementById('dq_div_zpt'));
+        chart.draw(data, options);
+    }
+
+    google.charts.setOnLoadCallback(drawFWHMChart);
+    google.charts.setOnLoadCallback(drawZPTChart);
+    google.charts.setOnLoadCallback(drawZOOMZPTChart);
+
+</script>
+
+<div class="chartWithOverlay" style="position: relative; width: 640px; height:500px;">
+    <div id="dq_div_fwhm" style="width:640px;"></div>
+    <div class="overlay" style="position: absolute; width: 400px; bottom: 60px; left: 85px;"></div>
+</div>
+
+<div class="chartWithOverlay" style="position: relative; width: 640px; height:500px;">
+    <div id="dq_div_zpt" style="width:640px;"></div>
+    <div class="overlay" style="position: absolute; width: 400px; bottom: 60px; left: 85px;"></div>
+</div>
+
+<div class="chartWithOverlay" style="position: relative; width: 640px; height:500px;">
+    <div id="dq_div_zoomzpt" style="width:640px;"></div>
+    <div class="overlay" style="position: absolute; width: 400px; bottom: 60px; left: 85px;"></div>
+</div>
+
+HTML;
+    // End timer
+    $total_time = round(microtime(true) - $start, 3);
+    echo "<center>loading plot in $total_time seconds<br></center>";
+
+}
+
+
+
 function getprocrate ($proc1, $proc0, $trange) {
   if($proc1 > $proc0) {
