Browse Source

Merge branch 'master' of home/.../sources

compton 4 months ago
parent
commit
0630037340
10 changed files with 629 additions and 777 deletions
  1. 5 1
      .gitignore
  2. 99 44
      src/avg/elabelizer.py
  3. 30 4
      src/page/README.md
  4. 88 0
      src/page/commonfoos.php
  5. 29 33
      src/page/index.php
  6. 176 175
      src/page/init.php
  7. 73 51
      src/page/main.css
  8. 0 350
      src/page/plots.php
  9. 127 117
      src/page/summary.php
  10. 2 2
      src/scripts/compton_runs_script.sh

+ 5 - 1
.gitignore

@@ -1 +1,5 @@
-__pycache__
+__pycache__
+.htaccess
+*.ini
+plotly*
+fmin.min.js

+ 99 - 44
src/avg/elabelizer.py

@@ -9,18 +9,47 @@ If this script is not working properly, try to setup environment firstly with th
 This script is inspired by listoffdata.py script (/sl/cmd3/cc7-64/Cmd3Off/scripts/listoffdata.py)
 """
 
+from datetime import datetime
+from typing import Dict, List, Tuple, NamedTuple, Optional
+from pathlib import Path
+from urllib.request import urlopen
+
+import json
 import os 
-os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings_read_all')
 
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings_read_all')
+API_KEY = "9e3b3d9b7a57098bb1bc0e5c5053f2084251cd00"
 
 import django
 django.setup()
-
 from cmdweb.apps.cmd3off.energypoints.models import EnergyPoint, Param, ParamData
-from urllib.request import urlopen
 
+class RowEPoint(NamedTuple):
+    """Structure of the energy point metadata"""
+    elabel: str
+    first_run: int
+    last_run: int
+    nominal_energy: float
+    start_time: datetime
+    stop_time: datetime
+    season: str
+
+class AvgEPoint(NamedTuple):
+    """Structure of the averaged beam energy point"""
+    energy_mean: float
+    first_run: int
+    last_run: int
+    nominal_energy: float
+    season: str
 
-def retrieve_elabels(startrun, stoprun):
+class CombinedEPoint(NamedTuple):
+    """Structure of the combined energy point"""
+    season: str
+    elabel: Optional[str]
+    energy_mean: Optional[float]
+
+
+def retrieve_elabels(startrun: int, stoprun: int) -> List[RowEPoint]:
     """Retrieves elabels from database
     
     Parameters:
@@ -32,7 +61,7 @@ def retrieve_elabels(startrun, stoprun):
     
     Returns:
     --------
