5 Commits fe6be1f132 ... 267f574c60

Auteur SHA1 Bericht Datum
  JustDreamer7 267f574c60 add .env_example, ReadMe.md, requirements.txt 1 jaar geleden
  JustDreamer7 58cf86734b add mask_db_delete.py, amp_mask_db_writer.py, 2 jaren geleden
  JustDreamer7 3641ae56c2 add json parsing to db_file_reader.py, 2 jaren geleden
  JustDreamer7 4dc05818e8 refactoring file_reader.py, db_file_reader.py, noSQL_db_Prisma.py, add docstrings 2 jaren geleden
  JustDreamer7 4f6651939d db_file_reader.py data_cl['Date'] changed 2 jaren geleden

+ 1 - 0
.env_example

@@ -0,0 +1 @@
+DB_URL=

+ 13 - 0
ReadMe.md

@@ -0,0 +1,13 @@
+noSQL DataBase for PRISMA-32
+----------
+
+
+1. noSQL DataBase for PRISMA-32
+2. **Author:** Andrew Pochestnev
+3. **Version:** 1.0.0
+4. **Instruction:** 
+   - create new directory
+   - clone the repository to new directory 
+   - create python virtualenv
+   - install all site-packages - ```pip install -r requirements.txt``` 
+   - change name of .env_example to .env

+ 73 - 20
file_reader/db_file_reader.py

@@ -1,18 +1,25 @@
 import datetime
+import time
 from collections import defaultdict
-from file_reader.file_reader import FileReader
 
 import pandas as pd
 import pymongo
 
 
-class DbFileReader(FileReader):
+# from file_reader.file_reader import FileReader
+
+
+class DbFileReader:
+    """Класс для чтения данных ПРИЗМА-32 из MongoDB базы данных, должен быть один для
+    всех модулей"""
     # __DB_URL = "mongodb://localhost:27017/"
     __amp_n_cols = []
     for i in range(1, 17):
         __amp_n_cols.append(f'amp{i}')
         __amp_n_cols.append(f'n{i}')
 
+    __slots__ = ["__db_url", "cluster", "single_date"]
+
     def __init__(self, cluster, single_date, db_url):
         self.cluster = cluster
         self.single_date = single_date
