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)
def creating_report( differential_pressure: Dict[str, numpy.ndarray], initial_pressure: numpy.ndarray, time: Dict[str, Union[str, numpy.ndarray]], table_params: numpy.ndarray, language: custom_plugin_base.utils.service_enum.LangEnum, unit_system: str, project_info: friction_loss.utils.plugin_dataclasses.ProjectInfo, temp_path: pathlib.Path, md_tvdss: numpy.ndarray) -> custom_plugin_base.server.calculation.SolveFileContent:
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.

def create_book( differential_pressure, initial_pressure, time, table_params, unit_system, project_info, md_tvdss, **kwargs) -> None:
 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.