-    List[Tuple[str, int, int, float, datetime, datetime]
+    List[RowEPoint]
         list of elabels and information about them
         (elabel, firstrun, lastrun, nominal energy, starttime, stoptime, season)
     """
@@ -48,78 +77,106 @@ def retrieve_elabels(startrun, stoprun):
     for e in EnergyPoint.objects.filter(startrun__gte=startrun, endrun__lte=stoprun):
         while((e.startrun < seasons[season_idx][1]) or (e.endrun > seasons[season_idx][2])):
             season_idx+=1
-        info = (e.name, e.startrun, e.endrun, e.energy, e.starttime, e.endtime, seasons[season_idx][0])
+        info = RowEPoint(
+            elabel = e.name, 
+            first_run = e.startrun, 
+            last_run = e.endrun, 
+            nominal_energy = e.energy, 
+            start_time = e.starttime, 
+            stop_time = e.endtime, 
+            season = seasons[season_idx][0]
+        )
         if not(e.name.startswith("Season")):
             points.append(info)
     return points
     
-def get_available_compton_seasons():
-    tables_url = 'https://cmd.inp.nsk.su/~compton/gitlist/compton_tables/raw/dev/tables/'
+def get_available_compton_seasons() -> Dict[str, str]:
+    """Returns a dictionary containing all available 
+    average energy season tables
+    
+    Returns
+    -------
+    Dict[str, str]
+        keys are season names, values are pathes to the tables
+    """
+
+    tables_url = f'https://cmd.inp.nsk.su/~compton/gogs/api/v1/repos/compton/tables/contents/?token={API_KEY}'
     with urlopen(tables_url) as f:
-        data = f.read().decode('utf-8')
-        datarows = list(map(lambda x: x[:-4], filter(lambda x: x.endswith('.csv'), data.split('\n'))))
+        data_str = f.read().decode('utf-8')
+        data = json.loads(data_str)
+        datarows = {Path(row['name']).stem: row['download_url'] for row in
+        filter(lambda x: (x['type'] == 'file') and x['name'].endswith('.csv'), data)}
     return datarows
 
-def retrieve_comptons(seasons=None):
+def retrieve_comptons(season_names: Optional[List[str]] = None) -> List[AvgEPoint]:
     """Retrieves compton measurements from tables
     
     Parameters:
     -----------
-    seasons: Optional[List[str]]
+    season_names: Optional[List[str]]
         list of seasons for retrieving
         (default is None, it means retrieving all available seasons)
     
     Returns:
     --------
-    List[Tuple[str, float, int, int, float]]
+    List[AvgEPoint]
         list of compton means measurements
         (season, energy_point, first_run, last_run, mean_energy)
         first_run and last_run can be different from the corresponding energy points from elabels database
     """
     
     available_seasons = get_available_compton_seasons()
-    if seasons is not None:
-        for s in seasons:
-            if s not in available_seasons:
-                raise ValueError(f"Season {s} is not found. List of available seasons: {available_seasons}")
+    seasons = dict()
+    if season_names is not None:
+        for s in season_names:
+            try:
+                seasons[s] = available_seasons[s]
+            except KeyError:
+                raise ValueError(f"Season {s} is not found. List of available seasons: {available_seasons.keys()}")
     else:
         seasons = available_seasons
         
-    def parse_compton_row(row, season):
+    def parse_compton_row(row: str, season: str) -> AvgEPoint:
         items = row.split(',')
-        return (season, float(items[0]), int(items[1]), int(items[2]), float(items[3]))
-    
-    def retrieve_compton_one_season(season):
-        with urlopen(f'https://cmd.inp.nsk.su/~compton/gitlist/compton_tables/raw/dev/tables/{season}.csv') as f:
+        return AvgEPoint(
+            season=season, 
+            nominal_energy=float(items[0]), 
+            first_run=int(items[1]), 
+            last_run=int(items[2]), 
+            energy_mean=float(items[3])
+        )
+    
+    def retrieve_compton_one_season(season_name: str, season_table_url: str) -> List[AvgEPoint]:
+        with urlopen(season_table_url) as f:
             r = f.read().decode('utf-8').strip()
-            rows = list(map(lambda x: parse_compton_row(x, season), r.split('\n')[1:]))
+            rows = list(map(lambda x: parse_compton_row(x, s_name), r.split('\n')[1:]))
         return rows
                     
     datarows = []
-    for s in seasons:
-        seasonrows = retrieve_compton_one_season(s)
+    for s_name, s_table in seasons.items():
+        seasonrows = retrieve_compton_one_season(s_name, s_table)
         datarows.extend(seasonrows)
     
     return datarows
         
-def combine_compton_elabel(epoints, comptonpoints):
+def combine_compton_elabel(epoints: List[RowEPoint], comptonpoints: List[AvgEPoint]) -> List[CombinedEPoint]:
     """Combines compton energy points and elabels from database
     
     Parameters:
     -----------
-    epoints : List[Tuple[...]]
+    epoints : List[RowEPoint]
         list of energy points
-    comptonpoints : List[Tuple[...]]
-        list of compton points
+    comptonpoints : List[AvgEPoint]
+        list of compton averaged points
     
     Returns:
     --------
-    combpoints : List[Tuple[...]]
+    combpoints : List[CombinedEPoint]
         list of combined points (outer join)
     """
     
-    epoints_sorted = sorted(epoints, key=lambda x: x[1])
-    cpoints_sorted = sorted(comptonpoints, key=lambda x: x[2])
+    epoints_sorted = sorted(epoints, key=lambda x: x.first_run)
+    cpoints_sorted = sorted(comptonpoints, key=lambda x: x.first_run)
     
     combined_data = []
     
@@ -128,42 +185,40 @@ def combine_compton_elabel(epoints, comptonpoints):
         erow = epoints_sorted[eidx]
         crow = cpoints_sorted[cidx]
         
-        cstart, cstop, cenergy, cseason = crow[2], crow[3], crow[4], crow[0]
-        estart, estop, elabel, eseason = erow[1], erow[2], erow[0], erow[6]
+        cstart, cstop, cenergy, cseason = crow.first_run, crow.last_run, crow.energy_mean, crow.season
+        estart, estop, elabel, eseason = erow.first_run, erow.last_run, erow.elabel, erow.season
         
         if (cstart >= estart) and (cstop <= estop):
-            combrow = (eseason, elabel, cenergy)
+            combrow = CombinedEPoint(eseason, elabel, cenergy)
             eidx += 1
             cidx += 1
             #print(combrow)
         elif (cstart > estop):
-            combrow = (eseason, elabel, None)
+            combrow = CombinedEPoint(eseason, elabel, None)
             eidx += 1
         elif (estart > cstop):
-            combrow = (cseason, None, cenergy)
+            combrow = CombinedEPoint(cseason, None, cenergy)
             cidx += 1
         else:
             raise Exception("Something wrong")
         
-        #print(combrow)
+        # print(combrow)
         combined_data.append(combrow)
     
     for i in range(eidx, len(epoints_sorted)):
         erow = epoints_sorted[i]
-        elabel = erow[0]
-        combrow = (None, elabel, None)
+        combrow = CombinedEPoint(erow.season, erow.elabel, None)
         combined_data.append(combrow)
         
     for i in range(cidx, len(cpoints_sorted)):
         crow = cpoints_sorted[i]
-        cstart, cstop, cenergy, cseason = crow[2], crow[3], crow[4], crow[0]
-        combrow = (cseason, None, cenergy)
+        combrow = CombinedEPoint(crow.season, None, crow.energy_mean)
         combined_data.append(combrow)
     
     return combined_data
 
 
-def elabelize():
+def elabelize() -> List[CombinedEPoint]:
     RUNLIMITS = (17405, 200000)
     SEASONS = None
     epoints = retrieve_elabels(*RUNLIMITS)
@@ -175,7 +230,7 @@ def elabelize():
 def main():
     combdata = elabelize()
     for c in combdata:
-        season, elabel, energy = c
+        season, elabel, energy = c.season, c.elabel, c.energy_mean
         if season is None:
             season = ''
         if elabel is None:

+ 30 - 4
src/page/README.md

@@ -1,7 +1,33 @@
 Здесь лежит исходный код для страниц с изображениями 
 [cmd.inp.nsk.su/~compton/pictures](https://cmd.inp.nsk.su/~compton/pictures/)
 
-* `init.php` - страница с детальной (интерактивной) информацией о конкретной энергетической точке
-* `summary.php` - страница с информацией в целом о сезоне
-* `plots.php` - неинтерактивная информация об усреднениях по точкам в сезоне
-* `main.css` - стили css для сайта
+* `index.php` — стартовая страница
+* `init.php` — страница с детальной (интерактивной) информацией о конкретной энергетической точке
+* `summary.php` — страница с информацией в целом о сезоне
+* `commonfoos.php` — набор используемых php-функций, который подгружается на других страницах
+* `main.css` — стили css для сайта
+
+
+### Развёртывание раздела pictures
+1. получить данные из этого репозитория 
+```bash
+mkdir pictures
+cd pictures
+git init 
+git remote add -f origin <this-repo-link>
+git sparse-checkout set "src/page"
+git pull origin master
+```
+2. прописать в корневом `.htaccess` проксирование: **pictures/\*** → **pictures/src/page/\***
+3. в папку **src/page** добавить конфигурационный файл `config.ini` с таким содержанием (`apitoken` можно получить в настройках профиля в gogs)
+```ini
+[gogs]
+apitoken = "xxxxxx"
+```
+4. скачать [plotly-latest.min.js](https://cdn.plot.ly/plotly-latest.min.js) и [fmin.min.js](https://github.com/benfred/fmin)
+и положить в папку **src/page**
+
+
+#### Полезные ссылки по отображению графиков в js
+* [4 Ways to Improve Your Plotly Graphs (towardsdatascience)](https://towardsdatascience.com/4-ways-to-improve-your-plotly-graphs-517c75947f7)
+* [Chartjs and Csv (createwithdata)](https://www.createwithdata.com/chartjs-and-csv/)

+ 88 - 0
src/page/commonfoos.php

@@ -0,0 +1,88 @@
+<?php
+$host = "https://cmd.inp.nsk.su/~compton/gogs";
+$owner = "compton";
+$repo = "tables";
+
+
+function get_request($link)
+{
+    // Common get request with json decoder
+
+    $json = file_get_contents($link);
+    return json_decode($json);
+}
+
+function get_folder_data($host, $owner, $repo, $path, $token)
+{
+    // Gets folder content info
+
+    $obj = get_request("{$host}/api/v1/repos/{$owner}/{$repo}/contents/{$path}?token={$token}");
+    return $obj;
+}
+
+function get_seasons($host, $owner, $repo, $path, $token)
+{
+    // Returns all info about available seasons
+
+    $obj = get_folder_data($host, $owner, $repo, $path, $token);
+    $dir_obj = array_filter($obj, function ($var) {
+        return ($var->type == "dir");
+    });
+    return $dir_obj;
+}
+
+function available_seasons($host, $owner, $repo, $path, $token)
+{
+    // Returns sorted array of available season names
+
+    $season_obj = get_seasons($host, $owner, $repo, $path, $token);
+    foreach ($season_obj as &$s) {
+        $s = $s->name;
+    }
+    usort($season_obj, function ($a, $b) {
+        return substr($a, -4, 4) > substr($b, -4, 4);
+    });
+    return $season_obj;
+}
+
+function season_table_url($host, $owner, $repo, $path, $token, $season)
+{
+    // Returns URL of the season table
+
+    $obj = get_folder_data($host, $owner, $repo, $path, $token);
+    $ret_obj = array_filter($obj, function ($var) use ($season) {
+        return ($var->type == "file") && (substr($var->name, 0, strlen($season)) == $season);
+    });
+
+    $file = current($ret_obj);
+    $download_url_fix = substr($file->download_url, 0, -strlen($file->name)) . $path . "/" . ($file->name);
+    return $download_url_fix;
+}
+
+function energy_point_urls($host, $owner, $repo, $path, $token)
+{
+    // Returns an Array of energy points in $path with "name" keys and "download_url" values
+
+    $obj = get_folder_data($host, $owner, $repo, $path, $token);
+    $obj = array_filter($obj, function ($var) {
+        return ($var->type == "file") && (substr($var->name, -4, 4) == ".csv");
+    });
+
+    $ret_arr = array();
+    foreach ($obj as $file) {
+        $download_url_fix = substr($file->download_url, 0, -strlen($file->name)) . $path . "/" . ($file->name);
+        $ret_arr[$file->name] = $download_url_fix;
+    }
+    // print_r($ret_arr);
+    return $ret_arr;
+}
+
+function isSelected($a, $b)
+{
+    // Utility comparator function for selection lists
+
+    if ($a == $b) {
+        return "selected";
+    }
+    return "";
+}

+ 29 - 33
src/page/index.php

@@ -1,39 +1,35 @@
+<?php
+require __DIR__ . '/commonfoos.php';
+
+$ini_array = parse_ini_file("config.ini");
+$token = $ini_array["apitoken"];
+
+$names = available_seasons($host, $owner, $repo, "energy_points", $token);
+?>
+
 <html>
-    <title>Compton pictures</title>
-    <meta name="viewport" content="width=device-width, initial-scale=1">
-    <link rel="stylesheet" href="main.css">
-    
-    <body>
-        <div class="main_block">
+<title>Compton pictures</title>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<link rel="stylesheet" href="main.css">
+
+<body>
+    <div class="main_block">
+        <div class="title_block">
             <h1>Compton avg by seasons</h1>
+        </div>
 
-	    <!--
+        <div class="content_block">
             <?php
-                $directory = '.';
-                $scanned_directory = array_diff(scandir($directory), array('..', '.'));
-                $indir = array_filter($scanned_directory, function($item) {
-                    return is_dir('./' . $item);
-                });
-                foreach($indir as $v){ ?>
-                    <a href="./plots.php?season=<?echo $v;?>"><?echo $v;?></a><br>
-                    <?
-                }
-	    ?> 
-
-            <br> -->
-	    
-            <a href="./init.php?season=RHO2013">RHO2013<a><br>
-	    <a href="./init.php?season=HIGH2017">HIGH2017<a><br>
-	    <a href="./init.php?season=RHO2018">RHO2018<a><br>
-            <a href="./init.php?season=HIGH2019">HIGH2019<a><br>
-	    <a href="./init.php?season=LOW2020">LOW2020<a><br>
-	    <a href="./init.php?season=HIGH2020">HIGH2020<a><br>
-	    <a href="./init.php?season=HIGH2021">HIGH2021<a><br>	    
-	    <a href="./init.php?season=NNBAR2022">NNBAR2022</a><br>
-	    <a href="./init.php?season=HIGH2023">HIGH2023</a><br>
-	    <a href="./init.php?season=PHI2024">PHI2024</a><br>
-		<br>
-            <a href="./summary.php?csv_file=PHI2024.csv">Season summary</a>
+            foreach ($names as $name) {
+                echo "<div class=\"selection_item\"><a href=\"./init.php?season={$name}\">• {$name}</a></div>";
+            }
+            ?>
         </div>
-    </body>
+        <br>
+        <?php
+        echo "<div class=\"selection_item\"><a href=\"./summary.php?season=" . end($names) . "\">Season summary</a></div>";
+        ?>
+    </div>
+</body>
+
 </html>

+ 176 - 175
src/page/init.php

@@ -1,171 +1,162 @@
-<!-- https://www.createwithdata.com/chartjs-and-csv/ -->
-<!-- https://towardsdatascience.com/4-ways-to-improve-your-plotly-graphs-517c75947f7e -->
-
 <?php
-$branch = 'dev';
-
-function getsmth($branch){
-    $url = "https://cmd.inp.nsk.su/~compton/gitlist/compton_tables/raw/".$branch."/tables/";
-    $text = file_get_contents($url);
-    $arrays = explode("\n", $text);
-    $clean_arrs = array_filter($arrays, function($value){
-	$temp_arr = explode('/', $value);
-        return preg_match("/[A-Z]+[0-9]+\//", $value);
-    });
-    foreach($clean_arrs as &$val){
-        $val = substr($val, 0, -1);
-    }
-    return $clean_arrs;
-}
-
-$availableSeasons = getsmth($branch);
-
-$season = isset($_GET["season"])&&in_array($_GET["season"], $availableSeasons) ? $_GET["season"] : reset($availableSeasons);
-$url = "https://cmd.inp.nsk.su/~compton/gitlist/compton_tables/raw/".$branch."/tables/".$season."/";
-$url_total_info = "https://cmd.inp.nsk.su/~compton/gitlist/compton_tables/raw/".$branch."/tables/".$season.".csv";
-$text = file_get_contents($url);
-$arrays = explode("\n", $text);
-
-$cleanArrs = array_filter($arrays, function($value) {
-   return end(explode('.', $value)) == "csv";
-});
-
-function isSelected($a, $b){
-    if ($a==$b){
-        return "selected";
-    }
-    return "";
-}
-
-$selected_csv = isset($_GET["csv_file"])&&in_array($_GET["csv_file"], $cleanArrs) ? $_GET["csv_file"] : reset($cleanArrs);
+require __DIR__ . '/commonfoos.php';
+
+$ini_array = parse_ini_file("config.ini");
+$token = $ini_array["apitoken"];
+
+$availableSeasons = available_seasons($host, $owner, $repo, "energy_points", $token);
+
+$season = isset($_GET["season"]) && in_array($_GET["season"], $availableSeasons) ? $_GET["season"] : end($availableSeasons);
+$season_url = season_table_url($host, $owner, $repo, "", $token, $season);
+
+$energyPoints = energy_point_urls($host, $owner, $repo, "energy_points/{$season}", $token);
 
+$selected_csv = isset($_GET["csv_file"]) && array_key_exists($_GET["csv_file"], $energyPoints) ? $_GET["csv_file"] : key($energyPoints);
 ?>
 
 <html>
+
 <head>
     <script src="plotly-latest.min.js"></script>
     <!-- <script src="https://cdn.plot.ly/plotly-latest.min.js"></script> -->
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <link rel="stylesheet" href="main.css">
     <title>Compton interactive plots</title>
-    <!-- <script src="chart.js"></script> -->
 </head>
+
 <body>
     <div id="gd" style="height: max(80vh, 600px); padding-bottom: 20px;"></div>
-            
+
     <form name="form" action="" method="get">
         <p style="text-align: center;">Select energy point:</p>
-	<div style="margin: 0 auto; display: flex; justify-content: center;">
-        <select name="season" class="select-css" style="margin: 0;" onchange="this.form.submit()">
-            <? foreach($availableSeasons as $s){ ?>
-            <option value="<?echo $s?>" <?echo isSelected($s, $season)?>><?echo $s?></option>
-            <? } ?>
-        </select>
-        <select name="csv_file" class="select-css" style="margin: 0;" onchange="this.form.submit()">
-            <? foreach($cleanArrs as $file){ ?>
-            <option value="<?echo $file?>" <?echo isSelected($file, $selected_csv)?>><?echo $file?></option>
-            <? } ?>
-        </select>
-	</div>
+        <div style="margin: 0 auto; display: flex; justify-content: center;">
+            <select name="season" class="select-css" style="margin: 0;" onchange="this.form.submit()">
+                <? foreach ($availableSeasons as $s) { ?>
+                    <option value="<? echo $s ?>" <? echo isSelected($s, $season) ?>>
+                        <? echo $s ?>
+                    </option>
+                <? } ?>
+            </select>
+            <select name="csv_file" class="select-css" style="margin: 0;" onchange="this.form.submit()">
+                <? foreach ($energyPoints as $key => $file) { ?>
+                    <option value="<? echo $key ?>" <? echo isSelected($key, $selected_csv) ?>>
+                        <? echo $key ?>
+                    </option>
+                <? } ?>
+            </select>
+        </div>
     </form>
 
 
     <script>
-        function makeplot(){
-            Plotly.d3.csv('<?echo $url_total_info;?>', (allRows)=>{
-                const {mean_energy, mean_spread, mean_energy_stat_err} = parseResultsTable(allRows, "<?echo $selected_csv;?>");        
-                Plotly.d3.csv('<?echo $url.$selected_csv;?>', function(data){processData(data, mean_energy, mean_spread, mean_energy_stat_err)});
-            }
-            );
+        function makeplot() {
+            Plotly.d3.csv('<? echo $season_url; ?>', (allRows) => {
+                const {
+                    mean_energy,
+                    mean_spread,
+                    mean_energy_stat_err
+                } = parseResultsTable(allRows, "<? echo $selected_csv; ?>");
+                Plotly.d3.csv('<? echo $energyPoints[$selected_csv]; ?>', function(data) {
+                    processData(data, mean_energy, mean_spread, mean_energy_stat_err)
+                });
+            });
         }
-        
-        function parseResultsTable(allRows, energy_point){
+
+        function parseResultsTable(allRows, energy_point) {
             // Extracts a row following the energy point in the total csv file (or null if energy point is not exists)
             data = energy_point.slice(0, -4).split('_');
-	    for (var i=0; i<allRows.length; i++){
-                if (allRows[i].first_run == data[1] ){
+            for (var i = 0; i < allRows.length; i++) {
+                if (allRows[i].first_run == data[1]) {
                     return allRows[i];
                 }
             }
             return null;
         }
-        
-        function parseRow(row){
+
+        function parseRow(row) {
             // Parses a row from the detailed csv file
-	    row['start_time'] = Date.parse(row['compton_start']);
+            row['start_time'] = Date.parse(row['compton_start']);
             row['stop_time'] = Date.parse(row['compton_stop']);
-            row['center_time'] = new Date((row['start_time'] + row['stop_time'])/2);
-            row['timedelta'] = (row['stop_time'] - row['start_time'])/2/1000; // in seconds
+            row['center_time'] = new Date((row['start_time'] + row['stop_time']) / 2);
+            row['timedelta'] = (row['stop_time'] - row['start_time']) / 2 / 1000; // in seconds
 
-	    text_energy = "E = " + parseFloat(row['e_mean']).toFixed(2) + "±" + parseFloat(row['e_std']).toFixed(2) + " MeV<br>";
-	    text_spread = "spread = " + parseFloat(row['spread_mean']).toFixed(2) + "±" + parseFloat(row['spread_std']).toFixed(2) + " MeV<br>";
-            text_str = text_energy + text_spread + "<b>Compton</b><br>" + "<i>Start: </i>" + 
-                    row['compton_start'] + "<br><i>Stop: </i>" + row['compton_stop'] + "<br><br>";
+            text_energy = "E = " + parseFloat(row['e_mean']).toFixed(2) + "±" + parseFloat(row['e_std']).toFixed(2) + " MeV<br>";
+            text_spread = "spread = " + parseFloat(row['spread_mean']).toFixed(2) + "±" + parseFloat(row['spread_std']).toFixed(2) + " MeV<br>";
+            text_str = text_energy + text_spread + "<b>Compton</b><br>" + "<i>Start: </i>" +
+                row['compton_start'] + "<br><i>Stop: </i>" + row['compton_stop'] + "<br><br>";
             row['text_str'] = text_str + "<b>Runs: </b>" + row['run_first'] + " - " + row['run_last'] + "<br><br>";
             return row;
         }
-        
-        function processSpread(data, elementId, mean_value){
-            let x = [], y = [], std_y = []
-            for (var i=0; i<data.length; i++){
-                const {center_time, spread_mean, spread_std} = parseRow(data[i]);
+
+        function processSpread(data, elementId, mean_value) {
+            let x = [],
+                y = [],
+                std_y = []
+            for (var i = 0; i < data.length; i++) {
+                const {
+                    center_time,
+                    spread_mean,
+                    spread_std
+                } = parseRow(data[i]);
                 x.push(center_time);
                 y.push(spread_mean);
                 std_y.push(spread_std);
             }
             makeSpreadPlot(elementId, x, y, std_y, mean_value);
         }
-        
+
         function kde(x, y, w) {
-            const ts = (t) => t.getTime()/1000;
+            const ts = (t) => t.getTime() / 1000;
             const toDateTime = (secs) => {
                 let t = new Date(0);
                 t.setSeconds(secs);
                 return t;
             };
             const steps = 1000;
-            const dt =  (ts(x[x.length - 1]) - ts(x[0]))/steps;
+            const dt = (ts(x[x.length - 1]) - ts(x[0])) / steps;
             const kernel = (x, x0, w0, y0) => {
-                if (Math.abs(x-x0)>w0){
+                if (Math.abs(x - x0) > w0) {
                     return 0;
                 }
-                return y0/w0;
+                return y0 / w0;
                 //return y0*3*(1-((x-x0)/w0/2)**2)/4;
-            }; 
+            };
             const get_est = (timestamp) => {
                 let val = 0
-                for (var i=0; i<x.length; i++){
+                for (var i = 0; i < x.length; i++) {
                     val += kernel(timestamp, ts(x[i]), w[i], y[i]);
                 }
                 return val;
             };
             //console.log(x, y);
-            const timestamp_arr = Plotly.d3.range(steps).map(function(i){return ts(x[0])+i*dt;});
-            
+            const timestamp_arr = Plotly.d3.range(steps).map(function(i) {
+                return ts(x[0]) + i * dt;
+            });
+
             let kdex = [];
             let kdey = [];
-            for (var j=0; j<timestamp_arr.length; j++){
+            for (var j = 0; j < timestamp_arr.length; j++) {
                 kdex.push(toDateTime(timestamp_arr[j]));
                 kdey.push(get_est(timestamp_arr[j]));
             }
             //console.log(kdex, kdey);
             return [kdex, kdey]
         }
-        
-        function oldAverage(E, L){
+
+        function oldAverage(E, L) {
             //Averager by the old method with E and L only
-            if (E.length !== L.length){
+            if (E.length !== L.length) {
                 return null;
             }
             let EL = 0;
             let sL = 0;
-            for (let i = 0; i<E.length; i++){
-                EL += parseFloat(E[i])*parseFloat(L[i]);
+            for (let i = 0; i < E.length; i++) {
+                EL += parseFloat(E[i]) * parseFloat(L[i]);
                 sL += parseFloat(L[i]);
             }
-            return EL/sL;
+            return EL / sL;
         }
-        
+
         function processData(allRows, mean_energy, mean_spread, mean_energy_stat_err) {
             // Processes all data rows
             var dict = {};
@@ -177,44 +168,44 @@ $selected_csv = isset($_GET["csv_file"])&&in_array($_GET["csv_file"], $cleanArrs
             dict['compton'] = [];
             dict['lum'] = [];
             dict['twidth'] = [];
-            
-            for (var i=0; i<allRows.length; i++){
+
+            for (var i = 0; i < allRows.length; i++) {
                 const row = parseRow(allRows[i]);
-                                
-                dict['x'].push( row['center_time'] );
-                dict['e_mean'].push( row['e_mean'] );
-                dict['e_std'].push( row['e_std'] );
-                dict['spread_mean'].push( row['spread_mean'] );
-                dict['spread_std'].push( row['spread_std'] );
-                dict['compton'].push( row['text_str'] );
-                dict['lum'].push( row['luminosity'] );
-                dict['twidth'].push( row['timedelta'] );
+
+                dict['x'].push(row['center_time']);
+                dict['e_mean'].push(row['e_mean']);
+                dict['e_std'].push(row['e_std']);
+                dict['spread_mean'].push(row['spread_mean']);
+                dict['spread_std'].push(row['spread_std']);
+                dict['compton'].push(row['text_str']);
+                dict['lum'].push(row['luminosity']);
+                dict['twidth'].push(row['timedelta']);
             }
-            
+
             const [a, b] = kde(dict['x'], dict['lum'], dict['twidth']);
             dict['kdex'] = a;
             dict['kdey'] = b;
             //console.log(dict['kdex'], dict['kdey']);
             //oldAverage(y, dict['lum']);
-            
+
             dict['mean_energy_total'] = mean_energy;
             dict['old_mean_energy_total'] = oldAverage(dict['e_mean'], dict['lum']);
             dict['mean_spread_total'] = mean_spread;
-	    dict['mean_energy_stat_err'] = mean_energy_stat_err;
-            
+            dict['mean_energy_stat_err'] = mean_energy_stat_err;
+
             makePlotly(dict, "gd");
         }
-        
-        function makePlotly(dict, elementId){
+
+        function makePlotly(dict, elementId) {
             const getYRange = (y, std_y) => {
                 const ys = [...y].sort();
                 const std_ys = [...std_y].sort();
-                let idx = Math.floor(ys.length/2);
+                let idx = Math.floor(ys.length / 2);
                 const y0 = parseFloat(ys[idx]);
                 const std0 = parseFloat(std_ys[idx]);
-                return [y0-6*std0, y0+6*std0];
+                return [y0 - 6 * std0, y0 + 6 * std0];
             };
-            
+
             var trace1 = {
                 x: dict['x'],
                 y: dict['e_mean'],
@@ -268,32 +259,38 @@ $selected_csv = isset($_GET["csv_file"])&&in_array($_GET["csv_file"], $cleanArrs
                 type: "scatter",
             };
             var traces = [trace1, trace2, trace3];
-            
+
             var updatemenus = [];
-	    console.log(dict);
-            if (dict['mean_energy_total']){
+            console.log(dict);
+            if (dict['mean_energy_total']) {
                 updatemenus = [{
-                buttons: [
-                    {
-                        args:[{'shapes[0].visible': true, 'shapes[1].visible': false, 'title': '<E> = ' + parseFloat(dict['mean_energy_total']).toFixed(3) + '±' + parseFloat(dict['mean_energy_stat_err']).toFixed(3) + ' MeV, ' + '<Spread> = ' + parseFloat(dict['mean_spread_total']).toFixed(3) + ' MeV',}],
+                    buttons: [{
+                        args: [{
+                            'shapes[0].visible': true,
+                            'shapes[1].visible': false,
+                            'title': '<E> = ' + parseFloat(dict['mean_energy_total']).toFixed(3) + '±' + parseFloat(dict['mean_energy_stat_err']).toFixed(3) + ' MeV, ' + '<Spread> = ' + parseFloat(dict['mean_spread_total']).toFixed(3) + ' MeV',
+                        }],
                         label: 'Current average method',
                         method: 'relayout'
                     }, {
-                        args:[{'shapes[0].visible': false, 'shapes[1].visible': true, 'title': '<E> = ' + parseFloat(dict['old_mean_energy_total']).toFixed(3) + ' MeV, ' + '<Spread> = ' + parseFloat(dict['mean_spread_total']).toFixed(3) + ' MeV',}],
+                        args: [{
+                            'shapes[0].visible': false,
+                            'shapes[1].visible': true,
+                            'title': '<E> = ' + parseFloat(dict['old_mean_energy_total']).toFixed(3) + ' MeV, ' + '<Spread> = ' + parseFloat(dict['mean_spread_total']).toFixed(3) + ' MeV',
+                        }],
                         label: 'Former average method',
                         method: 'relayout'
-                    },
-                ],
-                direction: 'center',
-                showactive: 'true',
-                type: 'dropdown',
-                y: 1.1,
-                xanchor: 'left',
-                yanchor: 'top',
-                active: 0,
-            }];
+                    }, ],
+                    direction: 'center',
+                    showactive: 'true',
+                    type: 'dropdown',
+                    y: 1.1,
+                    xanchor: 'left',
+                    yanchor: 'top',
+                    active: 0,
+                }];
             }
-            
+
             var layout = {
                 title: '<E> = ' + parseFloat(dict['mean_energy_total']).toFixed(3) + '±' + parseFloat(dict['mean_energy_stat_err']).toFixed(3) + ' MeV, ' + '<Spread> = ' + parseFloat(dict['mean_spread_total']).toFixed(3) + ' MeV',
                 updatemenus: updatemenus,
@@ -333,55 +330,59 @@ $selected_csv = isset($_GET["csv_file"])&&in_array($_GET["csv_file"], $cleanArrs
                 plot_bgcolor: 'rgba(0,0,0,0)',
                 autosize: true,
             };
-            
-            if (dict['mean_energy_total']){
+
+            if (dict['mean_energy_total']) {
                 layout['shapes'] = [{
-                    type: 'line',
-                    yref: 'y3',
-                    xref: 'paper',
-                    x0: 0,
-                    x1: 1,
-                    y0: dict['mean_energy_total'],
-                    y1: dict['mean_energy_total'],
-                    line: {
-                        color: '#590A0A',
+                        type: 'line',
+                        yref: 'y3',
+                        xref: 'paper',
+                        x0: 0,
+                        x1: 1,
+                        y0: dict['mean_energy_total'],
+                        y1: dict['mean_energy_total'],
+                        line: {
+                            color: '#590A0A',
+                        },
                     },
-                },
-                {
-                    type: 'line',
-                    yref: 'y3',
-                    xref: 'paper',
-                    x0: 0,
-                    x1: 1,
-                    y0: dict['old_mean_energy_total'],
-                    y1: dict['old_mean_energy_total'],
-                    line: {
-                        color: '#590A0A',
-                    },
-                    visible: false,
-                },
-                {
-                    type: 'line',
-                    yref: 'y2',
-                    xref: 'paper',
-                    x0: 0,
-                    x1: 1,
-                    y0: dict['mean_spread_total'],
-                    y1: dict['mean_spread_total'],
-                    line: {
-                        color: '#590A0A',
+                    {
+                        type: 'line',
+                        yref: 'y3',
+                        xref: 'paper',
+                        x0: 0,
+                        x1: 1,
+                        y0: dict['old_mean_energy_total'],
+                        y1: dict['old_mean_energy_total'],
+                        line: {
+                            color: '#590A0A',
+                        },
+                        visible: false,
                     },
-                    visible: true,
-                }];
+                    {
+                        type: 'line',
+                        yref: 'y2',
+                        xref: 'paper',
+                        x0: 0,
+                        x1: 1,
+                        y0: dict['mean_spread_total'],
+                        y1: dict['mean_spread_total'],
+                        line: {
+                            color: '#590A0A',
+                        },
+                        visible: true,
+                    }
+                ];
             }
-            
-            Plotly.newPlot('gd', traces, layout, {modeBarButtonsToRemove: ['toImage'], responsive: true,});
-            
+
+            Plotly.newPlot('gd', traces, layout, {
+                modeBarButtonsToRemove: ['toImage'],
+                responsive: true,
+            });
+
         }
-        
+
         makeplot();
-        
     </script>
 
 </body>
-</html>
+
+</html>

+ 73 - 51
src/page/main.css

@@ -1,102 +1,124 @@
 @import url('https://fonts.googleapis.com/css2?family=Raleway&display=swap');
 @import url('https://fonts.googleapis.com/css2?family=Open+Sans&display=swap');
 
-a{
-    font-size: 36px;
+a {
+    font-size: 3.6rem;
     text-decoration: none;
     color: #26110C;
-    transition-duration: 1s;
     font-family: 'Raleway', sans-serif;
 }
 
-a:hover{
+a:hover {
     color: #732727;
+    text-decoration: underline;
 }
 
-a:visited{
-    color: #26110C;
+body {
+    background-color: #F2A76650;
+    margin: 0;
+    /*#D9B9A7;*/
 }
 
-body{
-    background-color: #F2A76687; /*#D9B9A7;*/
+br {
+    margin-bottom: 1.8rem;
 }
 
-br{
-    margin-bottom: 18px;
+div.content_block {
+    display: flex;
+    flex-direction: column-reverse;
+    flex-wrap: wrap;
+    flex-basis: 100%;
+    flex: 1;
+    width: 100%;
 }
 
-div.main_block{
-    width: max(50%, 500px);
+div.main_block {
+    width: max(50%, 350px);
     max-width: min(100%, 800px);
     margin: 0 auto;
-    padding-top: 50px;
 }
 
-h1{
+div.selection_item {
+    min-width: 40%;
+    padding: 0.5rem 1rem;
+}
+
+div.title_block {
+    margin: 4rem 0;
+}
+
+h1 {
     font-family: 'Raleway', sans-serif;
-    font-size: 48px;
+    font-size: 4.8rem;
+    padding-left: 1rem;
+    margin: 0;
 }
 
-h2{
+h2 {
     font-family: 'Raleway', sans-serif;
-    font-size: 40px;
+    font-size: 4rem;
 }
 
-h3{
+h3 {
     font-family: 'Open Sans', sans-serif;
-    font-size: 32px;  
+    font-size: 3.2rem;
 }
 
-h4{
+h4 {
     font-family: 'Open Sans', sans-serif;
-    font-size: 24px;
+    font-size: 2.4rem;
 }
 
-hr{
+hr {
     border: 0;
     border-bottom: dashed;
 }
 
-img{
-    padding: 15px 0;
+html {
+    font-size: 62.5%;
+    margin: 0;
+}
+
+img {
+    padding: 1.5rem 0;
     width: 100%;
 }
 
-p{
+p {
     font-family: 'Raleway', sans-serif;
-    font-size: 28px;
+    font-size: 2.8rem;
 }
 
 select {
 
-  /* styling */
-  background-color: #F2A76652;
-  border: thin solid #F23030;
-  border-radius: 4px;
-  display: block;
-  font: inherit;
-  font-size: 20px;
-  line-height: 1.5em;
-  padding: 0.5em 3.5em 0.5em 1em;
+    /* styling */
+    background-color: #F2A76652;
+    border: thin solid #F23030;
+    border-radius: 4px;
+    display: block;
+    font: inherit;
+    font-size: 2.0rem;
+    line-height: 1.5em;
+    padding: 0.5em 3.5em 0.5em 1em;
 
-  /* reset */
+    /* reset */
 
-  margin: 0 auto;      
-  -webkit-box-sizing: border-box;
-  -moz-box-sizing: border-box;
-  box-sizing: border-box;
-  -webkit-appearance: none;
-  -moz-appearance: none;
+    margin: 0 auto;
+    -webkit-box-sizing: border-box;
+    -moz-box-sizing: border-box;
+    box-sizing: border-box;
+    -webkit-appearance: none;
+    -moz-appearance: none;
 }
 
 select.select-css {
     background-image:
-	linear-gradient(45deg, transparent 50%, #260101 0%),
-	linear-gradient(135deg, #260101 50%, transparent 0%);
-  background-position:
-      calc(100% - 21px) calc(1em + 2px),
-      calc(100% - 13px) calc(1em + 2px);
-  background-size:
-      8px 8px, 8px 8px, 2.5em 2.5em;
-  background-repeat: no-repeat;
-}
+        linear-gradient(45deg, transparent 50%, #260101 0%),
+        linear-gradient(135deg, #260101 50%, transparent 0%);
+    background-position:
+        calc(100% - 21px) calc(1em + 2px),
+        calc(100% - 13px) calc(1em + 2px);
+    background-size:
+        8px 8px, 8px 8px, 2.5em 2.5em;
+    background-repeat: no-repeat;
+}

+ 0 - 350
src/page/plots.php

@@ -1,350 +0,0 @@
-<!-- https://www.createwithdata.com/chartjs-and-csv/ -->
-<!-- https://towardsdatascience.com/4-ways-to-improve-your-plotly-graphs-517c75947f7e -->
-
-<?php
-$selected_csv = 
-
-$branch = 'dev';
-$season = 'NNBAR2021';
-$url = "https://cmd.inp.nsk.su/~compton/gitlist/compton_tables/raw/".$branch."/tables/".$season."/";
-$url_total_info = "https://cmd.inp.nsk.su/~compton/gitlist/compton_tables/raw/".$branch."/tables/".$season.".csv";
-$text = file_get_contents($url);
-$arrays = explode("\n", $text);
-
-$cleanArrs = array_filter($arrays, function($value) {
-   return end(explode('.', $value)) == "csv";
-});
-
-function isSelected($a, $b){
-    if ($a==$b){
-        return "selected";
-    }
-    return "";
-}
-
-$selected_csv = isset($_GET["csv_file"]) ? $_GET["csv_file"] : reset($cleanArrs);
-
-?>
-
-<html>
-<head>
-    <!--<script src="plotly-2.11.1.min.js"></script> -->
-    <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
-    <meta name="viewport" content="width=device-width, initial-scale=1">
-    <link rel="stylesheet" href="main.css">
-    <title>Compton interactive plots</title>
-    <!-- <script src="chart.js"></script> -->
-</head>
-<body>
-    <div id="gd" style="height: max(80vh, 600px); padding-bottom: 20px;"></div>
-            
-    <form name="form" action="" method="get">
-        <p style="text-align: center;">Select energy point:</p>
-        <select name="csv_file" class="select-css" onchange="this.form.submit()">
-            <?
-            foreach($cleanArrs as $file){
-                ?><option value="<?echo $file?>" <?echo isSelected($file, $selected_csv)?>><?echo $file?></option>
-                <?
-            }
-            ?>
-        </select>
-    </form>
-
-
-    <script>
-        function makeplot(){
-            Plotly.d3.csv('<?echo $url_total_info;?>', (allRows)=>{
-                const {mean_energy, mean_spread} = parseResultsTable(allRows, <?echo reset(explode('_', $selected_csv));?>);        
-                Plotly.d3.csv('<?echo $url.$selected_csv;?>', function(data){processData(data, mean_energy, mean_spread)});
-            }
-            );
-        }
-        
-        function parseResultsTable(allRows, energy_point){
-            // Extracts a row following the energy point in the total csv file (or null if energy point is not exists)
-            for (var i=0; i<allRows.length; i++){
-                if (allRows[i].energy_point == energy_point ){
-                    return allRows[i];
-                }
-            }
-            return null;
-        }
-        
-        function parseRow(row){
-            // Parses a row from the detailed csv file
-            row['start_time'] = Date.parse(row['compton_start']);
-            row['stop_time'] = Date.parse(row['compton_stop']);
-            row['center_time'] = new Date((row['start_time'] + row['stop_time'])/2);
-            row['timedelta'] = (row['stop_time'] - row['start_time'])/2/1000; // in seconds
-            text_str = "<b>Compton</b><br>" + "<i>Start: </i>" + 
-                    row['compton_start'] + "<br><i>Stop: </i>" + row['compton_stop'] + "<br><br>";
-            row['text_str'] = text_str + "<b>Runs: </b>" + row['run_first'] + " - " + row['run_last'] + "<br><br>";
-            return row;
-        }
-        
-        function processSpread(data, elementId, mean_value){
-            let x = [], y = [], std_y = []
-            for (var i=0; i<data.length; i++){
-                const {center_time, spread_mean, spread_std} = parseRow(data[i]);
-                x.push(center_time);
-                y.push(spread_mean);
-                std_y.push(spread_std);
-            }
-            makeSpreadPlot(elementId, x, y, std_y, mean_value);
-        }
-        
-        function kde(x, y, w) {
-            const ts = (t) => t.getTime()/1000;
-            const toDateTime = (secs) => {
-                let t = new Date(0);
-                t.setSeconds(secs);
-                return t;
-            };
-            const steps = 1000;
-            const dt =  (ts(x[x.length - 1]) - ts(x[0]))/steps;
-            const kernel = (x, x0, w0, y0) => {
-                if (Math.abs(x-x0)>w0){
-                    return 0;
-                }
-                return y0/w0;
-                //return y0*3*(1-((x-x0)/w0/2)**2)/4;
-            }; 
-            const get_est = (timestamp) => {
-                let val = 0
-                for (var i=0; i<x.length; i++){
-                    val += kernel(timestamp, ts(x[i]), w[i], y[i]);
-                }
-                return val;
-            };
-            //console.log(x, y);
-            const timestamp_arr = Plotly.d3.range(steps).map(function(i){return ts(x[0])+i*dt;});
-            
-            let kdex = [];
-            let kdey = [];
-            for (var j=0; j<timestamp_arr.length; j++){
-                kdex.push(toDateTime(timestamp_arr[j]));
-                kdey.push(get_est(timestamp_arr[j]));
-            }
-            //console.log(kdex, kdey);
-            return [kdex, kdey]
-        }
-        
-        function oldAverage(E, L){
-            //Averager by the old method with E and L only
-            if (E.length !== L.length){
-                return null;
-            }
-            let EL = 0;
-            let sL = 0;
-            for (let i = 0; i<E.length; i++){
-                EL += parseFloat(E[i])*parseFloat(L[i]);
-                sL += parseFloat(L[i]);
-            }
-            return EL/sL;
-        }
-        
-        function processData(allRows, mean_energy, mean_spread) {
-            // Processes all data rows
-            var dict = {};
-            dict['x'] = [];
-            dict['e_mean'] = [];
-            dict['e_std'] = [];
-            dict['spread_mean'] = [];
-            dict['spread_std'] = [];
-            dict['compton'] = [];
-            dict['lum'] = [];
-            dict['twidth'] = [];
-            
-            for (var i=0; i<allRows.length; i++){
-                const row = parseRow(allRows[i]);
-                                
-                dict['x'].push( row['center_time'] );
-                dict['e_mean'].push( row['e_mean'] );
-                dict['e_std'].push( row['e_std'] );
-                dict['spread_mean'].push( row['spread_mean'] );
-                dict['spread_std'].push( row['spread_std'] );
-                dict['compton'].push( row['text_str'] );
-                dict['lum'].push( row['luminosity'] );
-                dict['twidth'].push( row['timedelta'] );
-            }
-            
-            const [a, b] = kde(dict['x'], dict['lum'], dict['twidth']);
-            dict['kdex'] = a;
-            dict['kdey'] = b;
-            //console.log(dict['kdex'], dict['kdey']);
-            //oldAverage(y, dict['lum']);
-            
-            dict['mean_energy_total'] = mean_energy;
-            dict['old_mean_energy_total'] = oldAverage(dict['e_mean'], dict['lum']);
-            dict['mean_spread_total'] = mean_spread;
-            
-            makePlotly(dict, "gd");
-        }
-        
-        function makePlotly(dict, elementId){
-            const getYRange = (y, std_y) => {
-                const ys = [...y].sort();
-                const std_ys = [...std_y].sort();
-                let idx = Math.floor(ys.length/2);
-                const y0 = parseFloat(ys[idx]);
-                const std0 = parseFloat(std_ys[idx]);
-                return [y0-6*std0, y0+6*std0];
-            };
-            
-            var trace1 = {
-                x: dict['x'],
-                y: dict['e_mean'],
-                yaxis: 'y3',
-                mode: 'markers',
-                text: dict['compton'],
-                hovertemplate: "%{text}<br><br>" + "<extra></extra>",
-                hovermode: "x",
-                error_y: {
-                    type: 'data',
-                    array: dict['e_std'],
-                    color: '#260101',
-                },
-                showlegend: false,
-                marker: {
-                    color: '#260101',
-                },
-                type: "scatter",
-            };
-            var trace2 = {
-                x: dict['x'],
-                y: dict['spread_mean'],
-                yaxis: 'y2',
-                mode: 'markers',
-                text: dict['compton'],
-                hovertemplate: "%{text}<br><br>" + "<extra></extra>",
-                hovermode: "x",
-                error_y: {
-                    type: 'data',
-                    array: dict['spread_std'],
-                    color: '#260101',
-                },
-                showlegend: false,
-                marker: {
-                    color: '#260101',
-                },
-                type: "scatter",
-            };
-            var trace3 = {
-                x: dict['kdex'],
-                y: dict['kdey'],
-                hovertemplate: "%{y}<br><br>" + "<extra></extra>",
-                hovermode: "x",
-                showlegend: false,
-                marker: {
-                    color: '#F23030',
-                },
-                line: {
-                    shape: 'hvh',
-                },
-                type: "scatter",
-            };
-            var traces = [trace1, trace2, trace3];
-            
-            var updatemenus = [];
-            if (dict['mean_energy_total']){
-                updatemenus = [{
-                buttons: [
-                    {
-                        args:[{'shapes[0].visible': true, 'shapes[1].visible': false, 'title': 'Mean energy: ' + parseFloat(dict['mean_energy_total']).toFixed(3) + ' MeV',}],
-                        label: 'Current average method',
-                        method: 'relayout'
-                    }, {
-                        args:[{'shapes[0].visible': false, 'shapes[1].visible': true, 'title': 'Mean energy: ' + dict['old_mean_energy_total'].toFixed(3)  + ' MeV',}],
-                        label: 'Former average method',
-                        method: 'relayout'
-                    },
-                ],
-                direction: 'center',
-                showactive: 'true',
-                type: 'dropdown',
-                y: 1.1,
-                xanchor: 'left',
-                yanchor: 'top',
-                active: 0,
-            }];
-            }
-            
-            
-            var layout = {
-                title: 'Mean energy: ' + dict['mean_energy_total'] + ' MeV',
-                updatemenus: updatemenus,
-                font: {
-                    size: 18,
-                },
-                xaxis: {
-                    title: "Time, NSK",
-                    automargin: true,
-                },
-                yaxis3: {
-                    domain: [0.6, 1],
-                    title: "Mean energy, MeV",
-                    automargin: true,
-                    //showspikes: true,
-                    //spikemode: "across",
-                    //spikesnap: "data",
-                },
-                yaxis2: {
-                    domain: [0.3, 0.5],
-                    title: "Spread, MeV",
-                    autorange: false,
-                    range: getYRange(dict['spread_mean'], dict['spread_std']),
-                    //showspikes: true,
-                    //spikemode: "across",
-                    //spikesnap: "data",
-                },
-                yaxis: {
-                    domain: [0, 0.2],
-                    automargin: true,
-                    zeroline: true,
-                    rangemode: 'positive',
-                    title: "L, nb<sup>-1</sup>/s",
-                    hoverformat: '.2f',
-                },
-                paper_bgcolor: 'rgba(0,0,0,0)',
-                plot_bgcolor: 'rgba(0,0,0,0)',
-                autosize: true,
-            };
-            
-            if (dict['mean_energy_total']){
-                layout['shapes'] = [{
-                    type: 'line',
-                    yref: 'y3',
-                    xref: 'paper',
-                    x0: 0,
-                    x1: 1,
-                    y0: dict['mean_energy_total'],
-                    y1: dict['mean_energy_total'],
-                    line: {
-                        color: '#590A0A',
-                    },
-                },
-                {
-                    type: 'line',
-                    yref: 'y3',
-                    xref: 'paper',
-                    x0: 0,
-                    x1: 1,
-                    y0: dict['old_mean_energy_total'],
-                    y1: dict['old_mean_energy_total'],
-                    line: {
-                        color: '#590A0A',
-                    },
-                    visible: false,
-                }];
-            }
-            
-            Plotly.newPlot('gd', traces, layout, {modeBarButtonsToRemove: ['toImage'], responsive: true,});
-            
-        }
-        
-        makeplot();
-        
-    </script>
-
-</body>
-</html>

+ 127 - 117
src/page/summary.php

@@ -1,30 +1,18 @@
 <?php
-$selected_csv = 
+require __DIR__ . '/commonfoos.php';
 
-$branch = 'dev';
-$season = 'NNBAR2021';
-$url = "https://cmd.inp.nsk.su/~compton/gitlist/compton_tables/raw/".$branch."/tables/";
-$url_total_info = "https://cmd.inp.nsk.su/~compton/gitlist/compton_tables/raw/".$branch."/tables/".$season.".csv";
-$text = file_get_contents($url);
-$arrays = explode("\n", $text);
+$ini_array = parse_ini_file("config.ini");
+$token = $ini_array["apitoken"];
 
-$cleanArrs = array_filter($arrays, function($value) {
-   return end(explode('.', $value)) == "csv";
-});
+$available_seasons = available_seasons($host, $owner, $repo, "energy_points", $token);
 
-function isSelected($a, $b){
-    if ($a==$b){
-        return "selected";
-    }
-    return "";
-}
-
-$selected_csv = isset($_GET["csv_file"]) ? $_GET["csv_file"] : reset($cleanArrs);
-$selected_season = substr($selected_csv, 0, -4);
+$selected_season = isset($_GET["season"]) && in_array($_GET["season"], $available_seasons) ? $_GET["season"] : end($available_seasons);
+$selected_season_url = season_table_url($host, $owner, $repo, "", $token, $selected_season);
 
 ?>
 
 <html>
+
 <head>
     <script src="plotly-latest.min.js"></script>
     <script src="fmin.min.js"></script>
@@ -32,105 +20,113 @@ $selected_season = substr($selected_csv, 0, -4);
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <link rel="stylesheet" href="main.css">
     <title>Compton interactive plots</title>
-    <!-- <script src="chart.js"></script> -->
 </head>
+
 <body>
 
-<div style="display: flex; align-items: center; flex-wrap: wrap; justify-content: center; margin-top: min(20px,2%); margin-bottom: 40px;">
-    <h2 style="margin: 0;"><a href="index.php" style="font-size: inherit;">Pictures</a> / Season</h2>
-    <form name="form" action="" style="padding: 0 15px; margin: auto 0;" method="get">
-        <select name="csv_file" class="select-css" style="padding: 0.3em 1.3em 0.3em 0.4em;" onchange="this.form.submit()">
-            <?
-            foreach($cleanArrs as $file){
-                ?><option value="<?echo $file?>" <?echo isSelected($file, $selected_csv)?>><?echo substr($file, 0, -4)?></option>
+    <div style="display: flex; align-items: center; flex-wrap: wrap; justify-content: center; margin-top: min(20px,2%); margin-bottom: 40px;">
+        <h2 style="margin: 0;"><a href="./" style="font-size: inherit;">Pictures</a> / Season</h2>
+        <form name="form" action="" style="padding: 0 15px; margin: auto 0;" method="get">
+            <select name="season" class="select-css" style="padding: 0.3em 1.3em 0.3em 0.4em;" onchange="this.form.submit()">
                 <?
-            }
-            ?>
-        </select>
-    </form>
-    <h2 style="margin: 0;">summary</h2>
-</div>
-
-<div style="display: flex; align-items: center; flex-wrap: wrap; justify-content: center;">
-    <div style="max-width: 900px; width: 45%; min-width: min(100%, 600px); margin: 0 max(1%, 10px);">
-        <h3>Mean energy measurements</h3>
-        <div id="mean_energy_plot"></div>
-    </div>
-    <div style="max-width: 900px; width: 45%; min-width: min(100%, 600px); margin: 0 max(1%, 10px);">
-        <h3>Spread measurements</h3>
-        <div id="spread_plot"></div>
-    </div>
-    <div style="max-width: 900px; width: 45%; min-width: min(100%, 600px); margin: 0 max(1%, 10px);">
-        <h3>Mean energy deviations</h3>
-        <div id="energy_dev_plot"></div>
+                foreach ($available_seasons as $season) {
+                ?><option value="<? echo $season ?>" <? echo isSelected($season, $selected_season) ?>><? echo $season ?></option>
+                <?
+                }
+                ?>
+            </select>
+        </form>
+        <h2 style="margin: 0;">summary</h2>
     </div>
-    <div style="max-width: 900px; width: 45%; min-width: min(100%, 600px); margin: 0 max(1%, 10px);">
-        <h3>Impact of mean energy deviations</h3>
-        <div id="impact_energy_dev_plot"></div>
+
+    <div style="display: flex; align-items: center; flex-wrap: wrap; justify-content: center;">
+        <div style="max-width: 900px; width: 45%; min-width: min(100%, 600px); margin: 0 max(1%, 10px);">
+            <h3>Mean energy measurements</h3>
+            <div id="mean_energy_plot"></div>
+        </div>
+        <div style="max-width: 900px; width: 45%; min-width: min(100%, 600px); margin: 0 max(1%, 10px);">
+            <h3>Spread measurements</h3>
+            <div id="spread_plot"></div>
+        </div>
+        <div style="max-width: 900px; width: 45%; min-width: min(100%, 600px); margin: 0 max(1%, 10px);">
+            <h3>Mean energy deviations</h3>
+            <div id="energy_dev_plot"></div>
+        </div>
+        <div style="max-width: 900px; width: 45%; min-width: min(100%, 600px); margin: 0 max(1%, 10px);">
+            <h3>Impact of mean energy deviations</h3>
+            <div id="impact_energy_dev_plot"></div>
+        </div>
     </div>
-</div>
-<div style="margin-top: 40px; width: 100%;">
-    <div style="width: min(100%, 600px); margin: 0 auto;">
-        <h3 style="padding-right: 40px;">Methodology</h3>
-        <p style="font-size: inherit;"><b>Mean energy measurements:</b> a difference between measured mean beam energy and target beam energy vs target beam energy.</p>
-        <p style="font-size: inherit;"><b>Spread measurements:</b> a measured mean beam spread vs measured mean beam energy for the given energy points. A line shows the best fit of these points to a linear function (as a result of chi-square minimization)</p>
-        <p style="font-size: inherit;"><b>Mean energy deviations:</b> a measured mean energy deviations (so-called mean_energy_sys_err) vs measured mean beam energy for the given energy points.</p>
-        <p style="font-size: inherit;"><b>Impact of mean energy deviations:</b> a part of the mean energy deviation in total uncertainty (as d/√(d<sup>2</sup> + s<sup>2</sup>), where d is the mean energy deviation and s is the mean spread) for the given energy points.</p>
+    <div style="margin-top: 40px; width: 100%;">
+        <div style="width: min(100%, 600px); margin: 0 auto; font-size: 2rem;">
+            <h3 style="padding-right: 40px;">Methodology</h3>
+            <p style="font-size: inherit;"><b>Mean energy measurements:</b> a difference between measured mean beam energy and target beam energy vs target beam energy.</p>
+            <p style="font-size: inherit;"><b>Spread measurements:</b> a measured mean beam spread vs measured mean beam energy for the given energy points. A line shows the best fit of these points to a linear function (as a result of chi-square minimization)</p>
+            <p style="font-size: inherit;"><b>Mean energy deviations:</b> a measured mean energy deviations (so-called mean_energy_sys_err) vs measured mean beam energy for the given energy points.</p>
+            <p style="font-size: inherit;"><b>Impact of mean energy deviations:</b> a part of the mean energy deviation in total uncertainty (as d/√(d<sup>2</sup> + s<sup>2</sup>), where d is the mean energy deviation and s is the mean spread) for the given energy points.</p>
+        </div>
     </div>
-</div>
 
-<script>
-        function makeplot(){
-            Plotly.d3.csv('<?echo $url.$selected_csv;?>', (allRows)=>{
-                const {point_name, energy_point, mean_energy, mean_energy_stat_err, mean_energy_sys_err, mean_spread, mean_spread_stat_err} = parseResultsTable(allRows);
+    <script>
+        function makeplot() {
+            Plotly.d3.csv('<? echo $selected_season_url; ?>', (allRows) => {
+                const {
+                    point_name,
+                    energy_point,
+                    mean_energy,
+                    mean_energy_stat_err,
+                    mean_energy_sys_err,
+                    mean_spread,
+                    mean_spread_stat_err
+                } = parseResultsTable(allRows);
                 makeMeanEnergyPlot(energy_point, mean_energy, mean_energy_stat_err, point_name, "mean_energy_plot");
                 makeSpreadPlot(mean_energy, mean_spread, mean_spread_stat_err, point_name, "spread_plot");
                 makeMeanDevPlot(mean_energy, mean_energy_sys_err, point_name, "energy_dev_plot");
                 makeImpactDevPlot(point_name, mean_spread, mean_energy_sys_err, "impact_energy_dev_plot");
-            }
-            );
+            });
         }
-        
-        function parseResultsTable(allRows){
+
+        function parseResultsTable(allRows) {
             // Extracts a row following the energy point in the total csv file (or null if energy point is not exists)
             let data = {};
-            for(let key of Object.keys(allRows[0])){
+            for (let key of Object.keys(allRows[0])) {
                 data[key] = [];
             }
             data['point_name'] = [];
-            
+
             let float_keys = ['energy_point', 'mean_energy', 'mean_energy_stat_err', 'mean_spread', 'mean_spread_stat_err', 'mean_energy_sys_err'];
-            
-            for (var i=0; i<allRows.length; i++){
-                for(let key of Object.keys(allRows[i])){
+
+            for (var i = 0; i < allRows.length; i++) {
+                for (let key of Object.keys(allRows[i])) {
                     let value = allRows[i][key];
-                    if (float_keys.includes(key)){
+                    if (float_keys.includes(key)) {
                         value = parseFloat(value);
                     }
                     data[key].push(value);
                 }
-                data['point_name'].push(allRows[i]['energy_point']+'_'+allRows[i]['first_run']);
+                data['point_name'].push(allRows[i]['energy_point'] + '_' + allRows[i]['first_run']);
             }
             return data;
         }
-        
-        function linear_coeffs(x, y, yerr, remove_outliers=false){
+
+        function linear_coeffs(x, y, yerr, remove_outliers = false) {
             // Returns a chi square minimizer for linear function
-            function chi2min(X){
-                let k = X[0], b = X[1];
+            function chi2min(X) {
+                let k = X[0],
+                    b = X[1];
                 let chi2 = 0;
-                for(let i=0; i<x.length; i++){
-                    if (remove_outliers&&(y[i]<0.06))
+                for (let i = 0; i < x.length; i++) {
+                    if (remove_outliers && (y[i] < 0.06))
                         continue;
-                    y0 = k*x[i] + b;
-                    chi2 += Math.pow((y[i] - y0)/yerr[i], 2);
+                    y0 = k * x[i] + b;
+                    chi2 += Math.pow((y[i] - y0) / yerr[i], 2);
                 }
                 return chi2;
             }
             return chi2min;
         }
-        
-        function getPlotlyDefaults(){
+
+        function getPlotlyDefaults() {
             var layout = {
                 margin: {
                     l: 50,
@@ -166,19 +162,20 @@ $selected_season = substr($selected_csv, 0, -4);
             var config = {
                 toImageButtonOptions: {
                     format: 'png', // one of png, svg, jpeg, webp
-                    filename: 'spread_plot_<?echo $selected_season;?>',
+                    filename: 'spread_plot_<? echo $selected_season; ?>',
                     scale: 4,
-                  },
+                },
                 responsive: true,
                 modeBarButtonsToRemove: ['select2d', 'lasso2d', 'zoomIn2d', 'zoomOut2d', 'resetScale2d', 'hoverClosestGl2d', 'hoverClosestPie', 'toggleHover', 'toggleSpikelines'],
                 displayModeBar: true,
             };
             return {
-                "layout" : layout, "config" : config,
+                "layout": layout,
+                "config": config,
             };
         }
-        
-        function makeMeanEnergyPlot(energy_point, mean_energy, mean_energy_stat_err, texts, elementId){
+
+        function makeMeanEnergyPlot(energy_point, mean_energy, mean_energy_stat_err, texts, elementId) {
             // Plots mean energy - target energy vs target energy
             var energy_diff = [];
             Plotly.d3.zip(mean_energy, energy_point).forEach(e => energy_diff.push(e[0] - e[1]));
@@ -203,16 +200,19 @@ $selected_season = substr($selected_csv, 0, -4);
                 type: "scatter",
             };
             var traces = [trace1];
-            
-            var {layout, config} = getPlotlyDefaults();
+
+            var {
+                layout,
+                config
+            } = getPlotlyDefaults();
             layout.xaxis.title = "Target energy, MeV";
             layout.yaxis.title = "Mean energy - Target energy, MeV";
-            
+
             Plotly.newPlot(elementId, traces, layout, config);
-            
+
         }
-        
-        function makeMeanDevPlot(mean_energy, mean_energy_sys_err, texts, elementId){
+
+        function makeMeanDevPlot(mean_energy, mean_energy_sys_err, texts, elementId) {
             // Plots mean energy deviations vs mean measured energy
             var trace1 = {
                 x: mean_energy,
@@ -227,19 +227,22 @@ $selected_season = substr($selected_csv, 0, -4);
                 showlegend: false,
             };
             var traces = [trace1];
-            
-            var {layout, config} = getPlotlyDefaults()
-            
+
+            var {
+                layout,
+                config
+            } = getPlotlyDefaults()
+
             layout.yaxis.title = "Mean energy deviation, MeV";
             Plotly.newPlot(elementId, traces, layout, config);
-            
+
         }
-        
-        function makeSpreadPlot(mean_energy, mean_spread, mean_spread_stat_err, texts, elementId){
+
+        function makeSpreadPlot(mean_energy, mean_spread, mean_spread_stat_err, texts, elementId) {
             // Plots spreads vs mean measured energy
             var chi2min = linear_coeffs(mean_energy, mean_spread, mean_spread_stat_err, true);
-            var solution = fmin.nelderMead(chi2min, [0.001, 0]);       
-            
+            var solution = fmin.nelderMead(chi2min, [0.001, 0]);
+
             var trace1 = {
                 x: mean_energy,
                 y: mean_spread,
@@ -261,45 +264,52 @@ $selected_season = substr($selected_csv, 0, -4);
             };
             var trace2 = {
                 x: [Plotly.d3.min(mean_energy), Plotly.d3.max(mean_energy)],
-                y: [solution.x[0]*Plotly.d3.min(mean_energy) + solution.x[1], solution.x[0]*Plotly.d3.max(mean_energy) + solution.x[1]],
+                y: [solution.x[0] * Plotly.d3.min(mean_energy) + solution.x[1], solution.x[0] * Plotly.d3.max(mean_energy) + solution.x[1]],
                 mode: 'lines',
-                name: 'Fit: y = ' + Math.round(parseFloat(solution.x[0])*1e5)/1e5 + 'x ' + (Math.sign(solution.x[1])>0 ? "+" : "") + Math.round(solution.x[1]*1e3)/1e3,
+                name: 'Fit: y = ' + Math.round(parseFloat(solution.x[0]) * 1e5) / 1e5 + 'x ' + (Math.sign(solution.x[1]) > 0 ? "+" : "") + Math.round(solution.x[1] * 1e3) / 1e3,
                 hovermode: false,
                 hoverinfo: 'none',
             };
             var traces = [trace1, trace2];
-            
-            var {layout, config} = getPlotlyDefaults()
-            
+
+            var {
+                layout,
+                config
+            } = getPlotlyDefaults()
+
             Plotly.newPlot(elementId, traces, layout, config);
-            
+
         }
-        
-        function makeImpactDevPlot(point_name, mean_spread, mean_energy_sys_err, elementId){
+
+        function makeImpactDevPlot(point_name, mean_spread, mean_energy_sys_err, elementId) {
             let arr = Plotly.d3.zip(mean_spread, mean_energy_sys_err);
             let impact_factor = [];
-            arr.forEach(e => impact_factor.push(e[1]/Math.pow(e[0]**2+e[1]**2, 0.5)));
+            arr.forEach(e => impact_factor.push(e[1] / Math.pow(e[0] ** 2 + e[1] ** 2, 0.5)));
             var data = [{
                 type: 'bar',
                 x: impact_factor,
                 y: point_name,
                 orientation: 'h',
                 showlegend: false,
-                text: impact_factor.map(e => String(Math.round(e*1e2)) + '%'),
+                text: impact_factor.map(e => String(Math.round(e * 1e2)) + '%'),
                 textposition: 'auto',
                 hovertemplate: "Point: %{y}<br>Impact of %{text} <extra></extra>",
                 //hoverinfo: 'none',
             }];
-        
-            var {layout, config} = getPlotlyDefaults();
+
+            var {
+                layout,
+                config
+            } = getPlotlyDefaults();
             layout.xaxis.range = [0, 1];
             layout.yaxis.title = "";
             layout.xaxis.title = "Impact of mean energy deviations";
             Plotly.newPlot(elementId, data, layout, config);
         }
-        
+
         makeplot();
-</script>
+    </script>
 
 </body>
-</html>
+
+</html>

+ 2 - 2
src/scripts/compton_runs_script.sh

@@ -17,8 +17,8 @@ Sync repositories
 git -C $SOURCE_FOLDER checkout $SOURCE_BRANCH
 git -C $SOURCE_FOLDER pull origin $SOURCE_BRANCH
 
-git -C $TABLES_FOLDER checkout $SOURCE_BRANCH
-git -C $TABLES_FOLDER pull origin $SOURCE_BRANCH
+git -C $TABLES_FOLDER checkout $TABLES_BRANCH
+git -C $TABLES_FOLDER pull origin $TABLES_BRANCH
 
 # Update averaging
 source $VENV