@@ -22,7 +29,7 @@ class DbFileReader(FileReader):
         """Метод, прочитывающий noSQL БД ПРИЗМА-32 с помощью DB_URL"""
 
         data_cl = pd.DataFrame.from_records(
-            pymongo.MongoClient(self.__db_url)["prisma-32_db"][f'{str(self.single_date)}_12d'].find(
+            pymongo.MongoClient(self.__db_url)["prisma-32_db"][f'{str(self.single_date.date())}_12d'].find(
                 {'cluster': self.cluster}))
         if data_cl.empty:
             raise FileNotFoundError
@@ -37,35 +44,81 @@ class DbFileReader(FileReader):
             data_cl[f'amp{i}'] = amp_dict[f'det_{i:02}']
             data_cl[f'n{i}'] = n_dict[f'det_{i:02}']
         data_cl['time'] = [round(item / 1e9, 2) for item in data_cl['time_ns']]
-        data_cl['Date'] = [datetime.date(item[0:3], item[5:6], item[8:9]) for item in data_cl['time_ns']]
-
+        data_cl['Date'] = [datetime.date(int(item[0:4]), int(item[5:7]), int(item[8:10])) for item in data_cl['_id']]
+        # t1 = time.time_ns()
+        # data_cl_normalize = pd.json_normalize(data_cl['detectors']) # Медленнее, чем фиговый вложенный цикл
+        # data_cl_normalize.columns = self.__class__.__amp_n_cols   # c условиями (parsing_db)
+        # data_cl = pd.concat([data_cl, data_cl_normalize], axis=1)
+        data_cl = DbFileReader.parsing_db(data_cl,
+                                          amp_dict=True,
+                                          # Комментарий, amp_dict - переменная, которая требует амплитуды
+                                          n_dict=True,
+                                          n_time_delay=False)  # Парсим данные из БД
+        # print(f'parsing_db - {(time.time_ns() - t1) / 1e9}')
         return data_cl
 
     def concat_n_data(self, concat_n_df):
-        data_cl = self.reading_db
+        """Статический метод соединения датафреймов файлов,
+        полученных на выходе в один с добавления колонки с датой"""
+        data_cl = self.reading_db()
         # noinspection PyUnresolvedReferences
         concat_n_df = pd.concat([concat_n_df, data_cl[['Date', 'time', 'trigger'] + self.__class__.__amp_n_cols]],
                                 ignore_index=True)
         return concat_n_df
 
     @staticmethod
-    def db_preparing_data(start_date, end_date, path_to_db):
-        concat_n_df_1 = pd.DataFrame(columns=['Date', 'time', 'trigger'] + DbFileReader.__amp_n_cols)
-        concat_n_df_2 = pd.DataFrame(columns=['Date', 'time', 'trigger'] + DbFileReader.__amp_n_cols)
+    def parsing_db(data_cl, amp_dict=False, n_dict=False, n_time_delay=False):  # Парсинг n_time_delay не сильно
+        amp_dict = defaultdict(list) if amp_dict else False  # Замедляет работу программы, так что можно оставить
+        n_dict = defaultdict(list) if n_dict else False  # Все true
+        n_time_delay = defaultdict(list) if n_time_delay else False
+        for item in data_cl['detectors']:
+            for j in [f'det_{i:02}' for i in range(1, 17)]:
+                if type(amp_dict) is not bool:
+                    amp_dict[j].append(item[j]['amplitude'])
+                if type(n_dict) is not bool:
+                    n_dict[j].append(item[j]['neutrons'])
+                if type(n_time_delay) is not bool:
+                    n_time_delay[j].append(item[j]['time_delay'])
+
+        for i in range(1, 17):
+            if amp_dict:
+                data_cl[f'amp{i}'] = amp_dict[f'det_{i:02}']
+            if n_dict:
+                data_cl[f'n{i}'] = n_dict[f'det_{i:02}']
+            if n_time_delay:
+                data_cl[f'n_time_delay{i}'] = n_time_delay[f'det_{i:02}']
+        return data_cl
+
+    @staticmethod
+    def db_preparing_data(start_date, end_date, path_to_db, cluster):
+        """Статический метод подготовки информации для обработки из
+        базы данных ПРИЗМА-32 за определенный
+        период для определенного кластера"""
+        concat_n_df = pd.DataFrame(columns=['Date', 'time', 'trigger'] + DbFileReader.__amp_n_cols)
         for single_date in pd.date_range(start_date, end_date):
             try:
-                db_file_reader_1 = DbFileReader(cluster=1, single_date=single_date, db_url=path_to_db)
-                concat_n_df_1 = db_file_reader_1.concat_n_data(concat_n_df=concat_n_df_1)
-            except FileNotFoundError:
-                print(
-                    f"File n_{single_date.month:02}-" +
-                    f"{single_date.day:02}.{single_date.year - 2000:02}', does not exist")
-            try:
-                db_file_reader_1 = DbFileReader(cluster=2, single_date=single_date, db_url=path_to_db)
-                concat_n_df_2 = db_file_reader_1.concat_n_data(concat_n_df=concat_n_df_2)
+                db_file_reader = DbFileReader(cluster=cluster, single_date=single_date, db_url=path_to_db)
+                concat_n_df = db_file_reader.concat_n_data(concat_n_df=concat_n_df)
             except FileNotFoundError:
                 print(
-                    f"File 2n_{single_date.month:02}-" +
+                    f"File {cluster}n_{single_date.month:02}-" +
                     f"{single_date.day:02}.{single_date.year - 2000:02}', does not exist")
+                # Переделать n на коллекцию из БД
+        return concat_n_df
+
 
-        return concat_n_df_1, concat_n_df_2
+if __name__ == '__main__':
+    date_time_start = datetime.date(2018, 1, 1)  # посмотреть почему не собирается конец дня 2018-04-22
+    date_time_stop = datetime.date(2018, 12, 31)
+    t1 = time.time_ns()
+    for single_date in pd.date_range(date_time_start, date_time_stop):
+        try:
+            t2 = time.time_ns()
+            test = DbFileReader(cluster=1, single_date=single_date, db_url="mongodb://localhost:27017/")
+            test.reading_db()
+            print(f'time - {(time.time_ns() - t2) / 1e9}')
+        except FileNotFoundError:
+            print(
+                f"File n_{single_date.month:02}-" +
+                f"{single_date.day:02}.{single_date.year - 2000:02}', does not exist")
+    print(f'time - {(time.time_ns() - t1) / 1e9}')

+ 104 - 78
file_reader/file_reader.py

@@ -1,16 +1,22 @@
 import datetime
-import pandas as pd
-
+import pathlib
 
-# from pathlib import Path
+import pandas as pd
 
 
 class FileReader:
+    """Класс для чтения файлов ПРИЗМА-32, должен быть общим во всех модулях разработки"""
+
     __amp_n_cols = []
     for i in range(1, 17):
         __amp_n_cols.append(f'amp{i}')
         __amp_n_cols.append(f'n{i}')
 
+    __slots__ = ["cluster", "cluster_n", 'path_to_files', 'single_date']
+
+    # Для оптимизации вызова экземпляра класса, так как вызывается экземпляр на каждый день
+    # работы установки.
+
     def __init__(self, cluster, single_date, path_to_files=''):
         self.cluster = cluster
         if cluster == 1:
@@ -19,28 +25,26 @@ class FileReader:
             self.cluster_n = '2'
         self.path_to_files = path_to_files
         self.single_date = single_date
-        self.n_file_path = self.making_file_path(file_type='n')
-        self.n7_file_path = self.making_file_path(file_type='n7')
-        self.t_file_path = self.making_file_path(file_type='t')
-        self.p_file_path = self.making_file_path_eas_p(file_directory='nv', file_type='p')
-        self.eas_file_path = self.making_file_path_eas_p(file_directory='EAS', file_type='eas')
 
-    def __del__(self):
-        pass
+        # self.eas_file_path = self.making_file_path(file_directory='EAS', file_type='eas')
+        # Понадобится, когда добавим eas-файлы
 
-    def making_file_path(self, file_type):
-        file_path = f'{self.path_to_files}\\{file_type}\\{self.cluster_n}{file_type}_{self.single_date.month:02}-{self.single_date.day:02}.{self.single_date.year - 2000:02}'
-        return file_path
-
-    def making_file_path_eas_p(self, file_directory, file_type):
-        file_path = f'{self.path_to_files}/{file_directory}/{self.cluster}{file_type}_{self.single_date.month:02}-{self.single_date.day:02}.{self.single_date.year - 2000:02}'
+    def making_file_path(self, file_type, file_directory=None):
+        """Функция для построения путей для различных типов файлов ПРИЗМА-32"""
+        file_directory = file_type if file_directory is None else file_directory
+        file_name = self.cluster_n + \
+                    f'{file_type}_{self.single_date.month:02}-' + \
+                    f'{self.single_date.day:02}.{self.single_date.year - 2000:02}'
+        file_path = pathlib.PurePath(self.path_to_files, file_directory, file_name)
         return file_path
 
     def reading_n_file(self):
-        """Метод, прочитывающий n-файлы, возвращающий датафрейм дня на выходе. Или возвращающий filenotfounderror, если
-                файла нет"""
-        print(self.n_file_path)
-        n_file = pd.read_csv(self.n_file_path,
+        """Метод, прочитывающий n-файлы. Делит файл на два датафрейма, если в файле присутствуют
+         события следующего дня и возвращает их на выходе. Если в файле нет события следующего дня,
+         то возвращает один датафрейм и пустую строку"""
+        n_file_path = self.making_file_path(file_type='n')
+        print(n_file_path)
+        n_file = pd.read_csv(n_file_path,
                              sep=r'\s[-]*\s*', header=None, skipinitialspace=True, index_col=False, engine='python')
         n_file.dropna(axis=1, how='all', inplace=True)
         n_file.columns = ['time', 'number', 'sum_n', 'trigger'] + self.__class__.__amp_n_cols
@@ -54,16 +58,21 @@ class FileReader:
         return n_file, []
 
     def reading_n7_file(self):
-        print(self.n7_file_path)
+        """Метод, прочитывающий n7-файлы. При ошибке формата файла ValueError(надо указать какой, кстати) запускает
+        функцию конвертера n7-файлов. После успешного прочтения делит файл на два датафрейма, если в файле присутствуют
+        события следующего дня и возвращает их на выходе. Если в файле нет события следующего дня, то возвращает один
+        датафрейм и пустую строку"""
+        n7_file_path = self.making_file_path(file_type='n7')
+        print(n7_file_path)
         try:
-            n7_file = pd.read_csv(self.n7_file_path,
+            n7_file = pd.read_csv(n7_file_path,
                                   sep=r'\s[-]*\s*', header=None, skipinitialspace=True, index_col=False,
                                   engine='python')
             n7_file.dropna(axis=1, how='all', inplace=True)
             n7_file.columns = ['time', 'number', 'trigger'] + [f'amp{i}' for i in range(1, 17)]
-        except ValueError:
-            self.n7_file_conventer()
-            n7_file = pd.read_csv(self.n7_file_path,
+        except ValueError:  # указать, что за ValueError
+            self.n7_file_conventer(n7_file_path)
+            n7_file = pd.read_csv(n7_file_path,
                                   sep=r'\s[-]*\s*', header=None, skipinitialspace=True, index_col=False,
                                   engine='python')
             n7_file.dropna(axis=1, how='all', inplace=True)
@@ -77,52 +86,52 @@ class FileReader:
             n7_file_today = n7_file[n7_file.index < bad_end_time_index[0]]
             n7_file_day_after = n7_file[n7_file.index >= bad_end_time_index[0]]
             return n7_file_today, n7_file_day_after
-
         return n7_file, []
 
     @staticmethod
-    def concat_data(file_today, file_day_after, single_date, concat_n_df):
-        file_today['Date'] = [single_date.date()] * len(file_today.index)
-        concat_n_df = pd.concat([concat_n_df, file_today], ignore_index=True)
-        if any(file_day_after):
-            file_day_after['Date'] = [(single_date + datetime.timedelta(
-                days=1)).date()] * len(file_day_after.index)
-            concat_n_df = pd.concat([concat_n_df, file_day_after],
-                                    ignore_index=True)
-        return concat_n_df
+    def n7_file_conventer(n7_file_path):
+        """Статический метод конвентера для n7-файлов, если в них амплитуды записываются не на одной строчке с
+        событием"""
+        with open(n7_file_path, 'r', encoding='utf-8') as n7_file_read:
+            raw_data = n7_file_read.readlines()
+        if len(list(filter(lambda x: x != '', raw_data[0].rstrip().split(' ')))) < 5:
+            start_of_strings = [line.rstrip() for line in raw_data[::2]]
+            end_of_strings = raw_data[1::2]
+            raw_data = [x + ' ' + y for x, y in zip(start_of_strings, end_of_strings)]
+            with open(n7_file_path, 'w', encoding='utf-8') as n7_file_write:
+                n7_file_write.writelines(raw_data)
+        else:
+            raise FileNotFoundError
+
+    def t_file_conventer(self):
+        """Конвентер для t-файлов ПРИЗМА-32, возвращает датафрейм t-файла,
+         с которым сделать merge датафрейма n-файла"""
+        t_file_path = self.making_file_path(file_type='t')
 
-    def reading_t_file(self):
-        """Converter for PRISMA t-files"""
-        with open(self.t_file_path) as f:
-            raw_data = f.readlines()
-        raw_data = [line.rstrip() for line in raw_data]
-        # Убираем переводы строки
-        event_list = []
-        main_list = []
+        def reading_t_file(t_path):
+            """Генератор для чтения t-файлов"""
+            with open(t_path, encoding='utf-8') as file:
+                for file_line in file.readlines():
+                    yield file_line.rstrip()
+
+        raw_data = list(reading_t_file(t_path=t_file_path))
+        event_list, main_list = [], []
         sep = 0
-        for i in range(len(raw_data)):
+        for i, _ in enumerate(raw_data):
             if raw_data[i] == '*#*':
                 main_list.append(raw_data[sep].split(' '))
                 event_list.append(raw_data[sep + 1:i])
                 sep = i + 1
-        unit_delay = []
+        plural_data_list = []
         for item in event_list:
-            delay_per_event = []
+            time_list, detector_list, neut_quantity_list = [], [], []
             for line in item:
                 step = line.split(' ')
                 for i in range(1, 17):
                     if int(step[i]) != 0:
-                        delay_per_event.append([round(int(step[0]) * (10 ** (-4)), 4), i, int(step[i])])
-            unit_delay.append(delay_per_event)
-        plural_data_list = []
-        for i in unit_delay:
-            time_list = []
-            detector_list = []
-            neut_quantity_list = []
-            for j in i:
-                time_list.append(j[0])
-                detector_list.append(j[1])
-                neut_quantity_list.append(j[2])
+                        time_list.append(round(int(step[0]) * (10 ** (-4)), 4))
+                        detector_list.append(i)
+                        neut_quantity_list.append(int(step[i]))
             plural_data_list.append([time_list, detector_list, neut_quantity_list])
         for i in range(len(main_list)):
             main_list[i].extend(plural_data_list[i])
@@ -133,22 +142,10 @@ class FileReader:
         t_file_df = t_file_df[t_file_df["time"] < 86400]
         return t_file_df
 
-    def n7_file_conventer(self):
-        with open(self.n7_file_path, 'r') as f:
-            raw_data = f.readlines()
-        if len(list(filter(lambda x: x != '', raw_data[0].rstrip().split(' ')))) < 5:
-            start_of_strings = [line.rstrip() for line in raw_data[::2]]
-            end_of_strings = raw_data[1::2]
-            raw_data = [x + ' ' + y for x, y in zip(start_of_strings, end_of_strings)]
-            with open(self.n7_file_path, 'w') as f:
-                f.writelines(raw_data)
-        else:
-            raise FileNotFoundError
-
     def reading_p_file(self):
-        """Метод, прочитывающий p-файлы, возвращающий датафрейм дня на выходе. Или возвращающий filenotfounderror, если
-        файла нет"""
-        p_file = pd.read_csv(self.p_file_path,
+        """Метод, прочитывающий p-файлы, возвращающий датафрейм дня на выходе."""
+        p_file_path = self.making_file_path(file_directory='nv', file_type='p')
+        p_file = pd.read_csv(p_file_path,
                              sep=r'\s[-]*\s*', header=None, skipinitialspace=True, engine='python')
         p_file.dropna(axis=1, how='all', inplace=True)
         corr_p_file = self.correcting_p_file(p_file)
@@ -164,10 +161,10 @@ class FileReader:
         p_file = p_file.sort_values(by='time')
         if len(p_file['time']) > len(p_file['time'].unique()):
             p_file.drop_duplicates(keep=False, inplace=True)
-            """После удаления полных дубликатов ищем повторяющиеся индексы. Сначала удаляем строки, 
-            состоящие полностью из нулей и точек (value = len(p_file.columns)), потом ищем множество 
-            дубликатов индексов и множество строк, почти полностью (value > 30) состоящих из нулей и точек. 
-            Берем пересечение этих двух множеств и удаляем находящиеся в пересечении строки"""
+            # После удаления полных дубликатов ищем повторяющиеся индексы. Сначала удаляем строки,
+            # состоящие полностью из нулей и точек (value = len(p_file.columns)), потом ищем множество
+            # дубликатов индексов и множество строк, почти полностью (value > 30) состоящих из нулей и точек.
+            # Берем пересечение этих двух множеств и удаляем находящиеся в пересечении строки
             null_row = dict(p_file.isin([0, '.']).sum(axis=1))  # Проверяем на нули и точки
             all_null_index = list(
                 {key: value for key, value in null_row.items() if value == len(p_file.columns)}.keys())
@@ -179,8 +176,37 @@ class FileReader:
             same_index_row = list({key: value for key, value in same_index.items() if value is True}.keys())
             bad_index = list(set(null_index) & set(same_index_row))
             p_file.drop(index=bad_index, inplace=True)
-            """Также может быть, что после фильтрации осталось больше строк, чем нужно, так как в старых 
-            p-файлах может быть больше индексов, чем минут в дне. Тогда оставляем только 288"""
+            # Также может быть, что после фильтрации осталось больше строк, чем нужно, так как в старых
+            # p-файлах может быть больше индексов, чем минут в дне. Тогда оставляем только 288
             if len(p_file.index) == 289:
                 p_file = p_file.head(288)
         return p_file
+
+    @staticmethod
+    def concat_data(file_today, file_day_after, single_date, concat_n_df):
+        """Статический метод соединения датафреймов файлов, полученных на выходе в один с добавления колонки с датой"""
+        file_today['Date'] = [single_date.date()] * len(file_today.index)
+        concat_n_df = pd.concat([concat_n_df, file_today], ignore_index=True)
+        if any(file_day_after):  # не пропускает пустую строку
+            file_day_after['Date'] = [(single_date + datetime.timedelta(
+                days=1)).date()] * len(file_day_after.index)
+            concat_n_df = pd.concat([concat_n_df, file_day_after], ignore_index=True)
+        return concat_n_df
+
+    @staticmethod
+    def preparing_data(start_date, end_date, cluster, path_to_files):
+        """Статический метод подготовки данных из n-файлов за определенный период для определенного кластера"""
+        concat_n_df = pd.DataFrame(columns=['Date', 'time', 'trigger'] + FileReader.__amp_n_cols)
+        for single_date in pd.date_range(start_date - datetime.timedelta(days=1), end_date):
+            # минус один день в timedelta, так как начальные события первого дня могут остаться в n-файле предыдущего
+            # дня
+            try:
+                n_file_reader = FileReader(cluster=cluster, single_date=single_date, path_to_files=path_to_files)
+                n_file_today, n_file_day_after = n_file_reader.reading_n_file()
+                concat_n_df = n_file_reader.concat_data(file_today=n_file_today, file_day_after=n_file_day_after,
+                                                        concat_n_df=concat_n_df, single_date=single_date)
+            except FileNotFoundError:
+                print(
+                    f"File {path_to_files}/n_{single_date.month:02}-" +
+                    f"{single_date.day:02}.{single_date.year - 2000:02}', does not exist")
+        return concat_n_df

+ 0 - 0
logger/__init__.py


+ 12 - 0
logger/logger.py

@@ -0,0 +1,12 @@
+import logging
+
+
+class Logger:
+
+    def __init__(self):
+        self.logger = logging.getLogger("exampleApp")
+        self.logger.setLevel(logging.INFO)
+        fh = logging.FileHandler('logs/info.log')
+        fh.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
+        self.logger.addHandler(fh)
+        self.logger.info("Program started")

+ 0 - 0
masks/__init__.py


+ 38 - 0
masks/amp_mask_db_writer.py

@@ -0,0 +1,38 @@
+import datetime
+import time
+
+import pandas as pd
+
+# import numpy as np
+import pymongo
+
+from config_info.config import DB_URL
+
+# from file_reader.db_file_reader import DbFileReader
+
+db_client = pymongo.MongoClient(DB_URL)
+prisma_db = db_client["prisma-32_db"]
+
+
+def amp_mask_db_writer(cluster, start_date, end_date, path_to_mask):
+    """Запись из excel файла данных амплитудной маски в БД, за указанный промежуток времени."""
+    # Кажется нужно указать только год и месяц, который мы хотим записать в БД из excel.
+    mask_amp = pd.read_excel(f'{path_to_mask}\\{cluster}cl_amp_mask_{start_date.year}.xlsx',
+                             sheet_name=f'{start_date.year}-{start_date.month:02}')
+    for i in mask_amp.index:
+        daily_mask_data = mask_amp[[f"amp{i}_mask" for i in range(1, 17)]].iloc[0, :].tolist()
+        collection_prisma = prisma_db[f'{str(mask_amp["date"][i].date())}_12d']
+        upd_result = collection_prisma.update_many({'cluster': cluster},
+                                                   {"$set": {
+                                                       f'mask_of_hit_counters_amp': int(
+                                                           ''.join(map(lambda x: str(x), daily_mask_data)), 2),
+                                                       f'multiplicity_of_hit_counters_amp': sum(daily_mask_data)}})
+        print(f'Matched documents amp_mask_{cluster} - {upd_result.matched_count}')
+        print(f'Modified documents amp_mask_{cluster} - {upd_result.modified_count}')
+
+
+if __name__ == "__main__":
+    t1 = time.time_ns()
+    amp_mask_db_writer(cluster=1, start_date=datetime.date(2021, 1, 1), end_date=datetime.date(2021, 1, 31),
+                       path_to_mask="C:\\Users\\pad_z\\OneDrive\\Рабочий стол\\PrismaPassport\\amp_mask")
+    print(f'time - {(time.time_ns() - t1) / 1e9}')

+ 28 - 0
masks/amp_mask_template_creator.py

@@ -0,0 +1,28 @@
+import datetime
+import time
+
+import pandas as pd
+import numpy as np
+
+
+def amp_mask_template_creator(cluster, year, path_to_mask):
+    """Создание excel файла за год, в котором прописывается шаблон амплитудной маски."""
+    with pd.ExcelWriter(f'{path_to_mask}\\{cluster}cl_amp_mask_{year}.xlsx') as writer:
+        for period in pd.period_range(start=datetime.date(year, 1, 1), end=datetime.date(year, 12, 31), freq='M'):
+            start_month = datetime.date(period.year, period.month, 1)
+            end_month = datetime.date(period.year + int(period.month / 12), ((period.month % 12) + 1),
+                                      1) - datetime.timedelta(days=1)
+            daterange = [single_date.date() for single_date in pd.date_range(start_month, end_month)]
+            amp_template = np.ones((len(daterange), 16))
+            mask_amp = pd.DataFrame(amp_template.astype(int),
+                                    columns=[f'amp{i}_mask' for i in range(1, 17)])
+            mask_amp['date'] = daterange
+            mask_amp = mask_amp[['date'] + [f'amp{i}_mask' for i in range(1, 17)]]
+            mask_amp.to_excel(writer, sheet_name=str(period), index=False)
+
+
+if __name__ == "__main__":
+    t1 = time.time_ns()
+    amp_mask_template_creator(cluster=1, year=2022,
+                              path_to_mask="C:\\Users\\pad_z\\OneDrive\\Рабочий стол\\PrismaPassport\\amp_mask")
+    print(f'time - {(time.time_ns() - t1) / 1e9}')

+ 39 - 0
masks/mask_db_delete.py

@@ -0,0 +1,39 @@
+import datetime
+import time
+
+import pandas as pd
+
+# import numpy as np
+import pymongo
+
+from config_info.config import DB_URL
+
+# from file_reader.db_file_reader import DbFileReader
+
+db_client = pymongo.MongoClient(DB_URL)
+prisma_db = db_client["prisma-32_db"]
+
+
+def mask_db_delete(cluster, start_date, end_date, mask_type):
+    """Удаление данных нейтронной или амплитудной маски, за выделенный промежуток времени."""
+    for single_date in pd.date_range(start_date, end_date):
+        collection_prisma = prisma_db[f'{str(single_date.date())}_12d']
+        upd_result = collection_prisma.update_many({'cluster': cluster},
+                                                   {"$unset": {
+                                                       f'mask_of_hit_counters_{mask_type}': "",
+                                                       f'multiplicity_of_hit_counters_{mask_type}': ""}})
+        print(f'Matched documents {mask_type}_mask_{cluster} - {upd_result.matched_count}')
+        print(f'Modified documents {mask_type}_mask_{cluster} - {upd_result.modified_count}')
+
+
+if __name__ == "__main__":
+    t1 = time.time_ns()
+    mask_db_delete(cluster=1, start_date=datetime.date(2012, 1, 1), end_date=datetime.date(2021, 1, 31),
+                   mask_type='amp')
+    mask_db_delete(cluster=2, start_date=datetime.date(2012, 1, 1), end_date=datetime.date(2021, 1, 31),
+                   mask_type='amp')
+    mask_db_delete(cluster=1, start_date=datetime.date(2012, 1, 1), end_date=datetime.date(2021, 1, 31),
+                   mask_type='n')
+    mask_db_delete(cluster=2, start_date=datetime.date(2012, 1, 1), end_date=datetime.date(2021, 1, 31),
+                   mask_type='n')
+    print(f'time - {(time.time_ns() - t1) / 1e9}')

+ 34 - 0
masks/neutron_mask_db_writer.py

@@ -0,0 +1,34 @@
+import datetime
+import time
+
+import pandas as pd
+import pymongo
+
+from processing_data_prisma import ProccessingPrismaCl
+from file_reader.db_file_reader import DbFileReader
+
+
+def neutron_mask_db_writer(cluster, start_date, end_date, path_to_db):
+    """Запись нейтронной маски в БД по критерию >0.1 за день."""
+    for single_date in pd.date_range(start_date, end_date):
+        db_file_reader = DbFileReader(cluster=cluster, single_date=single_date, db_url=path_to_db)
+        data_cl = db_file_reader.reading_db()
+        neutron_to_zero_trigger = ProccessingPrismaCl._neutron_to_zero_trigger(n_file=data_cl)
+        n_mask_params = [int(val) for val in list(map(lambda x: x < 0.1, neutron_to_zero_trigger))]  # Посмотреть
+        # в каком порядке парсится маска нейтронов, то есть от 1-го до 16-го, или от 16-го до 1-го.
+        daily_binary_n_mask = {
+            'mask_of_hit_counters_n': int(''.join([str(val) for val in n_mask_params]), 2),
+            'multiplicity_of_hit_counters_n': sum(n_mask_params)}
+        collection_prisma = pymongo.MongoClient(path_to_db)["prisma-32_db"][f'{str(single_date.date())}_12d']
+        upd_n_result = collection_prisma.update_many({'cluster': cluster}, {"$set": daily_binary_n_mask})
+        print(f'Matched documents n_mask_{cluster} - {upd_n_result.matched_count}')
+        print(f'Modified documents n_mask_{cluster} - {upd_n_result.modified_count}')
+
+
+if __name__ == "__main__":
+    t1 = time.time_ns()
+    neutron_mask_db_writer(cluster=1, start_date=datetime.date(2018, 2, 1), end_date=datetime.date(2018, 3, 31),
+                           path_to_db="mongodb://localhost:27017/")
+    neutron_mask_db_writer(cluster=2, start_date=datetime.date(2018, 2, 1), end_date=datetime.date(2018, 3, 31),
+                           path_to_db="mongodb://localhost:27017/")
+    print(f'time - {(time.time_ns() - t1) / 1e9}')

+ 127 - 0
masks/processing_data_prisma.py

@@ -0,0 +1,127 @@
+# import datetime
+
+from collections import defaultdict
+
+import pandas as pd
+
+
+class ProccessingPrismaCl:
+    def __init__(self, n_data):
+        self.n_data = n_data
+
+    def period_processing_for_report(self, start_date, end_date):
+        worktime_dict = defaultdict(list)
+        n_vs_zero_tr_dict = defaultdict(list)
+        event_counter_fr_4 = defaultdict(list)
+        breaks_dict = defaultdict(list)
+        count_rate_amp_5_fr_2 = defaultdict(list)
+        count_rate_amp_10_fr_1 = defaultdict(list)
+
+        for single_date in pd.date_range(start_date, end_date):
+            worktime_dict['Date'].append(single_date)
+            n_vs_zero_tr_dict['Date'].append(single_date)
+            count_rate_amp_5_fr_2['Date'].append(single_date)
+            count_rate_amp_10_fr_1['Date'].append(single_date)
+            event_counter_fr_4['Date'].append(single_date)
+
+            single_n_data = self.n_data[self.n_data['Date'] == single_date].reset_index(drop=True)
+
+            if len(single_n_data) == 0:
+                worktime_dict['Worktime'].append(0.00)
+                for i in range(16):
+                    n_vs_zero_tr_dict[f'n{i + 1}'].append(0.00)
+                    count_rate_amp_5_fr_2[f'amp{i + 1}'].append(0.00)
+                    count_rate_amp_10_fr_1[f'amp{i + 1}'].append(0.00)
+                event_counter_fr_4['Events'].append(0.00)
+                continue
+
+            break_time_dict, worktime_item = self._counting_break_time(single_n_data, delta_time_crit=600)
+            worktime_dict['Worktime'].append(worktime_item)
+            # print(break_time_dict)
+            if break_time_dict:
+                breaks_dict['Date'].extend([single_date.date()] * len(break_time_dict['StartSeconds']))
+                breaks_dict['StartSeconds'].extend(break_time_dict['StartSeconds'])
+                breaks_dict['EndSeconds'].extend(break_time_dict['EndSeconds'])
+            neutron_to_zero_trigger = self._neutron_to_zero_trigger(single_n_data)
+            for i in range(16):
+                n_vs_zero_tr_dict[f'n{i + 1}'].append(neutron_to_zero_trigger[i])
+                count_rate_amp_5_fr_2[f'amp{i + 1}'].append(
+                    self._set_event_counter(single_n_data, a_crit=6, freq=2)['count_rate'][i + 1])
+                count_rate_amp_10_fr_1[f'amp{i + 1}'].append(
+                    self._set_event_counter(single_n_data, a_crit=11, freq=1)['count_rate'][i + 1])
+
+            event_counter_fr_4['Events'].append(
+                self._set_event_counter(single_n_data, a_crit=6, freq=4)['sum_events'])
+
+        amp_5_fr_2_frame = self.set_amp_df(a_crit=6, freq=2)
+        amp_10_fr_1_frame = self.set_amp_df(a_crit=11, freq=1)
+        worktime_frame = pd.DataFrame(worktime_dict)
+        n_vs_zero_tr_frame = pd.DataFrame(n_vs_zero_tr_dict)
+        breaks_frame = pd.DataFrame(breaks_dict)
+        event_counter_fr_4 = pd.DataFrame(event_counter_fr_4)
+        count_rate_amp_5_fr_2 = pd.DataFrame(count_rate_amp_5_fr_2)
+        count_rate_amp_10_fr_1 = pd.DataFrame(count_rate_amp_10_fr_1)
+
+        for column in [f'amp{i}' for i in range(1, 17)]:
+            count_rate_amp_5_fr_2[column] = count_rate_amp_5_fr_2[column] / worktime_frame['Worktime']
+            count_rate_amp_10_fr_1[column] = count_rate_amp_10_fr_1[column] / worktime_frame['Worktime']
+
+        return worktime_frame, breaks_frame, n_vs_zero_tr_frame, event_counter_fr_4, count_rate_amp_5_fr_2, count_rate_amp_10_fr_1, amp_5_fr_2_frame, amp_10_fr_1_frame
+
+    @staticmethod
+    def _counting_break_time(n_file, delta_time_crit):
+        """Метод, выявляющий в n-file 5-минутки, когда кластер не работал, возвращает начальное время остановки и
+        конечное время остановки"""
+        time_difference = n_file['time'].diff()
+        daily_breaks_dict = defaultdict(list)
+        worktime_item = 24.00
+        # print(f'{time_difference=}')
+        for i in range(1, len(time_difference)):
+            if time_difference[i] > delta_time_crit:
+                daily_breaks_dict['StartSeconds'].append(n_file['time'][i - 1])
+                daily_breaks_dict['EndSeconds'].append(n_file['time'][i])
+        if n_file['time'][0] > delta_time_crit:
+            daily_breaks_dict['StartSeconds'].append(0)
+            daily_breaks_dict['EndSeconds'].append(n_file['time'][0])
+        if n_file['time'][len(n_file['time']) - 1] < 86400 - delta_time_crit:
+            daily_breaks_dict['StartSeconds'].append(n_file['time'][len(n_file['time']) - 1])
+            daily_breaks_dict['EndSeconds'].append(86399)
+        if daily_breaks_dict:
+            worktime_item = worktime_item - round(sum(
+                [daily_breaks_dict['EndSeconds'][index] - daily_breaks_dict['StartSeconds'][index] for index in
+                 range(len(daily_breaks_dict['StartSeconds']))]) / 3600, 2)
+            return daily_breaks_dict, worktime_item
+        else:
+            return None, worktime_item
+
+    @staticmethod
+    def _neutron_to_zero_trigger(n_file):
+        """Метод, обрабатывающий данные n-файлов ПРИЗМА-32, дающий на выходе нормированное число в событии,
+        отобранных как нейтрон, при самозапуске"""
+        counter_zero_tr = len(n_file[n_file['trigger'] == 0].index)
+        zero_tr_frame = n_file[n_file['trigger'] == 0]
+        return [round(zero_tr_frame[f'n{i}'].sum() / counter_zero_tr, 3) for i in range(1, 17)]
+
+    # except ZeroDivisionError: Нужно дописать, если допустим нет нулевых триггеров
+
+    @staticmethod
+    def _set_event_counter(n_file, a_crit, freq):
+        """Метод, обрабатывающий данные n-файлов ПРИЗМА-32, на вход подаются определенная амплитуда и количество
+        детекторов, на которых амплитуда превышает заданную, на выходе метод возвращает словарь с параметрами:
+        1) суммарное число событий на кластере, подходящих под заданные условия;
+        2) датафрейм с амплитудами детекторов для каждого события, подходящего под заданные условия;
+        3) количество превышений заданной амплитуды у детектора в событиях, подходящих под заданные условия; """
+        cluster_count_rate = {}
+        amp_frame = n_file[[f'amp{i}' for i in range(1, 17)]]
+        amp_frame['fr_sum'] = amp_frame.isin(range(a_crit, 520)).sum(axis=1, skipna=True)  # noqa
+        amp_frame = amp_frame[amp_frame['fr_sum'] >= freq].reset_index(drop=True)
+        for i in range(1, 17):
+            cluster_count_rate[i] = len(amp_frame[amp_frame[f'amp{i}'] >= a_crit])
+        return {'sum_events': len(amp_frame.index),
+                'count_rate': cluster_count_rate}
+
+    def set_amp_df(self, a_crit, freq):
+        amp_frame = self.n_data[[f'amp{i}' for i in range(1, 17)]]
+        amp_frame['fr_sum'] = amp_frame.isin(range(a_crit, 520)).sum(axis=1, skipna=True)  # noqa
+        amp_frame = amp_frame[amp_frame['fr_sum'] >= freq].reset_index(drop=True)
+        return amp_frame[[f'amp{i}' for i in range(1, 17)]]

+ 45 - 0
masks/sqlmask_converter.py

@@ -0,0 +1,45 @@
+import datetime
+
+import sqlalchemy
+import pandas as pd
+import pymongo
+
+from config_info.config import DB_URL
+
+db_client = pymongo.MongoClient(DB_URL)
+prisma_db = db_client["prisma-32_db"]
+
+
+def sqlmask_converter_to_nosql(cluster, start_date, end_date, mask_type):
+    """Переводим маску из SQL БД в бинарный вид для транспортировки в noSQL БД.
+    SQL вид существует для 2012-02-01::2021-12-31"""
+    conn = 'postgresql+psycopg2://postgres:qwerty@localhost:5432/prisma'
+    engine = sqlalchemy.create_engine(conn)
+    connect = engine.connect()
+    mask_prisma = pd.read_sql(
+        f"SELECT * FROM mask_{cluster}_params WHERE date >= "
+        f"'{start_date.year}-{start_date.month:02}-{start_date.day:02}' AND  date <= \
+           '{end_date.year}-{end_date.month:02}-{end_date.day:02}' ORDER BY date asc;", connect)
+    data_prisma_mask = mask_prisma[[f'{mask_type}{i}_mask' for i in range(16, 0, -1)]]
+
+    for i in data_prisma_mask.index:
+        mask_params = data_prisma_mask.iloc[i]
+
+        collection_prisma = prisma_db[f'{str(mask_prisma["date"][i])}_12d']
+        upd_result = collection_prisma.update_many({'cluster': cluster},
+                                                   {"$set": {
+                                                       f'mask_of_hit_counters_{mask_type}': int(
+                                                           ''.join(mask_params.astype(str)), 2),
+                                                       f'multiplicity_of_hit_counters_{mask_type}': sum(mask_params)}})
+        print(f'Matched documents {mask_type}_mask_{cluster} - {upd_result.matched_count}')
+        print(f'Modified documents {mask_type}_mask_{cluster} - {upd_result.modified_count}')
+
+
+if __name__ == '__main__':
+    date_time_start = datetime.date(2012, 12, 1)
+    date_time_stop = datetime.date(2021, 12, 31)
+    sqlmask_converter_to_nosql(cluster=1, start_date=date_time_start, end_date=date_time_stop, mask_type='amp')
+    sqlmask_converter_to_nosql(cluster=2, start_date=date_time_start, end_date=date_time_stop, mask_type='amp')
+    sqlmask_converter_to_nosql(cluster=1, start_date=date_time_start, end_date=date_time_stop, mask_type='n')
+    sqlmask_converter_to_nosql(cluster=2, start_date=date_time_start, end_date=date_time_stop, mask_type='n')
+    print('test')

+ 56 - 32
noSQL_db_Prisma.py

@@ -1,33 +1,32 @@
 import datetime
-
+import pathlib
 import pymongo
 
-from config_info.config import *
+import config_info.config
 from file_reader.file_reader import FileReader
 
 
-# from pathlib import Path
-
-
 # noinspection DuplicatedCode
 class NoSQLPrisma:
-    __DB_URL = DB_URL
+    """Класс записи n, n7, t - файлов в MongoDB базу данных PRISMA-32"""
+    __DB_URL = config_info.config.DB_URL
     __db_client = pymongo.MongoClient(__DB_URL)
     __prisma_db = __db_client["prisma-32_db"]
+    __slots__ = ["cluster", "single_date", "file_reader"]
 
     def __init__(self, cluster, single_date):
         self.cluster = cluster
         self.single_date = single_date
         self.file_reader = FileReader(cluster=self.cluster, single_date=self.single_date,
-                                      path_to_files=f'z:\\PRISMA-32\\DataArchive\\DATA P{self.cluster} archive\\data{self.single_date.year}')
-
-    # def __del__(self):
-    #     pass
+                                      path_to_files=pathlib.PurePath('D:\\PRISMA20', f'P{self.cluster}'))
 
     def dinods_data_copier(self, event_datetime, trigger, det_params, dinode):
+        """Метод, создающий запись в базе данных, пользуясь информацией из его аргументов,
+        если запись в БД уже есть, то кидает ошибку"""
         try:
             new_record = {
-                '_id': f'{event_datetime.date()}_{self.cluster:02}_{dinode:02}d_{int(event_datetime.hour):02}:' +
+                '_id': f'{event_datetime.date()}_{self.cluster:02}_{dinode:02}d' +
+                       f'_{int(event_datetime.hour):02}:' +
                        f'{int(event_datetime.minute):02}:{int(event_datetime.second):02}.' +
                        f'{str(event_datetime.microsecond)[:3]}.000.000',
                 'time_ns': int((int(event_datetime.hour) * 3600 + int(event_datetime.minute) * 60 + int(
@@ -39,23 +38,32 @@ class NoSQLPrisma:
             collection_prisma = NoSQLPrisma.__prisma_db[f'{str(event_datetime.date())}_{dinode}d']
             ins_result = collection_prisma.insert_one(new_record)
             print(f'Copied - {ins_result.inserted_id}')
+            # with open('log.txt', 'a+') as log_file:
+            #     log_file.write(f'Copied - {ins_result.inserted_id}\n')
         except pymongo.errors.DuplicateKeyError:
-            print(f'Ошибка - {event_datetime.date()}-{event_datetime.time()}')
+            print(f'Запись существует - {self.cluster}cl - {dinode:02}d' +
+                  f' - {event_datetime.date()}-{event_datetime.time()}')
+            # with open('log.txt', 'a+') as log_file:
+            #     log_file.write(f'Ошибка - {event_datetime.date()}-{event_datetime.time()}\n')
 
     def prisma_12d_past_data_copier(self):
-        n_file_today, n_file_day_after = self.file_reader.reading_n_file()
+        """Главный метод для данных 12-динода, в котором происходит чтение n
+        и t-файлов и их соединение, определение их параметров и запись в БД"""
+        n_file_today, n_file_day_after = self.file_reader.reading_n_file()  # Если n-файла, нет то
+        # проброс исключение идет в runner.py
         try:
-            t_file = self.file_reader.reading_t_file()
-            n_file_today = n_file_today.merge(t_file)
+            t_file = self.file_reader.t_file_conventer()
+            n_file_today = n_file_today.merge(t_file)  # А что делать, если не все строки в t-файле совпадают
             self.make_params_from_df_12_d(n_file_today, self.single_date)
             if any(n_file_day_after):
                 n_file_day_after = n_file_day_after.merge(t_file)
                 self.make_params_from_df_12_d(n_file_day_after,
                                               self.single_date + datetime.timedelta(
                                                   days=1))
+        # Идет проброс исключение на существование t-файла и вызывается метод make_params_from_df_12_d_no_t
         except FileNotFoundError:
-            with open(f't_{self.cluster}cl_files_not_found.txt', 'a+') as f:
-                f.write(f't-файла {self.cluster}-го кластера от {self.single_date} не существует\n')
+            with open(f'files_not_found/t_{self.cluster}cl_files_not_found.txt', 'a+', encoding='utf-8') as t_log_file:
+                t_log_file.write(f't-файла {self.cluster}-го кластера от {self.single_date} не существует\n')
             self.make_params_from_df_12_d_no_t(n_file_today, self.single_date)
             if any(n_file_day_after):
                 self.make_params_from_df_12_d_no_t(n_file_day_after,
@@ -63,6 +71,8 @@ class NoSQLPrisma:
                                                        days=1))
 
     def prisma_7d_past_data_copier(self):
+        """Главный метод для данных 7-динода, в котором происходит чтение n7,
+                определение их параметров и запись в БД"""
         n7_file_today, n7_file_day_after = self.file_reader.reading_n7_file()
         self.make_params_from_df_7_d(n7_file_today, self.single_date)
         if any(n7_file_day_after):
@@ -70,15 +80,20 @@ class NoSQLPrisma:
                                          self.single_date + datetime.timedelta(days=1))
 
     def make_params_from_df_12_d(self, df, date):
+        """Метод для данных 12-динода, парсящий построчно n+t-dataframe, определяющий все нужные для БД
+        параметры события: время регистрации, амплитуды и кол-во нейтронов по детекторно, триггер,
+        время запаздывания нейтронов."""
         for index in range(len(df.index)):
             params = list(df.iloc[index])
             event_time = str(datetime.timedelta(seconds=params[0]))
+            event_time_split = event_time.split(':')
             event_datetime = datetime.datetime(date.year, date.month, date.day,
-                                               int(event_time.split(':')[0]),
-                                               int(event_time.split(':')[1]), int(float(event_time.split(':')[2])),
+                                               int(event_time_split[0]),
+                                               int(event_time_split[1]),
+                                               int(float(event_time_split[2])),
                                                int(round(
-                                                   float(event_time.split(':')[2]) - int(
-                                                       float(event_time.split(':')[2])),
+                                                   float(event_time_split[2]) - int(
+                                                       float(event_time_split[2])),
                                                    2) * 10 ** 6)) - datetime.timedelta(hours=4)
             trigger = params[3]
             amp = [int(params[j]) for j in range(4, 36, 2)]
@@ -100,20 +115,24 @@ class NoSQLPrisma:
                     'neutrons': n[i - 1],
                     'time_delay': n_time_delay_by_det
                 }
+            # Вызывает в конце dinods_data_copier для записи в БД всю информацию о событии
             self.dinods_data_copier(event_datetime=event_datetime, trigger=trigger,
                                     det_params=det_params, dinode=12)
-        return None
 
     def make_params_from_df_7_d(self, df, date):
+        """Метод для данных 7-динода, парсящий построчно n7-dataframe, определяющий все нужные для БД
+                параметры события: время регистрации, амплитуды по детекторно, триггер"""
         for index in range(len(df.index)):
             params = list(df.iloc[index])
             event_time = str(datetime.timedelta(seconds=params[0]))  # перевод в utc-формат
+            event_time_split = event_time.split(':')
             event_datetime = datetime.datetime(date.year, date.month, date.day,
-                                               int(event_time.split(':')[0]),
-                                               int(event_time.split(':')[1]), int(float(event_time.split(':')[2])),
+                                               int(event_time_split[0]),
+                                               int(event_time_split[1]),
+                                               int(float(event_time_split[2])),
                                                int(round(
-                                                   float(event_time.split(':')[2]) - int(
-                                                       float(event_time.split(':')[2])),
+                                                   float(event_time_split[2]) - int(
+                                                       float(event_time_split[2])),
                                                    2) * 10 ** 6)) - datetime.timedelta(hours=4)
             trigger = params[2]
             amp = [int(params[j]) for j in range(3, 19)]
@@ -124,20 +143,25 @@ class NoSQLPrisma:
                 det_params[f'det_{i:02}'] = {
                     'amplitude': amp[i - 1]
                 }
+            # Вызывает в конце dinods_data_copier для записи в БД всю информацию о событии
             self.dinods_data_copier(event_datetime=event_datetime, trigger=trigger,
                                     det_params=det_params, dinode=7)
-        return None
 
     def make_params_from_df_12_d_no_t(self, df, date):
+        """Метод для данных 12-динода, парсящий построчно n-dataframe, так t-файла не существует в эту дату,
+           определяющий все нужные для БД параметры события: время регистрации,
+           амплитуды и кол-во нейтронов по детекторно, триггер."""
         for index in range(len(df.index)):
             params = list(df.iloc[index])
             event_time = str(datetime.timedelta(seconds=params[0]))
+            event_time_split = event_time.split(':')
             event_datetime = datetime.datetime(date.year, date.month, date.day,
-                                               int(event_time.split(':')[0]),
-                                               int(event_time.split(':')[1]), int(float(event_time.split(':')[2])),
+                                               int(event_time_split[0]),
+                                               int(event_time_split[1]),
+                                               int(float(event_time_split[2])),
                                                int(round(
-                                                   float(event_time.split(':')[2]) - int(
-                                                       float(event_time.split(':')[2])),
+                                                   float(event_time_split[2]) - int(
+                                                       float(event_time_split[2])),
                                                    2) * 10 ** 6)) - datetime.timedelta(hours=4)
             trigger = params[3]
             amp = [int(params[j]) for j in range(4, 36, 2)]
@@ -151,6 +175,6 @@ class NoSQLPrisma:
                     'neutrons': n[i - 1],
                     'time_delay': False
                 }
+            # Вызывает в конце dinods_data_copier для записи в БД всю информацию о событии
             self.dinods_data_copier(event_datetime=event_datetime, trigger=trigger,
                                     det_params=det_params, dinode=12)
-        return None

+ 0 - 146
prisma_12d_db_copier.py

@@ -1,146 +0,0 @@
-import datetime
-
-import pandas as pd
-import pymongo
-
-from config_info.config import *
-
-db_client = pymongo.MongoClient(DB_URL)
-prisma_db = db_client["prisma-32_db"]
-
-
-def t_file_converter(path, cluster, date_):
-    """Converter for PRISMA t-files"""
-    with open(f'{path}{cluster}t_{date_.month:02}-{date_.day:02}.{date_.year - 2000:02}') as f:
-        raw_data = f.readlines()
-    raw_data = [line.rstrip() for line in raw_data]
-    # Убираем переводы строки
-    event_list = []
-    main_list = []
-    sep = 0
-    for i in range(len(raw_data)):
-        if raw_data[i] == '*#*':
-            main_list.append(raw_data[sep].split(' '))
-            event_list.append(raw_data[sep + 1:i])
-            sep = i + 1
-    unit_delay = []
-    for item in event_list:
-        delay_per_event = []
-        for line in item:
-            step = line.split(' ')
-            for i in range(1, 17):
-                if int(step[i]) != 0:
-                    delay_per_event.append([round(int(step[0]) * (10 ** (-4)), 4), i, int(step[i])])
-        unit_delay.append(delay_per_event)
-    plural_data_list = []
-    for i in unit_delay:
-        time_list = []
-        detector_list = []
-        neut_quantity_list = []
-        for j in i:
-            time_list.append(j[0])
-            detector_list.append(j[1])
-            neut_quantity_list.append(j[2])
-        plural_data_list.append([time_list, detector_list, neut_quantity_list])
-    for i in range(len(main_list)):
-        main_list[i].extend(plural_data_list[i])
-    t_file_df = pd.DataFrame(main_list,
-                             columns=['time', 'number', 'sum_n', 'trigger', 'time_delay', 'detectors', 'n_per_step'])
-    t_file_df = t_file_df.astype({"time": float, "number": int, "sum_n": int, "trigger": int})
-    return t_file_df
-
-
-def prisma_12d_past_data_copier(date, cluster):
-    if cluster == 1:
-        n_file_template = f"n_{date.month:02}-{date.day:02}.{date.year - 2000:02}"
-        n_file = pd.read_csv(PATH_TO_PRISMA_1_DATA + n_file_template, sep=' ', skipinitialspace=True, header=None)
-        n_file = n_file.dropna(axis=1, how='all')
-        n_file.columns = ['time', 'number', 'sum_n', 'trigger'] + list(range(32))
-        print("Data file: {}".format(PATH_TO_PRISMA_1_DATA + n_file_template))
-        t_file = t_file_converter(PATH_TO_PRISMA_1_T_FILES, "", date)
-        n_file = n_file.merge(t_file)
-        fix_end_time_series = n_file['time'].lt(n_file['time'].shift())
-        bad_end_time_index = fix_end_time_series[fix_end_time_series == True].index
-    else:
-        n_file_template = f"2n_{date.month:02}-{date.day:02}.{date.year - 2000:02}"
-        n_file = pd.read_csv(PATH_TO_PRISMA_2_DATA + n_file_template, sep=' ', skipinitialspace=True, header=None)
-        n_file = n_file.dropna(axis=1, how='all')
-        n_file.columns = ['time', 'number', 'sum_n', 'trigger'] + list(range(32))
-        print("Data file: {}".format(PATH_TO_PRISMA_2_DATA + n_file_template))
-        t_file = t_file_converter(PATH_TO_PRISMA_2_T_FILES, 2, date)
-        n_file = n_file.merge(t_file)
-        fix_end_time_series = n_file['time'].lt(n_file['time'].shift())
-        bad_end_time_index = fix_end_time_series[fix_end_time_series == True].index
-    for index in range(len(n_file.index)):
-        params = list(n_file.iloc[index])
-        event_time = str(datetime.timedelta(seconds=params[0]))
-        # event_date = (datetime.timedelta(seconds=params[0]) + datetime.timedelta(hours=3)).date()
-        event_datetime = datetime.datetime(date.year, date.month, date.day, int(event_time.split(':')[0]),
-                                           int(event_time.split(':')[1]), int(float(event_time.split(':')[2])),
-                                           int(round(
-                                               float(event_time.split(':')[2]) - int(float(event_time.split(':')[2])),
-                                               2) * 10 ** 6)) - datetime.timedelta(hours=4)
-        if index >= bad_end_time_index:
-            new_date = date + datetime.timedelta(days=1)
-            event_datetime = datetime.datetime(new_date.year, new_date.month, new_date.day, int(event_time.split(':')[0]),
-                                           int(event_time.split(':')[1]), int(float(event_time.split(':')[2])),
-                                           int(round(
-                                               float(event_time.split(':')[2]) - int(float(event_time.split(':')[2])),
-                                               2) * 10 ** 6)) - datetime.timedelta(hours=4)
-        trigger = params[3]
-        amp = [int(params[j]) for j in range(4, 36, 2)]
-        n = [int(params[j]) for j in range(5, 37, 2)]
-
-        n_time_delay = params[36]
-        detector = params[37]
-        n_in_step = params[38]
-
-        det_params = {}
-        for i in range(1, 17):
-            n_time_delay_by_det = []
-            detector_index = [ind for ind, v in enumerate(detector) if v == i]
-            for j in detector_index:
-                n_time_delay_by_det.extend([n_time_delay[j]] * int(n_in_step[j]))
-            #  В БД будут оставаться пустые списки при нуле нейтронов, надо ли это фиксить?
-            det_params[f'det_{i:02}'] = {
-                'amplitude': amp[i - 1],
-                'neutrons': n[i - 1],
-                'time_delay': n_time_delay_by_det
-            }
-
-        try:
-            new_record = {
-                '_id': f'{event_datetime.date()}_{cluster:02}_12d_{int(event_datetime.hour):02}:' +
-                       f'{int(event_datetime.minute):02}:{int(event_datetime.second):02}.' +
-                       f'{str(event_datetime.microsecond)[:3]}.000.000',
-                'time_ns': int((int(event_datetime.hour) * 1440 + int(event_datetime.minute) * 60 + int(
-                    event_datetime.second)) * 10e8 + int(event_datetime.microsecond) * 1000),
-                'cluster': cluster,
-                'trigger': int(trigger),
-                'detectors': det_params
-            }
-            collection_prisma = prisma_db[f'{str(event_datetime.date())}_12d']
-            ins_result = collection_prisma.insert_one(new_record)
-            print(f'Copied - {ins_result.inserted_id}')
-        except pymongo.errors.DuplicateKeyError:
-            print(f'Ошибка - {event_datetime.date()}-{event_time}')
-
-
-# Press the green button in the gutter to run the script.
-if __name__ == '__main__':
-    cluster_1 = 1
-    cluster_2 = 2
-    date_time_start = datetime.date(2021, 12, 1)  # посмотреть почему не собирается конец дня 2018-04-22
-    date_time_stop = datetime.date(2021, 12, 1)
-    LIST_OF_DATES = [(date_time_start + datetime.timedelta(days=i)) for i in
-                     range((date_time_stop - date_time_start).days + 1)]
-    for date in LIST_OF_DATES:
-        try:
-            prisma_12d_past_data_copier(date, cluster_1)
-        except FileNotFoundError:
-            print(f'файла {cluster_1}-го кластера от {date} не существует')
-        try:
-            prisma_12d_past_data_copier(date, cluster_2)
-        except FileNotFoundError:
-            print(f'файла {cluster_2}-го кластера от {date} не существует')
-    print('test')

+ 0 - 98
prisma_7d_db_copier.py

@@ -1,98 +0,0 @@
-import datetime
-
-import pandas as pd
-import pymongo
-
-from config_info.config import *
-
-db_client = pymongo.MongoClient(DB_URL)
-prisma_db = db_client["prisma-32_db"]
-
-
-def prisma_7d_past_data_copier(date, cluster):
-    if cluster == 1:
-        n7_file_template = f"n7_{date.month:02}-{date.day:02}.{date.year - 2000:02}"
-        n7_file = pd.read_csv(PATH_TO_PRISMA_1_7d_DATA + n7_file_template, sep=' ', skipinitialspace=True, header=None)
-        n7_file = n7_file.dropna(axis=1, how='all')
-        for i in range(len(n7_file[0])):
-            if type(n7_file[0][i]) is str:
-                n7_file.loc[i,0] = float('.'.join(n7_file.loc[i,0].split(',')))
-        print("Data file: {}".format(PATH_TO_PRISMA_1_7d_DATA + n7_file_template))
-        fix_end_time_series = n7_file[0].lt(n7_file[0].shift())
-        bad_end_time_index = fix_end_time_series[fix_end_time_series == True].index
-    else:
-        n7_file_template = f"2n7_{date.month:02}-{date.day:02}.{date.year - 2000:02}"
-        n7_file = pd.read_csv(PATH_TO_PRISMA_2_7d_DATA + n7_file_template, sep=' ', skipinitialspace=True, header=None)
-        n7_file = n7_file.dropna(axis=1, how='all')
-        for i in range(len(n7_file[0])):
-            if type(n7_file[0][i]) is str:
-                n7_file.loc[i,0] = float('.'.join(n7_file.loc[i,0].split(',')))
-        print("Data file: {}".format(PATH_TO_PRISMA_2_7d_DATA + n7_file_template))
-        fix_end_time_series = n7_file[0].lt(n7_file[0].shift())
-        bad_end_time_index = fix_end_time_series[fix_end_time_series == True].index
-    for index in range(len(n7_file.index)):
-        params = list(n7_file.iloc[index])
-        # if type(params[0]) is str:
-        #     params[0] = float('.'.join(params[0].split(',')))
-        event_time = str(datetime.timedelta(seconds=params[0]))  # перевод в utc-формат
-        # event_date = (datetime.timedelta(seconds=params[0]) + datetime.timedelta(hours=3)).date()
-        event_datetime = datetime.datetime(date.year, date.month, date.day, int(event_time.split(':')[0]),
-                                           int(event_time.split(':')[1]), int(float(event_time.split(':')[2])),
-                                           int(round(
-                                               float(event_time.split(':')[2]) - int(float(event_time.split(':')[2])),
-                                               2) * 10 ** 6)) - datetime.timedelta(hours=4)
-        if index >= bad_end_time_index:
-            new_date = date + datetime.timedelta(days=1)
-            event_datetime = datetime.datetime(new_date.year, new_date.month, new_date.day,
-                                               int(event_time.split(':')[0]),
-                                               int(event_time.split(':')[1]), int(float(event_time.split(':')[2])),
-                                               int(round(
-                                                   float(event_time.split(':')[2]) - int(
-                                                       float(event_time.split(':')[2])),
-                                                   2) * 10 ** 6)) - datetime.timedelta(hours=4)
-        trigger = params[2]
-        amp = [int(params[j]) for j in range(3, 19)]
-
-        det_params = {}
-
-        for i in range(1, 17):
-            det_params[f'det_{i:02}'] = {
-                'amplitude': amp[i - 1]
-            }
-
-        try:
-            new_record = {
-                '_id': f'{event_datetime.date()}_{cluster:02}_07d_{int(event_datetime.hour):02}:' +
-                       f'{int(event_datetime.minute):02}:{int(event_datetime.second):02}.' +
-                       f'{str(event_datetime.microsecond)[:3]}.000.000',
-                'time_ns': int((int(event_datetime.hour) * 1440 + int(event_datetime.minute) * 60 + int(
-                    event_datetime.second)) * 10e8 + int(event_datetime.microsecond) * 1000),
-                'cluster': cluster,
-                'trigger': int(trigger),
-                'detectors': det_params
-            }
-            collection_prisma = prisma_db[f'{str(event_datetime.date())}_7d']
-            ins_result = collection_prisma.insert_one(new_record)
-            print(f'Copied - {ins_result.inserted_id}')
-        except pymongo.errors.DuplicateKeyError:
-            print(f'Ошибка - {event_datetime.date()}-{event_time}')
-
-
-# Press the green button in the gutter to run the script.
-if __name__ == '__main__':
-    cluster_1 = 1
-    cluster_2 = 2
-    date_time_start = datetime.date(2021, 12, 1)  # посмотреть почему не собирается конец дня 2018-04-22
-    date_time_stop = datetime.date(2021, 12, 31)
-    LIST_OF_DATES = [(date_time_start + datetime.timedelta(days=i)) for i in
-                     range((date_time_stop - date_time_start).days + 1)]
-    for date in LIST_OF_DATES:
-        try:
-            prisma_7d_past_data_copier(date, cluster_1)
-        except FileNotFoundError:
-            print(f'файла {cluster_1}-го кластера от {date} не существует')
-        try:
-            prisma_7d_past_data_copier(date, cluster_2)
-        except FileNotFoundError:
-            print(f'файла {cluster_2}-го кластера от {date} не существует')
-    print('test')

BIN
requirements.txt


+ 7 - 8
runner.py

@@ -1,9 +1,9 @@
 import datetime
-from noSQL_db_Prisma import NoSQLPrisma
+from nosql_db_prisma import NoSQLPrisma
 
 
-date_time_start = datetime.date(2022, 9, 29)  # посмотреть почему не собирается конец дня 2018-04-22
-date_time_stop = datetime.date(2022, 9, 29)
+date_time_start = datetime.date(2020, 11, 11)  # посмотреть почему не собирается конец дня 2018-04-22
+date_time_stop = datetime.date(2020, 11, 12)
 # date_time_stop = datetime.date.today()
 LIST_OF_DATES = [(date_time_start + datetime.timedelta(days=i)) for i in
                  range((date_time_stop - date_time_start).days + 1)]
@@ -11,23 +11,22 @@ for date in LIST_OF_DATES:
     try:
         NoSQLPrisma(cluster=1, single_date=date).prisma_12d_past_data_copier()
     except FileNotFoundError:
-        print('нет')
-        with open('n_1cl_files_not_found.txt', 'a+') as f:
+        with open('files_not_found/n_1cl_files_not_found.txt', 'a+', encoding='utf-8') as f:
             f.write(f'n-файла 1-го кластера от {date} не существует\n')
     try:
         NoSQLPrisma(cluster=2, single_date=date).prisma_12d_past_data_copier()
     except FileNotFoundError:
 
-        with open('n_2cl_files_not_found.txt', 'a+') as f:
+        with open('files_not_found/n_2cl_files_not_found.txt', 'a+', encoding='utf-8') as f:
             f.write(f'n-файла 2-го кластера от {date} не существует\n')
     try:
         NoSQLPrisma(cluster=1, single_date=date).prisma_7d_past_data_copier()
     except FileNotFoundError:
-        with open('n7_1cl_files_not_found.txt', 'a+') as f:
+        with open('files_not_found/n7_1cl_files_not_found.txt', 'a+', encoding='utf-8') as f:
             f.write(f'n7-файла 1-го кластера от {date} не существует\n')
     try:
         NoSQLPrisma(cluster=2, single_date=date).prisma_7d_past_data_copier()
     except FileNotFoundError:
-        with open('n7_2cl_files_not_found.txt', 'a+') as f:
+        with open('files_not_found/n7_2cl_files_not_found.txt', 'a+', encoding='utf-8') as f:
             f.write(f'n7-файла 2-го кластера от {date} не существует\n')
 print('test')

+ 0 - 73
sqlmask_converter.py

@@ -1,73 +0,0 @@
-import pandas as pd
-import datetime
-import sqlalchemy
-
-
-def sqlmask_converter(start_date, end_date):
-    """Переводим маску из SQL БД в бинарный вид для транспортировки в noSQL БД"""
-    conn = 'postgresql+psycopg2://postgres:qwerty@localhost:5432/prisma'
-    engine = sqlalchemy.create_engine(conn)
-    connect = engine.connect()
-    mask_prisma_1 = pd.read_sql("SELECT * FROM mask_1_params WHERE date >= '{}-{:02}-{:02}' AND  date <= \
-           '{}-{:02}-{:02}' ORDER BY date asc;".format(start_date.year, start_date.month, start_date.day, end_date.year,
-                                                       end_date.month, end_date.day), connect)
-    mask_prisma_2 = pd.read_sql("SELECT * FROM mask_2_params WHERE date >= '{}-{:02}-{:02}' AND  date <= \
-           '{}-{:02}-{:02}' ORDER BY date asc;".format(start_date.year, start_date.month, start_date.day, end_date.year,
-                                                       end_date.month, end_date.day), connect)
-    # amp_data_prisma_1_mask = mask_prisma_1[
-    #     ['amp1_mask', 'amp2_mask', 'amp3_mask', 'amp4_mask', 'amp5_mask', 'amp6_mask', 'amp7_mask', 'amp8_mask',
-    #      'amp9_mask', 'amp10_mask', 'amp11_mask', 'amp12_mask', 'amp13_mask',
-    #      'amp14_mask', 'amp15_mask', 'amp16_mask']]
-    amp_data_prisma_1_mask = mask_prisma_1[
-        ['amp16_mask', 'amp15_mask', 'amp14_mask', 'amp13_mask', 'amp12_mask', 'amp11_mask', 'amp10_mask', 'amp9_mask',
-         'amp8_mask', 'amp7_mask', 'amp6_mask', 'amp5_mask', 'amp4_mask',
-         'amp3_mask', 'amp2_mask', 'amp1_mask']]
-    amp_data_prisma_2_mask = mask_prisma_2[
-        ['amp16_mask', 'amp15_mask', 'amp14_mask', 'amp13_mask', 'amp12_mask', 'amp11_mask', 'amp10_mask', 'amp9_mask',
-         'amp8_mask', 'amp7_mask', 'amp6_mask', 'amp5_mask', 'amp4_mask',
-         'amp3_mask', 'amp2_mask', 'amp1_mask']]
-
-    n_data_prisma_1_mask = mask_prisma_1[
-        ['n16_mask', 'n15_mask', 'n14_mask', 'n13_mask', 'n12_mask', 'n11_mask', 'n10_mask', 'n9_mask',
-         'n8_mask', 'n7_mask', 'n6_mask', 'n5_mask', 'n4_mask',
-         'n3_mask', 'n2_mask', 'n1_mask']]
-    n_data_prisma_2_mask = mask_prisma_2[
-        ['n16_mask', 'n15_mask', 'n14_mask', 'n13_mask', 'n12_mask', 'n11_mask', 'n10_mask', 'n9_mask',
-         'n8_mask', 'n7_mask', 'n6_mask', 'n5_mask', 'n4_mask',
-         'n3_mask', 'n2_mask', 'n1_mask']]
-
-    binary_n_mask_1 = {}
-    binary_n_mask_2 = {}
-    binary_amp_mask_1 = {}
-    binary_amp_mask_2 = {}
-
-    for i in amp_data_prisma_1_mask.index:
-        amp_mask_params = amp_data_prisma_1_mask.iloc[i]
-        n_mask_params = n_data_prisma_1_mask.iloc[i]
-        binary_amp_mask_1[str(mask_prisma_1['date'][i])] = {
-            'mask_of_hit_counters_a': int(''.join(amp_mask_params.astype(str)), 2),
-            'multiplicity_of_hit_counters_a': sum(amp_mask_params)}
-
-        binary_n_mask_1[str(mask_prisma_1['date'][i])] = {
-            'mask_of_hit_counters_n': int(''.join(n_mask_params.astype(str)), 2),
-            'multiplicity_of_hit_counters_n': sum(n_mask_params)}
-
-    for i in amp_data_prisma_2_mask.index:
-        amp_mask_params = amp_data_prisma_2_mask.iloc[i]
-        n_mask_params = n_data_prisma_2_mask.iloc[i]
-        binary_amp_mask_2[str(mask_prisma_2['date'][i])] = {
-            'mask_of_hit_counters_a': int(''.join(amp_mask_params.astype(str)), 2),
-            'multiplicity_of_hit_counters_a': sum(amp_mask_params)}
-
-        binary_n_mask_2[str(mask_prisma_2['date'][i])] = {
-            'mask_of_hit_counters_n': int(''.join(n_mask_params.astype(str)), 2),
-            'multiplicity_of_hit_counters_n': sum(n_mask_params)}
-
-    return binary_n_mask_1, binary_amp_mask_1, binary_n_mask_2, binary_amp_mask_2
-
-
-if __name__ == '__main__':
-    date_time_start = datetime.date(2021, 12, 1)  # посмотреть почему не собирается конец дня 2018-04-22
-    date_time_stop = datetime.date(2021, 12, 31)
-    sqlmask_converter(date_time_start, date_time_stop)
-    print('test')

+ 0 - 33
update_with_add_mask.py

@@ -1,33 +0,0 @@
-import pymongo
-import datetime
-
-from sqlmask_converter import sqlmask_converter
-from config_info.config import *
-
-db_client = pymongo.MongoClient(DB_URL)
-prisma_db = db_client["prisma-32_db"]
-
-
-def update_with_add_mask(date_, binary_n_mask_1, binary_amp_mask_1, binary_n_mask_2, binary_amp_mask_2):
-    collection_prisma = prisma_db[f'{str(date_)}_12d']
-    upd_n_result_1 = collection_prisma.update_many({'cluster': 1}, {"$set": binary_n_mask_1[str(date_)]})
-    print(f'Added n_mask_1 - {upd_n_result_1.raw_result}')
-    upd_amp_result_1 = collection_prisma.update_many({'cluster': 1}, {"$set": binary_amp_mask_1[str(date_)]})
-    print(f'Added amp_mask_1 - {upd_amp_result_1.raw_result}')
-    upd_n_result_2 = collection_prisma.update_many({'cluster': 2}, {"$set": binary_n_mask_2[str(date_)]})
-    print(f'Added n_mask_2 - {upd_n_result_2.raw_result}')
-    upd_amp_result_2 = collection_prisma.update_many({'cluster': 2}, {"$set": binary_amp_mask_2[str(date_)]})
-    print(f'Added amp_mask_2 - {upd_amp_result_2.raw_result}')
-
-
-if __name__ == '__main__':
-    date_time_start = datetime.date(2021, 12, 1)  # посмотреть почему не собирается конец дня 2018-04-22
-    date_time_stop = datetime.date(2021, 12, 31)
-    binary_n_mask_1, binary_amp_mask_1, binary_n_mask_2, binary_amp_mask_2 = sqlmask_converter(date_time_start,
-                                                                                               date_time_stop)
-    LIST_OF_DATES = [(date_time_start + datetime.timedelta(days=i)) for i in
-                     range((date_time_stop - date_time_start).days + 1)]
-    for date in LIST_OF_DATES:
-        update_with_add_mask(date, binary_n_mask_1, binary_amp_mask_1, binary_n_mask_2, binary_amp_mask_2)
-
-    print('test')