Changeset 43071
- Timestamp:
- Jul 13, 2026, 4:28:09 PM (4 days ago)
- Location:
- trunk/ippMonitor
- Files:
-
- 10 edited
-
config.dat.in (modified) (1 diff)
-
configure.tcsh (modified) (1 diff)
-
czartool/czarpoll.pl (modified) (1 diff)
-
raw/czartool_labels.php (modified) (1 diff)
-
raw/dataquality.php (modified) (1 diff)
-
raw/functions.php (modified) (24 diffs)
-
raw/getimage.php (modified) (1 diff)
-
raw/pointing.php (modified) (2 diffs)
-
raw/showimage.php (modified) (2 diffs)
-
raw/site.php.in (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/ippMonitor/config.dat.in
r42384 r43071 121 121 $HOST_MAILMAN = ""; 122 122 $LABEL_MAILMAN = ""; 123 124 $HOST_ITCVXLAN = ""; 125 $LABEL_ITCVXLAN = ""; 126 127 $HOST_ITCVXLAN_BACKUP = ""; 128 $LABEL_ITCVXLAN_BACKUP = ""; 129 130 $HOST_ATRCVXLAN = ""; 131 $LABEL_ATRCVXLAN = ""; -
trunk/ippMonitor/configure.tcsh
r42384 r43071 228 228 cat tmp.1 | sed "s|@WWWBIN@|$wwwbin|" > tmp.2 229 229 cat tmp.2 | sed "s|@LIBDIR@|$libdir|" > tmp.1 230 cat tmp.1 | sed "s|@PERLLIB@|$libdir| " > tmp.2230 cat tmp.1 | sed "s|@PERLLIB@|$libdir|g" > tmp.2 231 231 cat tmp.2 | sed "s|@SITE@|$site|" > tmp.1 232 232 cat tmp.1 | sed "s|@DBI@|$DBI|" > tmp.2 -
trunk/ippMonitor/czartool/czarpoll.pl
r42972 r43071 414 414 # check ippdb host IPP-2338 415 415 print "* Checking ippdb hosts\n"; 416 my @ippdb_hosts = qw(ipphome2 ipphome3 ippdb01 ippdb05 ippdb06 ippdb0 9ippdb11 ippdb12 ippdb13 ippdb14);416 my @ippdb_hosts = qw(ipphome2 ipphome3 ippdb01 ippdb05 ippdb06 ippdb08 ippdb11 ippdb12 ippdb13 ippdb14); 417 417 if($dbupdate == 1) {check_disk_usage_and_update($czarDb, @ippdb_hosts);} 418 418 -
trunk/ippMonitor/raw/czartool_labels.php
r42972 r43071 349 349 //showPingStatus($HOST_CONFLUENCE, $LABEL_CONFLUENCE); 350 350 showPingStatus($HOST_MAILMAN, $LABEL_MAILMAN); 351 showPingStatus($HOST_ITCVXLAN, $LABEL_ITCVXLAN); 352 showPingStatus($HOST_ITCVXLAN_BACKUP, $LABEL_ITCVXLAN_BACKUP); 353 showPingStatus($HOST_ATRCVXLAN, $LABEL_ATRCVXLAN); 351 354 352 355 // end time -
trunk/ippMonitor/raw/dataquality.php
r42972 r43071 72 72 73 73 echo getDataQuality($projectdb, $range, $proj); 74 echo "<div class=\"chartWithOverlay\" style=\"position: relative; width: 100%; height:200px;\"></div>"; 74 75 75 76 menu_end(); -
trunk/ippMonitor/raw/functions.php
r42972 r43071 283 283 cam_id : \${row.cam_id}<br> 284 284 moon_angle : \${row.moon_angle}<br> 285 raw_chips : \${row.n_raw}<br> 286 good_chips : \${row.g_chips}<br> 285 n_chips : \${Number(row.null_bg) + Number(row.good_chip)}<br> 286 good_phot : \${row.good_phot}<br> 287 good_astro : \${row.good_astro}<br> 288 null_bg : \${row.null_bg}<br> 289 poor_chips : \${row.poor_chip}<br> 287 290 comment : \${row.comment}<br> 291 <img src="http://ippmonitor.ipp.ifa.hawaii.edu/ippMonitor/getimage.php?name=\${row.image_path}&rule=PPIMAGE.JPEG2&camera=${proj}&class_id=NONE"> 288 292 `; 289 293 } … … 302 306 303 307 // testing day 304 //$mjdDay = 60945;305 308 $mjdDay = getMJD(); 309 //$mjdDay = 61109; 306 310 $mjdDay_yearback = $mjdDay - 366; 307 311 $mjdDay_monthback = $mjdDay - 32; … … 335 339 $stmt->execute([':expname' => $expname]); 336 340 $row = $stmt->fetch(PDO::FETCH_ASSOC); 337 // if (!empty($row['min_exp_id'])) {338 // $min_exp_id = $row['min_exp_id'];339 // } else {340 // echo "<center><b>No results found for min_exp_id</b></center>";341 // }342 343 341 if (!empty($row['min_exp_id'])) { 344 342 $min_exp_id = $row['min_exp_id']; 345 echo "<center><b>min_exp_id:$min_exp_id $mjdDay_monthback$mjdDay</b></center>";343 echo "<center><b>min_exp_id:$min_exp_id month:$mjdDay_monthback today:$mjdDay</b></center>"; 346 344 } else { 347 echo "<center><b>No results found for min_exp_id:$min_exp_id $mjdDay_monthback $mjdDay</b></center>"; 348 } 349 350 //echo "<br><br>"; 345 echo "<center><b>No results found for min_exp_id:$min_exp_id month:$mjdDay_monthback today:$mjdDay</b></center>"; 346 } 351 347 352 348 // Determine the date constraint based on the range … … 380 376 381 377 // Updated SQL query 382 $sql = "select * from (SELECT SUBTIME(dateobs, '10:00:00') AS time, AST_R0, AST_D0, AST_RS, AST_DS, AST_T0, posang,383 round(( 367*YEAR(dateobs)- FLOOR((7 * (YEAR(dateobs) + FLOOR((MONTH(dateobs) + 9) / 12))) / 4) + FLOOR(275 * MONTH(dateobs) / 9)384 + DAY(dateobs) + 1721013.5 + (HOUR(dateobs) / 24.0) + (MINUTE(dateobs) / 1440.0) + (SECOND(dateobs) / 86400.0) - 2400000.5), 5) AS MJD,385 filter, comment, round(ra*180/pi(), 5) as RA, round(decl*180/pi(), 5) as DECL, exp_name, alt,386 az, fwhm_major, fwhm_minor, zpt_obs, zpt_stdev, airmass, exp_time,387 rawExp.exp_id, camRun.label, moon_angle, cam_id, BIT_COUNT(astrom_chips) AS working_chips388 FROM rawExp389 JOIN chipRun USING (exp_id)390 JOIN camRun USING (chip_id)391 JOIN camProcessedExp USING (cam_id)392 WHERE $dateConstraint393 AND exp_type = 'OBJECT'394 AND camRun.state LIKE 'full'395 AND camProcessedExp.fault = 0396 AND camProcessedExp.zpt_obs != 0 ORDER BY RAND() limit 10000) as sub order by time;";397 398 $stmt = $db->query($sql);399 $DQarray = $stmt->fetchAll(PDO::FETCH_ASSOC);400 401 // Ensure $DQarray is not empty402 if (empty($DQarray)) {403 echo "<center><b> No data for MJD: $mjdDay </b></center>";404 return; // Stop execution if no data to encode405 }406 407 // Convert data array to JSON for easier handling in JavaScript408 $dataJson = json_encode($DQarray);409 410 if ($dataJson === false) {411 echo "<b>Error encoding JSON:</b> " . json_last_error_msg(); // Display any JSON encoding errors412 return; // Stop execution if JSON encoding fails413 }414 415 echo "<script>console.log(" . json_encode($dataJson) . ");</script>"; // Log JSON output to console for debugging416 417 418 echo <<<HTML419 <script type="text/javascript">420 // Use the encoded JSON directly in JavaScript421 const dataArray = JSON.parse('{$dataJson}'); // Directly parse the PHP JSON string422 423 const nRows = dataArray.length;424 425 // draw pointing vs mjd426 function drawMJDChart() {427 var data = new google.visualization.DataTable();428 data.addColumn('number', 'MJD');429 data.addColumn('number', 'RA_offset (AST_R0)');430 data.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}});431 data.addColumn({type: 'number', role: 'interval'});432 data.addColumn({type: 'number', role: 'interval'});433 data.addColumn('number', 'Dec_offset (AST_D0)');434 data.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}});435 data.addColumn({type: 'number', role: 'interval'});436 data.addColumn({type: 'number', role: 'interval'});437 data.addColumn('number', '20 TP unit ~5.1"');438 data.addColumn('number', '-20 TP unit ~5.1"');439 440 const mjdValues = dataArray.map(r => parseFloat(r.MJD));441 let mjdMin0 = Math.min(...mjdValues);442 const mjdMin = Math.floor(mjdMin0 * 10) / 10; // 1 decimal place or floor/ceil depending on your needs443 let mjdMax0 = Math.max(...mjdValues);444 const mjdMax = Math.ceil(mjdMax0 * 10) / 10; // 1 decimal place or floor/ceil depending on your needs445 // Extract the first MJD value from dataArray446 const firstMJD = dataArray.length > 0 ? Math.floor(parseFloat(dataArray[0].MJD)) : "N/A";447 console.log("First MJD Value:", firstMJD);448 const mjdoff = mjdMin;449 450 const mjdVals = [];451 const rows = dataArray.map(row => {452 const mjd = parseFloat(row.MJD) - mjdoff; // MJD shift to first one453 mjdVals.push(mjd); // collect MJD offset values454 const ra_off = parseFloat(row.AST_R0); // RA_offset (AST_R0)455 const dec_off = parseFloat(row.AST_D0); // DEC_offset (AST_D0)456 const ra_sct = parseFloat(row.AST_RS); // RA_scatter (AST_RS)457 const dec_sct = parseFloat(row.AST_DS); // DEC_scatter (AST_DS)458 const tooltip = buildTooltip(row); // Tooltip459 460 return [461 mjd, ra_off, tooltip, ra_off-ra_sct, ra_off+ra_sct, dec_off, tooltip, dec_off-dec_sct, dec_off+dec_sct,462 20, // Dummy value for 20 TP unit463 -20 // Dummy value for -20 TP unit464 ];465 });466 467 data.addRows(rows);468 469 // After building rows:470 const allVerticalVals = rows.flatMap(r => [471 r[3], // ra_off - ra_sct472 r[4], // ra_off + ra_sct473 r[7], // dec_off - dec_sct474 r[8] // dec_off + dec_sct475 ]).filter(v => !isNaN(v)); // â476 remove NaN values477 478 // If array is empty after filtering, use safe defaults479 const minY = allVerticalVals.length ? Math.min(...allVerticalVals) : 0;480 const maxY = allVerticalVals.length ? Math.max(...allVerticalVals) : 0;481 482 // Clamp values: use ±100 if beyond 100483 const yMin = Math.abs(minY) > 150 ? -150 : minY;484 const yMax = Math.abs(maxY) > 150 ? 150 : maxY;485 486 console.log("minY:", minY, yMin, "maxY:", maxY, yMax);487 488 // Now compute min and max489 const mjdMin1 = Math.min(...mjdVals);490 const mjdMax1 = Math.max(...mjdVals);491 492 const defaultSeries = { pointSize: 5, lineWidth: 0 };493 494 const titleText = `Pointing Offset vs. MJD ({$proj}) â \${nRows} rows\${dataArray.length >= 10000 ? " (sampled)" : ""}`;495 const options = {496 //title: 'Pointing Offset vs. MJD ({$proj})',497 title: titleText,498 titleTextStyle: {color: 'black', fontSize: 15},499 width: '100%',500 height: 480,501 legend: { position: 'top', alignment: 'center' },502 series: {503 0: { color: '#0000ff', pointSize: 3, lineWidth: 0 }, // RA_offset series504 1: { color: '#33a532', pointSize: 3, lineWidth: 0 }, // Dec_offset series505 2: { color: 'red', lineWidth: 2, lineDashStyle: [8, 4], pointSize: 0 }, // Line at y = 20506 3: { color: 'red', lineWidth: 2, lineDashStyle: [8, 4], pointSize: 0 } // Line at y = -20507 },508 intervals: { lineWidth: .5, style: 'sticks' },509 interval: {510 0: {color: 'blue'}, // interval columns attached to first series511 1: {color: 'green'} // interval columns attached to second series512 },513 hAxis: {514 title: 'MJD - ' + mjdoff + ' (day)',515 viewWindow: {516 min: 0., // small padding517 max: mjdMax1 + 0.005518 },519 gridlines: { count: -1 } // auto gridlines520 },521 vAxis: {522 title: 'Pointing Offset (TP units)',523 viewWindow: {524 min: yMin,525 max: yMax526 }527 },528 tooltip: { isHtml: true }, // Render tooltips as HTML529 chartArea: {left: '7%', top: 60, right: '4%', bottom: 50}, // Adjust left and right530 fontSize: 15,531 };532 533 const chart = new google.visualization.ScatterChart(document.getElementById('dq_div_mjd'));534 chart.draw(data, options);535 }536 537 // position angle538 function drawPOSChart() {539 var data = new google.visualization.DataTable();540 data.addColumn('number', 'Posang');541 data.addColumn('number', 'RA_offset (AST_R0)');542 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}});543 data.addColumn('number', 'Dec_offset (AST_D0)');544 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}});545 546 const rows = dataArray.map(row => {547 const posang = parseFloat(row.posang); // Position Angle548 const ra_off = parseFloat(row.AST_R0); // RA_offset (AST_R0)549 const dec_off = parseFloat(row.AST_D0); // DEC_offset (AST_D0)550 const tooltip = buildTooltip(row); // Tooltip551 return [552 posang, ra_off, tooltip, dec_off, tooltip553 ];554 });555 556 data.addRows(rows);557 558 const titleText = `Pointing Offset vs. Position Angle ({$proj}) â \${nRows} rows\${dataArray.length >= 10000 ? " (sampled)" : ""}`;559 const options = {560 title: titleText,561 titleTextStyle: {color: 'black', fontSize: 15},562 width: '100%',563 height: 480,564 legend: { position: 'top', alignment: 'center' },565 // pointSize: 5, // Point size for scatter plot566 // lineWidth: 2,567 series: {568 0: { color: '#0000ff', pointSize: 3, lineWidth: 0 }, // RA_offset series569 1: { color: '#33a532', pointSize: 3, lineWidth: 0 }, // Dec_offset series570 },571 intervals: { color: 'red', lineWidth: 2, style: 'sticks' },572 hAxis: {573 title: 'Position Angle (deg)',574 gridlines: {count: -1}575 },576 vAxis: {577 title: 'Pointing Offset (TP units)',578 },579 tooltip: { isHtml: true }, // Render tooltips as HTML580 chartArea: {left: '7%', top: 60, right: '4%', bottom: 50}, // Adjust left and right581 fontSize: 15,582 };583 584 const chart = new google.visualization.ScatterChart(document.getElementById('dq_div_pos'));585 chart.draw(data, options);586 }587 588 function drawALTChart() {589 var data = new google.visualization.DataTable();590 data.addColumn('number', 'Altitute');591 data.addColumn('number', 'RA_offset (AST_R0)');592 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}});593 data.addColumn('number', 'Dec_offset (AST_D0)');594 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}});595 596 const rows = dataArray.map(row => {597 const alt = parseFloat(row.alt); // Altitude598 const ra_off = parseFloat(row.AST_R0); // RA_offset (AST_R0)599 const dec_off = parseFloat(row.AST_D0); // DEC_offset (AST_D0)600 const tooltip = buildTooltip(row); // Tooltip601 return [602 alt, ra_off, tooltip, dec_off, tooltip603 ];604 });605 606 data.addRows(rows);607 608 const titleText = `Pointing Offset vs. Altitude ({$proj}) â \${nRows} rows\${dataArray.length >= 10000 ? " (sampled)" : ""}`;609 const options = {610 title: titleText,611 titleTextStyle: {color: 'black', fontSize: 15},612 width: '100%',613 height: 480,614 legend: { position: 'top', alignment: 'center' },615 series: {616 0: { color: '#0000ff', pointSize: 3, lineWidth: 0 }, // RA_offset series617 1: { color: '#33a532', pointSize: 3, lineWidth: 0 }, // Dec_offset series618 },619 intervals: { color: 'red', lineWidth: 2, style: 'sticks' },620 hAxis: {621 title: 'Altitude (deg)',622 gridlines: {count: -1}623 },624 vAxis: {625 title: 'Pointing Offset (TP units)',626 },627 tooltip: { isHtml: true }, // Render tooltips as HTML628 //chartArea: {left: 80, top: 50, right: 20, bottom: 50},629 chartArea: {left: '7%', top: 60, right: '4%', bottom: 50}, // Adjust left and right630 fontSize: 15,631 };632 633 const chart = new google.visualization.ScatterChart(document.getElementById('dq_div_alt'));634 chart.draw(data, options);635 }636 637 function drawAZChart() {638 var data = new google.visualization.DataTable();639 data.addColumn('number', 'Azumith');640 data.addColumn('number', 'RA_offset (AST_R0)');641 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}});642 data.addColumn('number', 'Dec_offset (AST_D0)');643 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}});644 645 const rows = dataArray.map(row => {646 const az = parseFloat(row.az); // Azumith647 const ra_off = parseFloat(row.AST_R0); // RA_offset (AST_R0)648 const dec_off = parseFloat(row.AST_D0); // DEC_offset (AST_D0)649 const tooltip = buildTooltip(row); // Tooltip650 return [651 az, ra_off, tooltip, dec_off, tooltip652 ];653 });654 655 data.addRows(rows);656 657 const titleText = `Pointing Offset vs. Azumith ({$proj}) â \${nRows} rows\${dataArray.length >= 10000 ? " (sampled)" : ""}`;658 const options = {659 title: titleText,660 titleTextStyle: {color: 'black', fontSize: 15},661 width: '100%',662 height: 480,663 legend: { position: 'top', alignment: 'center' },664 series: {665 0: { color: '#0000ff', pointSize: 3, lineWidth: 0 }, // RA_offset series666 1: { color: '#33a532', pointSize: 3, lineWidth: 0 }, // Dec_offset series667 },668 intervals: { color: 'red', lineWidth: 2, style: 'sticks' },669 hAxis: {670 title: 'Azumith (deg)',671 gridlines: {count: -1}672 },673 vAxis: {674 title: 'Pointing Offset (TP units)',675 },676 tooltip: { isHtml: true }, // Render tooltips as HTML677 //chartArea: {left: 80, top: 50, right: 20, bottom: 50},678 chartArea: {left: '7%', top: 60, right: '4%', bottom: 50}, // Adjust left and right679 fontSize: 15,680 };681 682 const chart = new google.visualization.ScatterChart(document.getElementById('dq_div_az'));683 chart.draw(data, options);684 }685 686 687 function drawScatChart() {688 var data = new google.visualization.DataTable();689 data.addColumn('number', 'tmp');690 data.addColumn('number', 'RA_scat (AST_RS)');691 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}});692 data.addColumn('number', 'Dec_scat (AST_DS)');693 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}});694 695 const rows = dataArray.map(row => {696 const par = parseFloat(row.MJD);697 const ra_scat = parseFloat(row.AST_RS); // RA_scat (AST_RS)698 const dec_scat = parseFloat(row.AST_DS); // DEC_scat (AST_DS)699 const tooltip = buildTooltip(row); // Tooltip700 return [701 par, ra_scat, tooltip, dec_scat, tooltip702 ];703 });704 705 data.addRows(rows);706 707 const titleText = `Pointing Offset vs. MJD ({$proj}) â \${nRows} rows\${dataArray.length >= 10000 ? " (sampled)" : ""}`;708 const options = {709 title: titleText,710 titleTextStyle: {color: 'black', fontSize: 15},711 width: '100%',712 height: 480,713 legend: { position: 'top', alignment: 'center' },714 series: {715 0: { color: '#0000ff', pointSize: 3, lineWidth: 0 }, // RA_offset series716 1: { color: '#33a532', pointSize: 3, lineWidth: 0 }, // Dec_offset series717 },718 intervals: { color: 'red', lineWidth: 2, style: 'sticks' },719 hAxis: {720 title: 'MJD',721 gridlines: {count: -1}722 },723 vAxis: {724 title: 'Pointing Scatter (TP units)',725 viewWindow: {726 min: 0,727 // max: 20728 }729 },730 tooltip: { isHtml: true }, // Render tooltips as HTML731 //chartArea: {left: 80, top: 50, right: 20, bottom: 50},732 chartArea: {left: '7%', top: 60, right: '4%', bottom: 50}, // Adjust left and right733 fontSize: 15,734 };735 736 const chart = new google.visualization.ScatterChart(document.getElementById('dq_div_scat'));737 chart.draw(data, options);738 }739 740 google.charts.setOnLoadCallback(drawMJDChart);741 google.charts.setOnLoadCallback(drawPOSChart);742 google.charts.setOnLoadCallback(drawALTChart);743 google.charts.setOnLoadCallback(drawAZChart);744 google.charts.setOnLoadCallback(drawScatChart);745 </script>746 747 <div class="chartWithOverlay" style="position: relative; width: 1240px; height:500px;">748 <div id="dq_div_mjd" style="width:1240px;"></div>749 </div>750 751 <div class="chartWithOverlay" style="position: relative; width: 1240px; height:500px;">752 <div id="dq_div_scat" style="width:1240px;"></div>753 </div>754 755 <div class="chartWithOverlay" style="position: relative; width: 1240px; height:500px;">756 <div id="dq_div_pos" style="width:1240px;"></div>757 </div>758 759 <div class="chartWithOverlay" style="position: relative; width: 1240px; height:500px;">760 <div id="dq_div_alt" style="width:1240px;"></div>761 </div>762 763 <div class="chartWithOverlay" style="position: relative; width: 1240px; height:500px;">764 <div id="dq_div_az" style="width:1240px;"></div>765 </div>766 HTML;767 768 // End timer769 $total_time = round(microtime(true) - $start, 3);770 echo "<center>Loading plot in $total_time seconds<br></center>";771 772 }773 774 ###########################################################################775 #776 # Get data quality777 #778 ###########################################################################779 function getDataQuality($db, $range = 'week', $proj) {780 // Start timer781 $start = microtime(true);782 783 // testing day784 $mjdDay = getMJD();785 //$mjdDay = 60950;786 $mjdDay_yearback = $mjdDay - 366;787 $mjdDay_monthback = $mjdDay - 32;788 $min_exp_id = 0;789 790 791 // Determine the reference exp_name based on the selected range792 switch ($range) {793 case 'year':794 $expname = "o" . $mjdDay_yearback . "%";795 break;796 case 'month':797 $expname = "o" . $mjdDay_monthback . "%";798 break;799 case 'week':800 $expname = "o" . ($mjdDay - 7) . "%";801 break;802 case 'yesterday':803 $expname = "o" . ($mjdDay - 1) . "%";804 break;805 case 'today':806 $expname = "o" . $mjdDay . "%";807 break;808 default:809 $expname = "o" . ($mjdDay - 7) . "%"; // Default: week810 break;811 }812 813 // --- PDO query for min_exp_id ---814 $stmt = $db->prepare("SELECT MIN(exp_id) AS min_exp_id FROM rawExp WHERE exp_name LIKE :expname");815 $stmt->execute([':expname' => $expname]);816 $row = $stmt->fetch(PDO::FETCH_ASSOC);817 if (!empty($row['min_exp_id'])) {818 $min_exp_id = $row['min_exp_id'];819 echo "<center><b>min_exp_id:$min_exp_id $mjdDay_monthback $mjdDay</b></center>";820 } else {821 echo "<center><b>No results found for min_exp_id:$min_exp_id $mjdDay_monthback $mjdDay</b></center>";822 }823 824 // Determine the date constraint based on the range825 switch ($range) {826 case 'year':827 $dateConstraint = "rawExp.dateobs >= NOW() - INTERVAL 365 DAY AND rawExp.exp_id >= $min_exp_id";828 break;829 case 'month':830 $dateConstraint = "rawExp.dateobs >= NOW() - INTERVAL 30 DAY AND rawExp.exp_id >= $min_exp_id";831 break;832 case 'week':833 $expnames = array();834 for ($i = 0; $i < 7; $i++) {835 $expnames[] = "rawExp.exp_name LIKE 'o" . ($mjdDay - $i) . "%'";836 }837 $dateConstraint = "(" . implode(" OR ", $expnames) . ") AND rawExp.exp_id >= $min_exp_id";838 $qday = $mjdDay - 6; // or something meaningful for week839 break;840 case 'yesterday':841 $dateConstraint = "rawExp.exp_name LIKE 'o" . ($mjdDay - 1) . "%' AND rawExp.exp_id >= $min_exp_id";842 $qday = $mjdDay - 1;843 break;844 case 'today':845 $dateConstraint = "rawExp.exp_name LIKE 'o$mjdDay%' AND rawExp.exp_id >= $min_exp_id";846 $qday = $mjdDay;847 break;848 case 'all':849 $dateConstraint = "rawExp.exp_id >= 0";850 break;851 default: // Default to last night852 $dateConstraint = "rawExp.exp_name LIKE 'o" . ($mjdDay - 1) . "%' AND rawExp.exp_id >= $min_exp_id";853 $qday = $mjdDay - 1;854 break;855 }856 857 // Updated SQL query858 $sql1 = "select * from (SELECT SUBTIME(dateobs, '10:00:00') AS time, AST_R0, AST_D0, AST_RS, AST_DS, AST_T0, posang,859 round(( 367*YEAR(dateobs)- FLOOR((7 * (YEAR(dateobs) + FLOOR((MONTH(dateobs) + 9) / 12))) / 4) + FLOOR(275 * MONTH(dateobs) / 9)860 + DAY(dateobs) + 1721013.5 + (HOUR(dateobs) / 24.0) + (MINUTE(dateobs) / 1440.0) + (SECOND(dateobs) / 86400.0) - 2400000.5), 5) AS MJD,861 filter, comment, round(ra*180/pi(), 5) as RA, round(decl*180/pi(), 5) as DECL, exp_name, alt,862 az, fwhm_major, fwhm_minor, zpt_obs, zpt_stdev, airmass, exp_time,863 rawExp.exp_id, camRun.label, moon_angle, cam_id, BIT_COUNT(astrom_chips) AS working_chips864 FROM rawExp865 JOIN chipRun USING (exp_id)866 JOIN camRun USING (chip_id)867 JOIN camProcessedExp USING (cam_id)868 WHERE $dateConstraint869 AND exp_type = 'OBJECT'870 AND camRun.state LIKE 'full'871 AND camProcessedExp.fault = 0872 AND camProcessedExp.zpt_obs != 0 ORDER BY RAND() limit 5000) as sub order by time;";873 378 $sql = " SELECT * FROM (SELECT 874 379 SUBTIME(rawExp.dateobs, '10:00:00') AS time, … … 901 406 cme.zpt_obs, 902 407 cme.zpt_stdev, 408 cme.path_base AS image_path, 903 409 rawExp.airmass, 904 410 rawExp.exp_time, … … 907 413 camRun.label, 908 414 camRun.cam_id, 909 BIT_COUNT(astrom_chips) AS g_chips, 910 SUM(CASE WHEN rim.bg > 0 THEN 1 ELSE 0 END) AS n_raw, 911 SUM(CASE WHEN chi.bg IS NOT NULL THEN 1 ELSE 0 END) AS n_read, 912 SUM(CASE WHEN chi.quality > 0 THEN 1 ELSE 0 END) AS n_poor 913 914 FROM camProcessedExp cme 915 JOIN camRun USING (cam_id) 916 JOIN chipRun USING (chip_id) 917 JOIN chipProcessedImfile chi USING (chip_id) 918 JOIN rawExp ON (rawExp.exp_id = chipRun.exp_id) 919 JOIN rawImfile rim ON (rim.exp_id = rawExp.exp_id) 920 921 WHERE 922 $dateConstraint 923 AND rawExp.exp_type = 'OBJECT' 924 AND camRun.state = 'full' 925 AND cme.fault = 0 926 AND cme.zpt_obs != 0 927 AND rim.class_id = chi.class_id 928 929 GROUP BY 415 BIT_COUNT(astrom_chips) AS good_astro, 416 SUM(chi.bg IS NOT NULL) AS good_chip, 417 SUM(chi.bg IS NULL) AS null_bg, 418 SUM(chi.n_stars > 5) AS good_phot, 419 SUM(chi.quality > 0) AS poor_chip 420 421 FROM camProcessedExp cme 422 JOIN camRun USING (cam_id) 423 JOIN chipRun USING (chip_id) 424 JOIN chipProcessedImfile chi USING (chip_id) 425 JOIN rawExp ON (rawExp.exp_id = chipRun.exp_id) 426 427 WHERE 428 $dateConstraint 429 AND rawExp.exp_type = 'OBJECT' 430 AND camRun.state = 'full' 431 AND cme.fault = 0 432 AND cme.zpt_obs != 0 433 434 GROUP BY 435 rawExp.exp_name, 436 camRun.label, 437 cam_id, 438 rawExp.dateobs, 439 rawExp.ra, 440 rawExp.decl, 441 rawExp.alt, 442 rawExp.moon_angle, 443 astrom_chips, 444 cme.bg, 445 cme.n_stars 446 447 ORDER BY RAND() limit 5000) as sub order by time; 448 "; 449 450 $stmt = $db->query($sql); 451 $DQarray = $stmt->fetchAll(PDO::FETCH_ASSOC); 452 453 // Ensure $DQarray is not empty 454 if (empty($DQarray)) { 455 echo "<center><b> No data for MJD: $mjdDay </b></center>"; 456 return; // Stop execution if no data to encode 457 } 458 459 // Convert data array to JSON for easier handling in JavaScript 460 $dataJson = json_encode($DQarray); 461 462 if ($dataJson === false) { 463 echo "<b>Error encoding JSON:</b> " . json_last_error_msg(); // Display any JSON encoding errors 464 return; // Stop execution if JSON encoding fails 465 } 466 467 echo "<script>console.log(" . json_encode($dataJson) . ");</script>"; // Log JSON output to console for debugging 468 469 470 echo <<<HTML 471 <script type="text/javascript"> 472 // Use the encoded JSON directly in JavaScript 473 const dataArray = JSON.parse('{$dataJson}'); // Directly parse the PHP JSON string 474 475 const nRows = dataArray.length; 476 477 // draw pointing vs mjd 478 function drawMJDChart() { 479 var data = new google.visualization.DataTable(); 480 data.addColumn('number', 'MJD'); 481 data.addColumn('number', 'RA_offset (AST_R0)'); 482 data.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}}); 483 data.addColumn({type: 'number', role: 'interval'}); 484 data.addColumn({type: 'number', role: 'interval'}); 485 data.addColumn('number', 'Dec_offset (AST_D0)'); 486 data.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}}); 487 data.addColumn({type: 'number', role: 'interval'}); 488 data.addColumn({type: 'number', role: 'interval'}); 489 data.addColumn('number', '20 TP unit ~5.1"'); 490 data.addColumn('number', '-20 TP unit ~5.1"'); 491 492 const mjdoff = $mjdDay; 493 const rows = dataArray.map(row => { 494 const mjd = parseFloat(row.MJD) - mjdoff; // MJD shift to first one 495 const ra_off = parseFloat(row.AST_R0); // RA_offset (AST_R0) 496 const dec_off = parseFloat(row.AST_D0); // DEC_offset (AST_D0) 497 const ra_sct = parseFloat(row.AST_RS); // RA_scatter (AST_RS) 498 const dec_sct = parseFloat(row.AST_DS); // DEC_scatter (AST_DS) 499 const tooltip = buildTooltip(row); // Tooltip 500 501 return [ 502 mjd, ra_off, tooltip, ra_off-ra_sct, ra_off+ra_sct, dec_off, tooltip, dec_off-dec_sct, dec_off+dec_sct, 503 20, // Dummy value for 20 TP unit 504 -20 // Dummy value for -20 TP unit 505 ]; 506 }); 507 508 data.addRows(rows); 509 510 // After building rows: 511 const allVerticalVals = rows.flatMap(r => [ 512 r[3], // ra_off - ra_sct 513 r[4], // ra_off + ra_sct 514 r[7], // dec_off - dec_sct 515 r[8] // dec_off + dec_sct 516 ]).filter(v => !isNaN(v)); // â 517 remove NaN values 518 519 // If array is empty after filtering, use safe defaults 520 const minY = allVerticalVals.length ? Math.min(...allVerticalVals) : 0; 521 const maxY = allVerticalVals.length ? Math.max(...allVerticalVals) : 0; 522 523 // Clamp values: use ±100 if beyond 100 524 const yMin = Math.abs(minY) > 150 ? -150 : minY; 525 const yMax = Math.abs(maxY) > 150 ? 150 : maxY; 526 527 console.log("minY:", minY, yMin, "maxY:", maxY, yMax); 528 529 const defaultSeries = { pointSize: 5, lineWidth: 0 }; 530 531 const titleText = `Pointing Offset vs. MJD ({$proj}) â \${nRows} rows\${dataArray.length >= 10000 ? " (sampled)" : ""}`; 532 const options = { 533 //title: 'Pointing Offset vs. MJD ({$proj})', 534 title: titleText, 535 titleTextStyle: {color: 'black', fontSize: 15}, 536 width: '100%', 537 height: 480, 538 legend: { position: 'top', alignment: 'center' }, 539 series: { 540 0: { color: '#0000ff', pointSize: 3, lineWidth: 0 }, // RA_offset series 541 1: { color: '#33a532', pointSize: 3, lineWidth: 0 }, // Dec_offset series 542 2: { color: 'red', lineWidth: 2, lineDashStyle: [8, 4], pointSize: 0 }, // Line at y = 20 543 3: { color: 'red', lineWidth: 2, lineDashStyle: [8, 4], pointSize: 0 } // Line at y = -20 544 }, 545 intervals: { lineWidth: .5, style: 'sticks' }, 546 interval: { 547 0: {color: 'blue'}, // interval columns attached to first series 548 1: {color: 'green'} // interval columns attached to second series 549 }, 550 hAxis: { 551 title: 'MJD - ' + mjdoff + ' (today)', 552 gridlines: { count: -1 } // auto gridlines 553 }, 554 vAxis: { 555 title: 'Pointing Offset (TP units)', 556 viewWindow: { 557 min: yMin, 558 max: yMax 559 } 560 }, 561 tooltip: { isHtml: true }, // Render tooltips as HTML 562 explorer: { actions: ['dragToZoom', 'rightClickToReset'], axis: 'horizontal', keepInBounds: true, maxZoomIn: .01}, // Zoom 563 chartArea: {left: '7%', top: 60, right: '4%', bottom: 50}, // Adjust left and right 564 fontSize: 15, 565 }; 566 567 const chart = new google.visualization.ScatterChart(document.getElementById('dq_div_mjd')); 568 chart.draw(data, options); 569 } 570 571 // position angle 572 function drawPOSChart() { 573 var data = new google.visualization.DataTable(); 574 data.addColumn('number', 'Posang'); 575 data.addColumn('number', 'RA_offset (AST_R0)'); 576 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}}); 577 data.addColumn('number', 'Dec_offset (AST_D0)'); 578 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}}); 579 580 const rows = dataArray.map(row => { 581 const posang = parseFloat(row.posang); // Position Angle 582 const ra_off = parseFloat(row.AST_R0); // RA_offset (AST_R0) 583 const dec_off = parseFloat(row.AST_D0); // DEC_offset (AST_D0) 584 const tooltip = buildTooltip(row); // Tooltip 585 return [ 586 posang, ra_off, tooltip, dec_off, tooltip 587 ]; 588 }); 589 590 data.addRows(rows); 591 592 const titleText = `Pointing Offset vs. Position Angle ({$proj}) â \${nRows} rows\${dataArray.length >= 10000 ? " (sampled)" : ""}`; 593 const options = { 594 title: titleText, 595 titleTextStyle: {color: 'black', fontSize: 15}, 596 width: '100%', 597 height: 480, 598 legend: { position: 'top', alignment: 'center' }, 599 // pointSize: 5, // Point size for scatter plot 600 // lineWidth: 2, 601 series: { 602 0: { color: '#0000ff', pointSize: 3, lineWidth: 0 }, // RA_offset series 603 1: { color: '#33a532', pointSize: 3, lineWidth: 0 }, // Dec_offset series 604 }, 605 intervals: { color: 'red', lineWidth: 2, style: 'sticks' }, 606 hAxis: { 607 title: 'Position Angle (deg)', 608 gridlines: {count: -1} 609 }, 610 vAxis: { 611 title: 'Pointing Offset (TP units)', 612 }, 613 tooltip: { isHtml: true }, // Render tooltips as HTML 614 explorer: { actions: ['dragToZoom', 'rightClickToReset'], axis: 'horizontal', keepInBounds: true, maxZoomIn: .01}, // Zoom 615 chartArea: {left: '7%', top: 60, right: '4%', bottom: 50}, // Adjust left and right 616 fontSize: 15, 617 }; 618 619 const chart = new google.visualization.ScatterChart(document.getElementById('dq_div_pos')); 620 chart.draw(data, options); 621 } 622 623 function drawALTChart() { 624 var data = new google.visualization.DataTable(); 625 data.addColumn('number', 'Altitute'); 626 data.addColumn('number', 'RA_offset (AST_R0)'); 627 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}}); 628 data.addColumn('number', 'Dec_offset (AST_D0)'); 629 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}}); 630 631 const rows = dataArray.map(row => { 632 const alt = parseFloat(row.alt); // Altitude 633 const ra_off = parseFloat(row.AST_R0); // RA_offset (AST_R0) 634 const dec_off = parseFloat(row.AST_D0); // DEC_offset (AST_D0) 635 const tooltip = buildTooltip(row); // Tooltip 636 return [ 637 alt, ra_off, tooltip, dec_off, tooltip 638 ]; 639 }); 640 641 data.addRows(rows); 642 643 const titleText = `Pointing Offset vs. Altitude ({$proj}) â \${nRows} rows\${dataArray.length >= 10000 ? " (sampled)" : ""}`; 644 const options = { 645 title: titleText, 646 titleTextStyle: {color: 'black', fontSize: 15}, 647 width: '100%', 648 height: 480, 649 legend: { position: 'top', alignment: 'center' }, 650 series: { 651 0: { color: '#0000ff', pointSize: 3, lineWidth: 0 }, // RA_offset series 652 1: { color: '#33a532', pointSize: 3, lineWidth: 0 }, // Dec_offset series 653 }, 654 intervals: { color: 'red', lineWidth: 2, style: 'sticks' }, 655 hAxis: { 656 title: 'Altitude (deg)', 657 gridlines: {count: -1} 658 }, 659 vAxis: { 660 title: 'Pointing Offset (TP units)', 661 }, 662 tooltip: { isHtml: true }, // Render tooltips as HTML 663 explorer: { actions: ['dragToZoom', 'rightClickToReset'], axis: 'horizontal', keepInBounds: true, maxZoomIn: .01}, // Zoom 664 //chartArea: {left: 80, top: 50, right: 20, bottom: 50}, 665 chartArea: {left: '7%', top: 60, right: '4%', bottom: 50}, // Adjust left and right 666 fontSize: 15, 667 }; 668 669 const chart = new google.visualization.ScatterChart(document.getElementById('dq_div_alt')); 670 chart.draw(data, options); 671 } 672 673 function drawAZChart() { 674 var data = new google.visualization.DataTable(); 675 data.addColumn('number', 'Azumith'); 676 data.addColumn('number', 'RA_offset (AST_R0)'); 677 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}}); 678 data.addColumn('number', 'Dec_offset (AST_D0)'); 679 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}}); 680 681 const rows = dataArray.map(row => { 682 const az = parseFloat(row.az); // Azumith 683 const ra_off = parseFloat(row.AST_R0); // RA_offset (AST_R0) 684 const dec_off = parseFloat(row.AST_D0); // DEC_offset (AST_D0) 685 const tooltip = buildTooltip(row); // Tooltip 686 return [ 687 az, ra_off, tooltip, dec_off, tooltip 688 ]; 689 }); 690 691 data.addRows(rows); 692 693 const titleText = `Pointing Offset vs. Azumith ({$proj}) â \${nRows} rows\${dataArray.length >= 10000 ? " (sampled)" : ""}`; 694 const options = { 695 title: titleText, 696 titleTextStyle: {color: 'black', fontSize: 15}, 697 width: '100%', 698 height: 480, 699 legend: { position: 'top', alignment: 'center' }, 700 series: { 701 0: { color: '#0000ff', pointSize: 3, lineWidth: 0 }, // RA_offset series 702 1: { color: '#33a532', pointSize: 3, lineWidth: 0 }, // Dec_offset series 703 }, 704 intervals: { color: 'red', lineWidth: 2, style: 'sticks' }, 705 hAxis: { 706 title: 'Azumith (deg)', 707 gridlines: {count: -1} 708 }, 709 vAxis: { 710 title: 'Pointing Offset (TP units)', 711 }, 712 tooltip: { isHtml: true }, // Render tooltips as HTML 713 explorer: { actions: ['dragToZoom', 'rightClickToReset'], axis: 'horizontal', keepInBounds: true, maxZoomIn: .01}, // Zoom 714 //chartArea: {left: 80, top: 50, right: 20, bottom: 50}, 715 chartArea: {left: '7%', top: 60, right: '4%', bottom: 50}, // Adjust left and right 716 fontSize: 15, 717 }; 718 719 const chart = new google.visualization.ScatterChart(document.getElementById('dq_div_az')); 720 chart.draw(data, options); 721 } 722 723 724 function drawScatChart() { 725 var data = new google.visualization.DataTable(); 726 data.addColumn('number', 'MJD'); 727 data.addColumn('number', 'RA_scat (AST_RS)'); 728 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}}); 729 data.addColumn('number', 'Dec_scat (AST_DS)'); 730 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}}); 731 732 const mjdoff = $mjdDay; 733 const rows = dataArray.map(row => { 734 const mjd = parseFloat(row.MJD) - mjdoff; // MJD shift to first one 735 const ra_scat = parseFloat(row.AST_RS); // RA_scat (AST_RS) 736 const dec_scat = parseFloat(row.AST_DS); // DEC_scat (AST_DS) 737 const tooltip = buildTooltip(row); // Tooltip 738 return [ 739 mjd, ra_scat, tooltip, dec_scat, tooltip 740 ]; 741 }); 742 743 data.addRows(rows); 744 745 const titleText = `Pointing Offset vs. MJD ({$proj}) â \${nRows} rows\${dataArray.length >= 10000 ? " (sampled)" : ""}`; 746 const options = { 747 title: titleText, 748 titleTextStyle: {color: 'black', fontSize: 15}, 749 width: '100%', 750 height: 280, 751 legend: { position: 'top', alignment: 'center' }, 752 series: { 753 0: { color: '#0000ff', pointSize: 3, lineWidth: 0 }, // RA_offset series 754 1: { color: '#33a532', pointSize: 3, lineWidth: 0 }, // Dec_offset series 755 }, 756 intervals: { color: 'red', lineWidth: 2, style: 'sticks' }, 757 hAxis: { 758 title: 'MJD - ' + mjdoff + ' (today)', 759 gridlines: {count: -1} 760 }, 761 vAxis: { 762 title: 'Scatter (TP units)', 763 viewWindow: { 764 min: 0, 765 // max: 20 766 } 767 }, 768 tooltip: { isHtml: true }, // Render tooltips as HTML 769 explorer: { actions: ['dragToZoom', 'rightClickToReset'], axis: 'horizontal', keepInBounds: true, maxZoomIn: .01}, // Zoom 770 //chartArea: {left: 80, top: 50, right: 20, bottom: 50}, 771 chartArea: {left: '7%', top: 60, right: '4%', bottom: 50}, // Adjust left and right 772 fontSize: 15, 773 }; 774 775 const chart = new google.visualization.ScatterChart(document.getElementById('dq_div_scat')); 776 chart.draw(data, options); 777 } 778 779 google.charts.setOnLoadCallback(drawMJDChart); 780 google.charts.setOnLoadCallback(drawPOSChart); 781 google.charts.setOnLoadCallback(drawALTChart); 782 google.charts.setOnLoadCallback(drawAZChart); 783 google.charts.setOnLoadCallback(drawScatChart); 784 </script> 785 786 <div class="chartWithOverlay" style="position: relative; width: 1240px; height:500px;"> 787 <div id="dq_div_mjd" style="width:1240px;"></div> 788 </div> 789 790 <div class="chartWithOverlay" style="position: relative; width: 1240px; height:300px;"> 791 <div id="dq_div_scat" style="width:1240px;"></div> 792 </div> 793 794 <div class="chartWithOverlay" style="position: relative; width: 1240px; height:500px;"> 795 <div id="dq_div_pos" style="width:1240px;"></div> 796 </div> 797 798 <div class="chartWithOverlay" style="position: relative; width: 1240px; height:500px;"> 799 <div id="dq_div_alt" style="width:1240px;"></div> 800 </div> 801 802 <div class="chartWithOverlay" style="position: relative; width: 1240px; height:500px;"> 803 <div id="dq_div_az" style="width:1240px;"></div> 804 </div> 805 HTML; 806 807 // End timer 808 $total_time = round(microtime(true) - $start, 3); 809 echo "<center>Loading plot in $total_time seconds<br></center>"; 810 811 } 812 813 ########################################################################### 814 # 815 # Get data quality 816 # 817 ########################################################################### 818 function getDataQuality($db, $range = 'week', $proj) { 819 // Start timer 820 $start = microtime(true); 821 // mjd today 822 $mjdDay = getMJD(); 823 // testing day 824 //$mjdDay = 61104; 825 $mjdDay_yearback = $mjdDay - 366; 826 $mjdDay_monthback = $mjdDay - 30; 827 $min_exp_id = 0; 828 829 830 // Determine the reference exp_name based on the selected range 831 switch ($range) { 832 case 'year': 833 $expname = "o" . $mjdDay_yearback . "%"; 834 break; 835 case 'month': 836 $expname = "o" . $mjdDay_monthback . "%"; 837 break; 838 case 'week': 839 $expname = "o" . ($mjdDay - 7) . "%"; 840 break; 841 case 'yesterday': 842 $expname = "o" . ($mjdDay - 1) . "%"; 843 break; 844 case 'today': 845 $expname = "o" . $mjdDay . "%"; 846 break; 847 default: 848 $expname = "o" . ($mjdDay - 7) . "%"; // Default: week 849 break; 850 } 851 852 // --- PDO query for min_exp_id --- 853 $stmt = $db->prepare("SELECT MIN(exp_id) AS min_exp_id FROM rawExp WHERE exp_name LIKE :expname"); 854 $stmt->execute([':expname' => $expname]); 855 $row = $stmt->fetch(PDO::FETCH_ASSOC); 856 if (!empty($row['min_exp_id'])) { 857 $min_exp_id = $row['min_exp_id']; 858 echo "<center><b>min_exp_id $min_exp_id in $range $expname - $mjdDay (today)</b></center>"; 859 } else { 860 echo "<center><b>No min_exp_id $min_exp_id in $range $expname - $mjdDay (today)</b></center>"; 861 } 862 863 // Determine the date constraint based on the range 864 switch ($range) { 865 case 'year': 866 $dateConstraint = "rawExp.dateobs >= NOW() - INTERVAL 365 DAY AND rawExp.exp_id >= $min_exp_id"; 867 break; 868 case 'month': 869 $dateConstraint = "rawExp.dateobs >= NOW() - INTERVAL 30 DAY AND rawExp.exp_id >= $min_exp_id"; 870 break; 871 case 'week': 872 $expnames = array(); 873 for ($i = 0; $i < 7; $i++) { 874 $expnames[] = "rawExp.exp_name LIKE 'o" . ($mjdDay - $i) . "%'"; 875 } 876 $dateConstraint = "(" . implode(" OR ", $expnames) . ") AND rawExp.exp_id >= $min_exp_id"; 877 $qday = $mjdDay - 6; // or something meaningful for week 878 break; 879 case 'yesterday': 880 $dateConstraint = "rawExp.exp_name LIKE 'o" . ($mjdDay - 1) . "%' AND rawExp.exp_id >= $min_exp_id"; 881 $qday = $mjdDay - 1; 882 break; 883 case 'today': 884 $dateConstraint = "rawExp.exp_name LIKE 'o$mjdDay%' AND rawExp.exp_id >= $min_exp_id"; 885 $qday = $mjdDay; 886 break; 887 case 'all': 888 $dateConstraint = "rawExp.exp_id >= 0"; 889 break; 890 default: // Default to last night 891 $dateConstraint = "rawExp.exp_name LIKE 'o" . ($mjdDay - 1) . "%' AND rawExp.exp_id >= $min_exp_id"; 892 $qday = $mjdDay - 1; 893 break; 894 } 895 896 // Updated SQL query 897 $sql = " SELECT * FROM (SELECT 898 SUBTIME(rawExp.dateobs, '10:00:00') AS time, 899 cme.AST_R0, 900 cme.AST_D0, 901 cme.AST_RS, 902 cme.AST_DS, 903 cme.AST_T0, 904 rawExp.posang, 905 ROUND( 906 (367*YEAR(rawExp.dateobs) 907 - FLOOR((7*(YEAR(rawExp.dateobs)+FLOOR((MONTH(rawExp.dateobs)+9)/12)))/4) 908 + FLOOR(275*MONTH(rawExp.dateobs)/9) 909 + DAY(rawExp.dateobs) 910 + 1721013.5 911 + (HOUR(rawExp.dateobs)/24.0) 912 + (MINUTE(rawExp.dateobs)/1440.0) 913 + (SECOND(rawExp.dateobs)/86400.0) 914 - 2400000.5),5 915 ) AS MJD, 916 rawExp.filter, 917 rawExp.comment, 918 ROUND(rawExp.ra*180/PI(),5) AS RA, 919 ROUND(rawExp.decl*180/PI(),5) AS DECL, 930 920 rawExp.exp_name, 921 rawExp.alt, 922 rawExp.az, 923 cme.fwhm_major, 924 cme.fwhm_minor, 925 cme.zpt_obs, 926 cme.zpt_stdev, 927 cme.path_base AS image_path, 928 rawExp.airmass, 929 rawExp.exp_time, 930 rawExp.exp_id, 931 rawExp.moon_angle, 931 932 camRun.label, 932 cam_id, 933 rawExp.dateobs, 934 rawExp.ra, 935 rawExp.decl, 936 rawExp.alt, 937 rawExp.moon_angle, 938 astrom_chips, 939 cme.bg, 940 cme.n_stars 941 942 ORDER BY RAND() limit 5000) as sub order by time; 943 "; 933 camRun.cam_id, 934 BIT_COUNT(astrom_chips) AS good_astro, 935 SUM(chi.bg IS NOT NULL) AS good_chip, 936 SUM(chi.bg IS NULL) AS null_bg, 937 SUM(chi.n_stars > 5) AS good_phot, 938 SUM(chi.quality > 0) AS poor_chip 939 940 FROM camProcessedExp cme 941 JOIN camRun USING (cam_id) 942 JOIN chipRun USING (chip_id) 943 JOIN chipProcessedImfile chi USING (chip_id) 944 JOIN rawExp ON (rawExp.exp_id = chipRun.exp_id) 945 946 WHERE 947 $dateConstraint 948 AND rawExp.exp_type = 'OBJECT' 949 AND camRun.state = 'full' 950 AND cme.fault = 0 951 952 GROUP BY 953 rawExp.exp_name, 954 camRun.label, 955 cam_id, 956 rawExp.dateobs, 957 rawExp.ra, 958 rawExp.decl, 959 rawExp.alt, 960 rawExp.moon_angle, 961 astrom_chips, 962 cme.bg, 963 cme.n_stars 964 965 ORDER BY RAND() limit 5000) as sub order by time; 966 "; 944 967 945 968 //echo "<center>$sql</center><br>"; 946 //echo "<center>$sql1</center>";947 969 $stmt = $db->query($sql); 948 970 $DQarray = $stmt->fetchAll(PDO::FETCH_ASSOC); … … 985 1007 var data = new google.visualization.DataTable(); 986 1008 data.addColumn('number', 'MJD'); 987 data.addColumn('number', ' Number of raw Chips');1009 data.addColumn('number', 'good phot (nstar>5)'); 988 1010 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}}); 989 // data.addColumn('number', 'Number of Good Chips'); 990 // data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}}); 991 992 const mjdValues = dataArray.map(r => parseFloat(r.MJD)); 993 let mjdMin0 = Math.min(...mjdValues); 994 const mjdMin = Math.floor(mjdMin0 * 10) / 10; // 1 decimal place or floor/ceil depending on your needs 995 let mjdMax0 = Math.max(...mjdValues); 996 const mjdMax = Math.ceil(mjdMax0 * 10) / 10; // 1 decimal place or floor/ceil depending on your needs 997 // Extract the first MJD value from dataArray 998 const firstMJD = dataArray.length > 0 ? Math.floor(parseFloat(dataArray[0].MJD)) : "N/A"; 999 const mjdoff = mjdMin; 1000 // output at console 1001 // console.log("First MJD Value:", firstMJD); 1002 1011 data.addColumn('number', 'good astro'); 1012 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}}); 1013 data.addColumn('number', 'null bg'); 1014 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}}); 1015 data.addColumn('number', 'poor (q>0)'); 1016 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}}); 1017 1018 const mjdoff = $mjdDay; 1003 1019 // build data rows 1004 const mjdVals = [];1005 1020 const rows = dataArray.map(row => { 1006 1021 const mjd = parseFloat(row.MJD) - mjdoff; 1007 mjdVals.push(mjd); // collect MJD offset values 1008 1009 const n_raw = parseFloat(row.n_raw)+1; 1010 const n_chips = parseFloat(row.g_chips); 1011 const f_good = n_chips / n_raw; 1022 const null_bg = parseFloat(row.null_bg); 1023 const good_phot = parseFloat(row.good_phot); 1024 const good_astro = parseFloat(row.good_astro); 1025 const poor_chip = parseFloat(row.poor_chip); 1012 1026 const tooltip = buildTooltip(row); 1013 1027 1014 1028 return[ 1015 mjd, f_good, tooltip,1029 mjd, good_phot, tooltip, good_astro, tooltip, null_bg, tooltip, poor_chip, tooltip, 1016 1030 ]; 1017 1031 }); … … 1019 1033 data.addRows(rows); 1020 1034 1021 // Now compute min and max 1022 const mjdMin1 = Math.min(...mjdVals); 1023 const mjdMax1 = Math.max(...mjdVals); 1024 1025 const titleText = `N Chips vs. MJD ({$proj}) â \${nRows} rows\${dataArray.length >= 5000 ? " (sampled)" : ""}`; 1035 const titleText = `Chips ratio vs. MJD ({$proj}) â \${nRows} rows\${dataArray.length >= 5000 ? " (sampled)" : ""}`; 1036 1037 const options = { 1038 title: titleText, 1039 titleTextStyle: {color: 'black', fontSize: 14, bold: true}, 1040 width: '100%', 1041 height: Math.min(window.innerHeight * 0.6, 430), // This gives a nice result on smaller screens. 1042 legend: { position: 'top', alignment: 'center' }, 1043 series: { 1044 //0: { color: '#ffe000', pointShape: 'star', pointSize: 10, lineWidth: 0}, 1045 0: { color: '#0000ff', pointShape: 'square', pointSize: 8, lineWidth: 0}, 1046 1: { color: '#33a532', pointShape: 'triangle',pointSize: 5, lineWidth: 0}, 1047 2: { color: '#ff0000', pointShape: 'star', pointSize: 8, lineWidth: 0}, 1048 3: { color: '#808080', pointShape: 'triangle',pointSize: 5, lineWidth: 0}, 1049 }, 1050 intervals: { color: 'red', lineWidth: 2, style: 'sticks' }, 1051 hAxis: { 1052 title: 'MJD - ' + mjdoff + ' (today)', 1053 gridlines: { count: -1 } // auto gridlines 1054 }, 1055 vAxis: { 1056 title: 'number of chips', 1057 }, 1058 tooltip: { isHtml: true }, // Render tooltips as HTML 1059 explorer: { actions: ['dragToZoom', 'rightClickToReset'], axis: 'horizontal', keepInBounds: true, maxZoomIn: .01}, // Zoom 1060 chartArea: {left: '9%', top: '10%', right: '3%', bottom: 50}, // Adjust left and right 1061 fontSize: 14, 1062 }; 1063 1064 const chart = new google.visualization.ScatterChart(document.getElementById('dq_div_chips')); 1065 chart.draw(data, options); 1066 } 1067 1068 // draw FWHM vs MJD 1069 function drawFWHMChart() { 1070 1071 // data header 1072 var data = new google.visualization.DataTable(); 1073 data.addColumn('number', 'MJD'); 1074 data.addColumn('number', 'FWHM_maj'); 1075 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}}); 1076 data.addColumn('number', 'FWHM_min'); 1077 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}}); 1078 data.addColumn('number', '1"'); 1079 data.addColumn('number', '3"'); 1080 1081 // build data rows 1082 const mjdoff = $mjdDay; 1083 const rows = dataArray.map(row => { 1084 const mjd = parseFloat(row.MJD) - mjdoff; 1085 const fwhm_maj = parseFloat(row.fwhm_major); 1086 const fwhm_min = parseFloat(row.fwhm_minor); 1087 const tooltip = buildTooltip(row); 1088 return[ 1089 mjd, fwhm_maj, tooltip, fwhm_min, tooltip, 4, 12, 1090 ]; 1091 }); 1092 1093 data.addRows(rows); 1094 1095 const titleText = `FWHM vs. MJD ({$proj}) â \${nRows} rows\${dataArray.length >= 5000 ? " (sampled)" : ""}`; 1026 1096 1027 1097 const options = { … … 1039 1109 intervals: { color: 'red', lineWidth: 2, style: 'sticks' }, 1040 1110 hAxis: { 1041 title: 'MJD - ' + mjdoff + ' (day)', 1042 viewWindow: { 1043 min: 0., // small padding 1044 max: mjdMax1 + 0.005 1045 }, 1046 gridlines: { count: -1 } // auto gridlines 1047 }, 1048 vAxis: { 1049 title: 'Good chips (number)', 1050 // viewWindow: { 1051 // max: 65, 1052 // min: 0 1053 // }, 1054 }, 1055 tooltip: { isHtml: true }, // Render tooltips as HTML 1056 chartArea: {left: '9%', top: '10%', right: '3%', bottom: 50}, // Adjust left and right 1057 fontSize: 14, 1058 }; 1059 1060 const chart = new google.visualization.ScatterChart(document.getElementById('dq_div_chips')); 1061 chart.draw(data, options); 1062 } 1063 1064 // draw FWHM vs MJD 1065 function drawFWHMChart() { 1066 1067 // data header 1068 var data = new google.visualization.DataTable(); 1069 data.addColumn('number', 'MJD'); 1070 data.addColumn('number', 'FWHM_maj'); 1071 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}}); 1072 data.addColumn('number', 'FWHM_min'); 1073 data.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}}); 1074 data.addColumn('number', '1"'); 1075 data.addColumn('number', '3"'); 1076 1077 const mjdValues = dataArray.map(r => parseFloat(r.MJD)); 1078 let mjdMin0 = Math.min(...mjdValues); 1079 const mjdMin = Math.floor(mjdMin0 * 10) / 10; // 1 decimal place or floor/ceil depending on your needs 1080 let mjdMax0 = Math.max(...mjdValues); 1081 const mjdMax = Math.ceil(mjdMax0 * 10) / 10; // 1 decimal place or floor/ceil depending on your needs 1082 // Extract the first MJD value from dataArray 1083 const firstMJD = dataArray.length > 0 ? Math.floor(parseFloat(dataArray[0].MJD)) : "N/A"; 1084 const mjdoff = mjdMin; 1085 // output at console 1086 // console.log("First MJD Value:", firstMJD); 1087 1088 // build data rows 1089 const mjdVals = []; 1090 const rows = dataArray.map(row => { 1091 const mjd = parseFloat(row.MJD) - mjdoff; 1092 mjdVals.push(mjd); // collect MJD offset values 1093 1094 const fwhm_maj = parseFloat(row.fwhm_major); 1095 const fwhm_min = parseFloat(row.fwhm_minor); 1096 const tooltip = buildTooltip(row); 1097 1098 return[ 1099 mjd, fwhm_maj, tooltip, fwhm_min, tooltip, 4, 12, 1100 ]; 1101 }); 1102 1103 data.addRows(rows); 1104 1105 // Now compute min and max 1106 const mjdMin1 = Math.min(...mjdVals); 1107 const mjdMax1 = Math.max(...mjdVals); 1108 1109 const titleText = `FWHM vs. MJD ({$proj}) â \${nRows} rows\${dataArray.length >= 5000 ? " (sampled)" : ""}`; 1110 1111 const options = { 1112 title: titleText, 1113 titleTextStyle: {color: 'black', fontSize: 14, bold: true}, 1114 width: '100%', 1115 height: Math.min(window.innerHeight * 0.6, 430), // This gives a nice result on smaller screens. 1116 legend: { position: 'top', alignment: 'center' }, 1117 series: { 1118 0: { color: '#0000ff', pointSize: 3, lineWidth: 0. }, 1119 1: { color: '#33a532', pointSize: 3, lineWidth: 0. }, 1120 2: { color: 'red', lineWidth: 2, pointSize: 0 }, 1121 3: { color: 'red', lineWidth: 2, lineDashStyle: [8, 4], pointSize: 0 } 1122 }, 1123 intervals: { color: 'red', lineWidth: 2, style: 'sticks' }, 1124 hAxis: { 1125 title: 'MJD - ' + mjdoff + ' (day)', 1126 viewWindow: { 1127 min: 0., // small padding 1128 max: mjdMax1 + 0.005 1129 }, 1130 gridlines: { count: -1 } // auto gridlines 1111 title: 'MJD - ' + mjdoff + ' (today)', 1112 gridlines: { count: -1 } // auto gridlines 1131 1113 }, 1132 1114 vAxis: { … … 1134 1116 }, 1135 1117 tooltip: { isHtml: true }, // Render tooltips as HTML 1118 explorer: { actions: ['dragToZoom', 'rightClickToReset'], axis: 'horizontal', keepInBounds: true, maxZoomIn: .01}, // Zoom 1136 1119 chartArea: {left: '9%', top: '10%', right: '3%', bottom: 50}, // Adjust left and right 1137 1120 fontSize: 14, … … 1168 1151 const filterCounts = Object.fromEntries(filters.map(f => [f.key, 0])); 1169 1152 1170 const mjdValues = dataArray.map(r => parseFloat(r.MJD));1171 const mjdMin0 = Math.min(...mjdValues);1172 const mjdMax0 = Math.max(...mjdValues);1173 const mjdMin = Math.floor(mjdMin0 * 10) / 10;1174 const mjdMax = Math.ceil(mjdMax0 * 10) / 10;1175 const mjdoff = mjdMin;1176 1177 const mjdVals = [];1178 1179 1153 // build rows 1154 const mjdoff = $mjdDay; 1180 1155 const rows = dataArray.map(row => { 1181 1156 const mjd = parseFloat(row.MJD) - mjdoff; 1182 mjdVals.push(mjd);1183 1184 1157 const filter = row.filter[0]; 1185 1158 const zpt_obs = parseFloat(row.zpt_obs); … … 1224 1197 data.addRows(rows); 1225 1198 1226 const mjdMin1 = Math.min(...mjdVals);1227 const mjdMax1 = Math.max(...mjdVals);1228 1199 const defaultSeries = { pointSize: 6, lineWidth: 0 }; 1229 1200 … … 1244 1215 intervals: { color: 'red', lineWidth: .0, style: 'sticks' }, 1245 1216 hAxis: { 1246 title: 'MJD - ' + mjdoff + ' (day)', 1247 viewWindow: { min: 0, max: mjdMax1 + 0.005 }, 1217 title: 'MJD - ' + mjdoff + ' (today)', 1248 1218 gridlines: { count: -1 } 1249 1219 }, … … 1253 1223 }, 1254 1224 tooltip: { isHtml: true }, 1225 explorer: { actions: ['dragToZoom', 'rightClickToReset'], axis: 'horizontal', keepInBounds: true, maxZoomIn: .01}, // Zoom 1255 1226 chartArea: { left: '9%', top: '10%', right: '3%', bottom: 50 }, 1256 1227 fontSize: 14, 1257 1228 }; 1258 // options.series[1] = { color: 'black', lineDashStyle: [2, 3], lineWidth: 2, pointSize: 0 };1259 // options.series[3] = { color: 'black', lineDashStyle: [2, 3], lineWidth: 2, pointSize: 0 };1260 // options.series[5] = { color: 'black', lineDashStyle: [2, 3], lineWidth: 2, pointSize: 0 };1261 // options.series[7] = { color: 'black', lineDashStyle: [2, 3], lineWidth: 2, pointSize: 0 };1262 // options.series[9] = { color: 'black', lineDashStyle: [2, 3], lineWidth: 2, pointSize: 0 };1263 // options.series[11] = { color: 'black', lineDashStyle: [2, 3], lineWidth: 2, pointSize: 0 };1264 1229 1265 1230 const chart = new google.visualization.ScatterChart(document.getElementById('dq_div_zpt')); … … 1269 1234 // draw zoomed zerpoint vs mjd 1270 1235 function drawZOOMZPTChart() { 1271 const mjdValues = dataArray.map(r => parseFloat(r.MJD));1272 let mjdMin0 = Math.min(...mjdValues);1273 const mjdMin = Math.floor(mjdMin0 * 10) / 10; // 1 decimal place or floor/ceil depending on your needs1274 let mjdMax0 = Math.max(...mjdValues);1275 const mjdMax = Math.ceil(mjdMax0 * 10) / 10; // 1 decimal place or floor/ceil depending on your needs1276 // Extract the first MJD value from dataArray1277 const firstMJD = dataArray.length > 0 ? Math.floor(parseFloat(dataArray[0].MJD)) : "N/A";1278 const mjdoff = mjdMin;1279 // output at console1280 console.log("First MJD Value:", firstMJD);1281 1282 1236 // Compute median zpt_obs per filter 1283 1237 function median(arr) { … … 1313 1267 // ref? 1314 1268 gzp0 = 24.563; rzp0 = 24.750; izp0 = 24.611; zzp0 = 24.240; yzp0 = 23.320; wzp0 = 26.000; 1315 //1316 //gzp0 = 24.563; rzp0 = 24.750; izp0 = 24.611; zzp0 = 24.240; yzp0 = 23.320; wzp0 = 26.000;1317 1269 break; 1318 1270 case 'gpc2': … … 1342 1294 }; 1343 1295 1344 const mjdVals = [];1345 1296 let allZps = []; 1297 const mjdoff = $mjdDay; 1346 1298 const rows = dataArray.map(row => { 1347 1299 const mjd = parseFloat(row.MJD) - mjdoff; … … 1366 1318 rowData.push( zp, tooltip, zp !== null ? zp - zpt_stdev : null, zp !== null ? zp + zpt_stdev : null); 1367 1319 }); 1368 1369 // collect MJD offset values1370 mjdVals.push(mjd);1371 1320 1372 1321 // collect valid zp values … … 1445 1394 1446 1395 // plot options 1447 const mjdMin1 = Math.min(...mjdVals);1448 const mjdMax1 = Math.max(...mjdVals);1449 1396 const defaultSeries = { pointSize: 6, lineWidth: 0 }; 1450 1397 … … 1456 1403 width: '100%', 1457 1404 height: Math.min(window.innerHeight * 0.6, 430), // This gives a nice result on smaller screens. 1458 //legend: { position: 'top', alignment: 'center', maxLines: 3, textStyle: {fontSize: 12} },1459 legend: { position: 'none', alignment: 'center', maxLines: 3 },1405 legend: { position: 'top', alignment: 'center', maxLines: 3, textStyle: {fontSize: 12} }, 1406 //legend: { position: 'none', alignment: 'center', maxLines: 3 }, 1460 1407 series: { 1461 1408 0: { ...defaultSeries, color: '#00f000', pointShape: 'circle', }, // 'g' filter … … 1468 1415 intervals: { color: 'red', lineWidth: .0, style: 'sticks' }, 1469 1416 hAxis: { 1470 title: 'MJD - ' + mjdoff + ' (day)', 1471 viewWindow: { 1472 min: 0, // small padding 1473 max: mjdMax1 + 0.005 1474 }, 1417 title: 'MJD - ' + mjdoff + ' (today)', 1475 1418 gridlines: { count: -1 }, 1476 1419 minorGridlines: { count: 1 } … … 1484 1427 }, 1485 1428 tooltip: { isHtml: true}, 1429 explorer: { actions: ['dragToZoom', 'rightClickToReset'], axis: 'horizontal', keepInBounds: true, maxZoomIn: .01}, // Zoom 1486 1430 chartArea: { left: '9%', top: '12%', right: '3%', bottom: 50 }, 1487 1431 fontSize: 14, … … 1501 1445 <div class="chartWithOverlay" style="position: relative; width: 100%; height:440px;"> 1502 1446 <div id="dq_div_chips" style="width:100%; border:1px solid #000;"></div> 1447 </div> 1448 1449 <div class="chartWithOverlay" style="position: relative; width: 100%; height:440px;"> 1450 <div id="dq_div_fwhm" style="width:100%; border:1px solid #000;"></div> 1503 1451 </div> 1504 1452 … … 1514 1462 </div> 1515 1463 1516 <div class="chartWithOverlay" style="position: relative; width: 100%; height:440px;">1517 <div id="dq_div_fwhm" style="width:100%; border:1px solid #000;"></div>1518 </div>1519 1520 1521 1464 HTML; 1522 1465 // End timer -
trunk/ippMonitor/raw/getimage.php
r41730 r43071 96 96 /* --site=$SITE */ 97 97 $output = array(); 98 exec ("ipp_filename.pl --site=$SITE --basename $basename --filerule $filerule --camera $camera --class_id $class_id 2> /tmp/errors", $output, $status); 98 //exec ("ipp_filename.pl --site=$SITE --basename $basename --filerule $filerule --camera $camera --class_id $class_id 2> /tmp/errors", $output, $status); 99 exec ("ipp_filename.pl --site=$SITE --basename $basename --filerule $filerule --camera $camera --class_id $class_id 2>&1", $output, $status); 100 101 if ($debug) { 102 echo "DEBUG 3.5<br>"; 103 for ($i = 0; $i < count($output); $i++) { 104 echo "output x $i: $output[$i]<br>"; 105 } 106 echo "status xx: $status<br>"; 107 108 } 99 109 100 110 # use these to check the environment -
trunk/ippMonitor/raw/pointing.php
r42972 r43071 29 29 echo "<tr>"; 30 30 echo " <td style=width:1240>"; 31 echo " <h1 align=\"middle\"> Data QualityReport</h1>";31 echo " <h1 align=\"middle\">Pointing Report</h1>"; 32 32 33 33 # … … 72 72 73 73 echo getPointing($projectdb, $range, $proj); 74 echo "<div class=\"chartWithOverlay\" style=\"position: relative; width: 100%; height:200px;\"></div>"; 75 74 76 menu_end(); 75 77 -
trunk/ippMonitor/raw/showimage.php
r42384 r43071 6 6 global $DBHOST; 7 7 8 $debug = 0;8 $debug = 1; 9 9 $sheet = 'ipp.css'; 10 10 … … 30 30 echo "basename: $basename<br>"; 31 31 echo "filerule: $filerule<br>"; 32 echo "filerule: $filerule<br>";33 32 echo "camera: $camera<br>"; 34 33 echo "class_id: $class_id<br>"; 35 exit ();34 // exit (); 36 35 } 37 36 -
trunk/ippMonitor/raw/site.php.in
r41730 r43071 6 6 $WWWHOST = "@HOST@"; 7 7 8 $PERLLIB = "@PERLLIB@ ";8 $PERLLIB = "@PERLLIB@:@PERLLIB@/perl5:@PERLLIB@/perl5/site_perl"; 9 9 $BINDIR = "@BINDIR@"; 10 10 $WWWBIN = "@WWWBIN@";
Note:
See TracChangeset
for help on using the changeset viewer.
