friction_loss.outputs.create_report
1import io 2import shutil 3from pathlib import Path 4from typing import Dict, Union 5 6import numpy as np 7from custom_plugin_base.server.calculation import SolveFileContent 8from custom_plugin_base.utils.service_enum import LangEnum 9from polydoc.polypage import polypage, polybook 10 11from friction_loss.outputs.create_template import create_excel_table 12from friction_loss.outputs.webreport_utils import (create_plot, create_table_params, create_title_table, 13 create_animate_plot) 14from friction_loss.utils.const import FOLDER_NAME, LANG_LIST 15from friction_loss.utils.plugin_dataclasses import ProjectInfo 16from friction_loss.utils.set_language import PAGES_NAMES_TRANSLATOR, UNIT_SYSTEMS, NAMES_COLUMNS_TRANSLATOR 17 18 19def creating_report(differential_pressure: Dict[str, np.ndarray], initial_pressure: np.ndarray, 20 time: Dict[str, Union[np.ndarray, str]], table_params: np.ndarray, 21 language: LangEnum, unit_system: str, project_info: ProjectInfo, 22 temp_path: Path, md_tvdss: np.ndarray) -> SolveFileContent: 23 """ 24 Function of creating files of web-report 25 26 Parameters 27 ---------- 28 differential_pressure : dict 29 'downhole_pressure' : np.ndarray 30 Recalculated pressure. 31 'data' : np.ndarray(PDCTransientData) 32 Pressure and flow rate data for each time point 33 initial_pressure : np.ndarray 34 Pressure at well points for a given flow rate 35 time : dict[str, np.ndarray | str] 36 'value': np.ndarray 37 Array of the elapsed time of the well operation 38 'unit': str 39 Units of time 40 table_params : np.ndarray(dict[str, PolypresInputParameter]) 41 keys: parameter names 42 values: dataclass with rows of table in initial units 43 language : LangEnum 44 Selected language of interface. 45 unit_system : str 46 Units of project 47 project_info : ProjectInfo 48 Dataclass with information about project 49 temp_path : os.Path 50 os.Path to the temporary directory 51 md_tvdss: np.ndarray 52 Array with MD and TVDss coordinates 53 54 Returns 55 ------- 56 output: SolveFileContent 57 A SolveFileContent object containing the archived web report. 58 """ 59 temp_folder_path = temp_path.joinpath(FOLDER_NAME) 60 temp_folder_path.mkdir(exist_ok=True) 61 62 # Создание веб-документа с описанием плагина 63 polybook(root_folder=str(temp_path), title=FOLDER_NAME, langlist=LANG_LIST, headerbar=True, footer=True, 64 create_book=create_book, differential_pressure=differential_pressure, time=time, language=language.value, 65 initial_pressure=initial_pressure, table_params=table_params, 66 unit_system=unit_system, project_info=project_info, md_tvdss=md_tvdss) 67 68 # Архивация папки 69 shutil.make_archive(str(temp_folder_path), 'zip', temp_folder_path) 70 71 # Преобразование фрхива в байты 72 with open(str(temp_folder_path) + '.zip', 'rb') as f: 73 zip_folder = f.read() 74 encoded_folder = io.BytesIO(zip_folder).getvalue() 75 76 output = SolveFileContent(name=FOLDER_NAME + '.zip', 77 content_type='zip', 78 content=encoded_folder) 79 80 return output 81 82 83def create_book(differential_pressure, initial_pressure, time, table_params, 84 unit_system, project_info, md_tvdss, **kwargs) -> None: 85 """ 86 Generate HTML report pages. 87 """ 88 path = Path(kwargs['root_folder']) / FOLDER_NAME / f"{kwargs['language']}_{kwargs['title']}" 89 language = LangEnum(kwargs['language']) 90 depths = table_params[-1].copy() 91 92 # Переводчик 93 PAGES_NAMES = PAGES_NAMES_TRANSLATOR[language] 94 NAMES_COLUMNS = NAMES_COLUMNS_TRANSLATOR[language] 95 UNIT_SYSTEM = UNIT_SYSTEMS[language] 96 97 page = polypage(content_line_height=2, p_style=dict(font_size='1.5em', line_height=2.5), **kwargs) 98 page.locale['ru']['Fig.'] = 'Рис.' 99 100 page.copy_file(str(path / 'img' / 'header.png'), str(path / PAGES_NAMES['report'] / 'img')) 101 page.copy_file(str(path / 'img' / 'body.png'), str(path / PAGES_NAMES['report'] / 'img')) 102 103 # Создание страниц отчета host_page-главная страница 104 host_page = page.add_page(title=PAGES_NAMES['report'], home_page=True, image_folder='img', 105 background_image_header='header.png', background_image_body='body.png') 106 107 # Массивы пересчитанного и исходного давления 108 y = {'depth': differential_pressure['downhole_pressure'], 109 'initial': initial_pressure} 110 111 # -------------------------------------Титульная страница----------------------------------------------------------# 112 title_page = host_page.add_page(title=PAGES_NAMES['title'], footer=False, headerbar=False, 113 background_image_body='body.ong', image_folder='img') 114 title_page.hold.add_break(count=3) 115 create_title_table(page=title_page, info=project_info, language=language) 116 # -----------------------------------------------------------------------------------------------------------------# 117 118 names = project_info.well_name.split(', ') 119 wells_pages = [host_page.add_page(title=name, footer=False, headerbar=False, 120 background_image_body='body.png', image_folder='img') for name in names] 121 122 # обновили глубину положения датчика 123 if np.isnan(depths['gauge']): 124 depths['gauge'] = 0 125 126 for idx, well in enumerate(wells_pages): 127 # обновили референсную глубину 128 if np.isnan(table_params[-1]['ref']): 129 depths['ref'] = differential_pressure['data'][1].pressure[0][-1] 130 # -------------------------------Страница с пересчитанным давлением--------------------------------------------# 131 depth_page = well.add_page(title=PAGES_NAMES['downhole'], footer=False, headerbar=False, 132 background_image_body='body.png', image_folder='img') 133 create_plot(path=path, name=PAGES_NAMES['downhole'], page=depth_page, x=time['value'][idx], y=y, 134 x_label=PAGES_NAMES['time'], x_unit=UNIT_SYSTEM[unit_system]['Time'], idx=idx, 135 y_label=PAGES_NAMES['pressure'], y_unit=UNIT_SYSTEM[unit_system]['Pressure'], language=language, 136 well_name=names[idx], depths=depths, depth_unit=UNIT_SYSTEM[unit_system]['Length']) 137 # Добавили информацию о насосе 138 if isinstance(table_params[idx]["pump"].value, str): 139 pump = table_params[idx]["pump"].value 140 depth_page.hold.add_h(level=3, color='black', style="text-align:left", 141 content=f'{PAGES_NAMES["pump"]}: {pump}') 142 else: 143 depth_page.hold.add_h(level=3, color='black', style="text-align:left", 144 content=f'{PAGES_NAMES["no_pump"]}') 145 # -------------------------------------------------------------------------------------------------------------# 146 147 # ----------------------------Страница с профилем давлением----------------------------------------------------# 148 profil_page = well.add_page(title=PAGES_NAMES['profile'], footer=False, headerbar=False, 149 background_image_body='body.png', image_folder='img') 150 time['unit'] = UNIT_SYSTEM[unit_system]['Time'] 151 create_animate_plot(path=path, name=PAGES_NAMES['profile'], page=profil_page, idx=idx, 152 data=differential_pressure['data'][idx], time=time, 153 x_label=PAGES_NAMES['pressure'], x_unit=UNIT_SYSTEM[unit_system]['Pressure'], 154 language=language, y_label=PAGES_NAMES['depth'], 155 y_unit=UNIT_SYSTEM[unit_system]['Length'], well_name=names[idx]) 156 157 # Добавили информацию о насосе 158 if isinstance(table_params[idx]["pump"].value, str): 159 pump = table_params[idx]["pump"].value 160 profil_page.hold.add_h(level=3, color='black', style="text-align:left", 161 content=f'{PAGES_NAMES["pump"]}: {pump}') 162 else: 163 profil_page.hold.add_h(level=3, color='black', style="text-align:left", 164 content=f'{PAGES_NAMES["no_pump"]}') 165 # -------------------------------------------------------------------------------------------------------------# 166 167 # ---------------------------Страница с таблицей параметров----------------------------------------------------# 168 well.hold.add_h(level=1, content=PAGES_NAMES['well_and_pump'], 169 color='black', style="text-align:left") 170 well.hold.add_break() 171 create_table_params(page=well, data_dict=table_params[idx], language=language) 172 well.hold.add_break(2) 173 174 # Добавили кнопку загрузки файла 175 file_name = PAGES_NAMES['params_file'] 176 well.hold.add_a(level=2, color='black', style="text-align:left", content=NAMES_COLUMNS['download'], 177 subtag=f'href="{file_name}.xlsx" download=f"{file_name}.xlsx", download') 178 # --------------------------------------------------------------------------------------------------------------# 179 180 # Создали подвижную панель слева 181 host_iframe = host_page.add_content_and_iframe(home_page=title_page, 182 left_offset='22%', 183 breadcrumbs=False, 184 item_style=dict(fz='x-large'), 185 counter_format='plain') 186 187 name_project = [dict(text=f'FLOSS   —   {project_info.test_name}', target=title_page)] 188 host_page.add_navbar(navbar=name_project, target=host_iframe, refresh_footer=True) 189 190 # Создание страниц документа 191 page.locale = False # для того чтобы не создавался файлик locale.xlsx 192 page.create_pages() 193 194 create_excel_table(path=path / PAGES_NAMES['report'] / names[0] / f'{PAGES_NAMES["params_file"]}.xlsx', 195 data=table_params, language=language, unit=unit_system, 196 well_names=project_info.well_name, md_tvdss=md_tvdss) 197 for well in names[1:]: 198 # Создание Excel файла с параметрами, который можно скачать пользвателю 199 path_to_file = path / PAGES_NAMES['report'] / well / f'{PAGES_NAMES["params_file"]}.xlsx' 200 shutil.copy(path / PAGES_NAMES['report'] / names[0] / f'{PAGES_NAMES["params_file"]}.xlsx', path_to_file)
20def creating_report(differential_pressure: Dict[str, np.ndarray], initial_pressure: np.ndarray, 21 time: Dict[str, Union[np.ndarray, str]], table_params: np.ndarray, 22 language: LangEnum, unit_system: str, project_info: ProjectInfo, 23 temp_path: Path, md_tvdss: np.ndarray) -> SolveFileContent: 24 """ 25 Function of creating files of web-report 26 27 Parameters 28 ---------- 29 differential_pressure : dict 30 'downhole_pressure' : np.ndarray 31 Recalculated pressure. 32 'data' : np.ndarray(PDCTransientData) 33 Pressure and flow rate data for each time point 34 initial_pressure : np.ndarray 35 Pressure at well points for a given flow rate 36 time : dict[str, np.ndarray | str] 37 'value': np.ndarray 38 Array of the elapsed time of the well operation 39 'unit': str 40 Units of time 41 table_params : np.ndarray(dict[str, PolypresInputParameter]) 42 keys: parameter names 43 values: dataclass with rows of table in initial units 44 language : LangEnum 45 Selected language of interface. 46 unit_system : str 47 Units of project 48 project_info : ProjectInfo 49 Dataclass with information about project 50 temp_path : os.Path 51 os.Path to the temporary directory 52 md_tvdss: np.ndarray 53 Array with MD and TVDss coordinates 54 55 Returns 56 ------- 57 output: SolveFileContent 58 A SolveFileContent object containing the archived web report. 59 """ 60 temp_folder_path = temp_path.joinpath(FOLDER_NAME) 61 temp_folder_path.mkdir(exist_ok=True) 62 63 # Создание веб-документа с описанием плагина 64 polybook(root_folder=str(temp_path), title=FOLDER_NAME, langlist=LANG_LIST, headerbar=True, footer=True, 65 create_book=create_book, differential_pressure=differential_pressure, time=time, language=language.value, 66 initial_pressure=initial_pressure, table_params=table_params, 67 unit_system=unit_system, project_info=project_info, md_tvdss=md_tvdss) 68 69 # Архивация папки 70 shutil.make_archive(str(temp_folder_path), 'zip', temp_folder_path) 71 72 # Преобразование фрхива в байты 73 with open(str(temp_folder_path) + '.zip', 'rb') as f: 74 zip_folder = f.read() 75 encoded_folder = io.BytesIO(zip_folder).getvalue() 76 77 output = SolveFileContent(name=FOLDER_NAME + '.zip', 78 content_type='zip', 79 content=encoded_folder) 80 81 return output
Function of creating files of web-report
Parameters
differential_pressure : dict 'downhole_pressure' : np.ndarray Recalculated pressure. 'data' : np.ndarray(PDCTransientData) Pressure and flow rate data for each time point initial_pressure : np.ndarray Pressure at well points for a given flow rate time : dict[str, np.ndarray | str] 'value': np.ndarray Array of the elapsed time of the well operation 'unit': str Units of time table_params : np.ndarray(dict[str, PolypresInputParameter]) keys: parameter names values: dataclass with rows of table in initial units language : LangEnum Selected language of interface. unit_system : str Units of project project_info : ProjectInfo Dataclass with information about project temp_path : os.Path os.Path to the temporary directory md_tvdss: np.ndarray Array with MD and TVDss coordinates
Returns
output: SolveFileContent A SolveFileContent object containing the archived web report.
84def create_book(differential_pressure, initial_pressure, time, table_params, 85 unit_system, project_info, md_tvdss, **kwargs) -> None: 86 """ 87 Generate HTML report pages. 88 """ 89 path = Path(kwargs['root_folder']) / FOLDER_NAME / f"{kwargs['language']}_{kwargs['title']}" 90 language = LangEnum(kwargs['language']) 91 depths = table_params[-1].copy() 92 93 # Переводчик 94 PAGES_NAMES = PAGES_NAMES_TRANSLATOR[language] 95 NAMES_COLUMNS = NAMES_COLUMNS_TRANSLATOR[language] 96 UNIT_SYSTEM = UNIT_SYSTEMS[language] 97 98 page = polypage(content_line_height=2, p_style=dict(font_size='1.5em', line_height=2.5), **kwargs) 99 page.locale['ru']['Fig.'] = 'Рис.' 100 101 page.copy_file(str(path / 'img' / 'header.png'), str(path / PAGES_NAMES['report'] / 'img')) 102 page.copy_file(str(path / 'img' / 'body.png'), str(path / PAGES_NAMES['report'] / 'img')) 103 104 # Создание страниц отчета host_page-главная страница 105 host_page = page.add_page(title=PAGES_NAMES['report'], home_page=True, image_folder='img', 106 background_image_header='header.png', background_image_body='body.png') 107 108 # Массивы пересчитанного и исходного давления 109 y = {'depth': differential_pressure['downhole_pressure'], 110 'initial': initial_pressure} 111 112 # -------------------------------------Титульная страница----------------------------------------------------------# 113 title_page = host_page.add_page(title=PAGES_NAMES['title'], footer=False, headerbar=False, 114 background_image_body='body.ong', image_folder='img') 115 title_page.hold.add_break(count=3) 116 create_title_table(page=title_page, info=project_info, language=language) 117 # -----------------------------------------------------------------------------------------------------------------# 118 119 names = project_info.well_name.split(', ') 120 wells_pages = [host_page.add_page(title=name, footer=False, headerbar=False, 121 background_image_body='body.png', image_folder='img') for name in names] 122 123 # обновили глубину положения датчика 124 if np.isnan(depths['gauge']): 125 depths['gauge'] = 0 126 127 for idx, well in enumerate(wells_pages): 128 # обновили референсную глубину 129 if np.isnan(table_params[-1]['ref']): 130 depths['ref'] = differential_pressure['data'][1].pressure[0][-1] 131 # -------------------------------Страница с пересчитанным давлением--------------------------------------------# 132 depth_page = well.add_page(title=PAGES_NAMES['downhole'], footer=False, headerbar=False, 133 background_image_body='body.png', image_folder='img') 134 create_plot(path=path, name=PAGES_NAMES['downhole'], page=depth_page, x=time['value'][idx], y=y, 135 x_label=PAGES_NAMES['time'], x_unit=UNIT_SYSTEM[unit_system]['Time'], idx=idx, 136 y_label=PAGES_NAMES['pressure'], y_unit=UNIT_SYSTEM[unit_system]['Pressure'], language=language, 137 well_name=names[idx], depths=depths, depth_unit=UNIT_SYSTEM[unit_system]['Length']) 138 # Добавили информацию о насосе 139 if isinstance(table_params[idx]["pump"].value, str): 140 pump = table_params[idx]["pump"].value 141 depth_page.hold.add_h(level=3, color='black', style="text-align:left", 142 content=f'{PAGES_NAMES["pump"]}: {pump}') 143 else: 144 depth_page.hold.add_h(level=3, color='black', style="text-align:left", 145 content=f'{PAGES_NAMES["no_pump"]}') 146 # -------------------------------------------------------------------------------------------------------------# 147 148 # ----------------------------Страница с профилем давлением----------------------------------------------------# 149 profil_page = well.add_page(title=PAGES_NAMES['profile'], footer=False, headerbar=False, 150 background_image_body='body.png', image_folder='img') 151 time['unit'] = UNIT_SYSTEM[unit_system]['Time'] 152 create_animate_plot(path=path, name=PAGES_NAMES['profile'], page=profil_page, idx=idx, 153 data=differential_pressure['data'][idx], time=time, 154 x_label=PAGES_NAMES['pressure'], x_unit=UNIT_SYSTEM[unit_system]['Pressure'], 155 language=language, y_label=PAGES_NAMES['depth'], 156 y_unit=UNIT_SYSTEM[unit_system]['Length'], well_name=names[idx]) 157 158 # Добавили информацию о насосе 159 if isinstance(table_params[idx]["pump"].value, str): 160 pump = table_params[idx]["pump"].value 161 profil_page.hold.add_h(level=3, color='black', style="text-align:left", 162 content=f'{PAGES_NAMES["pump"]}: {pump}') 163 else: 164 profil_page.hold.add_h(level=3, color='black', style="text-align:left", 165 content=f'{PAGES_NAMES["no_pump"]}') 166 # -------------------------------------------------------------------------------------------------------------# 167 168 # ---------------------------Страница с таблицей параметров----------------------------------------------------# 169 well.hold.add_h(level=1, content=PAGES_NAMES['well_and_pump'], 170 color='black', style="text-align:left") 171 well.hold.add_break() 172 create_table_params(page=well, data_dict=table_params[idx], language=language) 173 well.hold.add_break(2) 174 175 # Добавили кнопку загрузки файла 176 file_name = PAGES_NAMES['params_file'] 177 well.hold.add_a(level=2, color='black', style="text-align:left", content=NAMES_COLUMNS['download'], 178 subtag=f'href="{file_name}.xlsx" download=f"{file_name}.xlsx", download') 179 # --------------------------------------------------------------------------------------------------------------# 180 181 # Создали подвижную панель слева 182 host_iframe = host_page.add_content_and_iframe(home_page=title_page, 183 left_offset='22%', 184 breadcrumbs=False, 185 item_style=dict(fz='x-large'), 186 counter_format='plain') 187 188 name_project = [dict(text=f'FLOSS   —   {project_info.test_name}', target=title_page)] 189 host_page.add_navbar(navbar=name_project, target=host_iframe, refresh_footer=True) 190 191 # Создание страниц документа 192 page.locale = False # для того чтобы не создавался файлик locale.xlsx 193 page.create_pages() 194 195 create_excel_table(path=path / PAGES_NAMES['report'] / names[0] / f'{PAGES_NAMES["params_file"]}.xlsx', 196 data=table_params, language=language, unit=unit_system, 197 well_names=project_info.well_name, md_tvdss=md_tvdss) 198 for well in names[1:]: 199 # Создание Excel файла с параметрами, который можно скачать пользвателю 200 path_to_file = path / PAGES_NAMES['report'] / well / f'{PAGES_NAMES["params_file"]}.xlsx' 201 shutil.copy(path / PAGES_NAMES['report'] / names[0] / f'{PAGES_NAMES["params_file"]}.xlsx', path_to_file)
Generate HTML report pages.