123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- import datetime
- import pathlib
- import pymongo
- import config_info.config
- from file_reader.file_reader import FileReader
- # noinspection DuplicatedCode
- class NoSQLPrisma:
- """Класс записи 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=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' +
- 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(
- event_datetime.second)) * 10e8 + int(event_datetime.microsecond) * 1000),
- 'cluster': self.cluster,
- 'trigger': int(trigger),
- 'detectors': det_params
- }
- 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'Запись существует - {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):
- """Главный метод для данных 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.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'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,
- self.single_date + datetime.timedelta(
- 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):
- self.make_params_from_df_7_d(n7_file_day_after,
- 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(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
- }
- # Вызывает в конце dinods_data_copier для записи в БД всю информацию о событии
- self.dinods_data_copier(event_datetime=event_datetime, trigger=trigger,
- det_params=det_params, dinode=12)
- 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(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]
- }
- # Вызывает в конце dinods_data_copier для записи в БД всю информацию о событии
- self.dinods_data_copier(event_datetime=event_datetime, trigger=trigger,
- det_params=det_params, dinode=7)
- 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(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)]
- det_params = {}
- for i in range(1, 17):
- # В БД будут оставаться пустые списки при нуле нейтронов, надо ли это фиксить?
- det_params[f'det_{i:02}'] = {
- 'amplitude': amp[i - 1],
- '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)
|