pydfnWorks
python wrapper for dfnWorks
make_pdf.py
Go to the documentation of this file.
1 """
2  :filename: make_pdf.py
3  :synopsis: Combines figures and network information to make the output report pdf
4  :version: 1.0
5  :maintainer: Jeffrey Hyman
6  :moduleauthor: Jeffrey Hyman <jhyman@lanl.gov>
7 """
8 
9 from fpdf import FPDF
10 
11 # NEED TO BE SET TO /Users/jhyman/src
12 dfnworks_image_black = "/Users/jhyman/src/dfnworks-main/pydfnworks/pydfnworks/dfnGen/generation/output_report/figures/dfnWorks.all.black.png"
13 lanl_image = "/Users/jhyman/src/dfnworks-main/pydfnworks/pydfnworks/dfnGen/generation/output_report/figures/lanl-logo-footer.png"
14 
15 class PDF(FPDF):
16  global name
17 
18  def header(self):
19  # Logo
20  self.image(dfnworks_image_black, x=5, y=8, w=50)
21  self.set_font('Times', 'B', 18)
22  self.text(x=100, y=10, txt=f'dfnGen Output Report: {name}')
23  self.image(lanl_image, x=240, y=2, w=50)
24 
25  # Page footer
26  def footer(self):
27  # Position at 1.5 cm from bottom
28  self.set_y(-15)
29  # Arial italic 8
30  self.set_font('Times', 'I', 8)
31  # Page number
32  self.cell(0, 10, 'Page ' + str(self.page_no()), 0, 0, 'C')
33 
34 
35 def add_table_of_contents(params, pdf):
36  """ Creates Table of contents
37 
38  Parameters
39  ------------
40  params : dictionary
41  General dictionary of output analysis code. Contains information on number of families, number of fractures, and colors.
42  pdf : fpdf object
43  Current working pdf
44 
45  Returns
46  ---------
47  pdf : fpdf object
48  Current working pdf
49 
50  Notes
51  ------
52  None
53  """
54 
55  if params["verbose"]:
56  print("--> Making Table of Contents")
57 
58  pdf.add_page()
59  pdf.image(f"{params['output_dir']}/network/network_orientations.png",
60  x=90,
61  y=50,
62  w=200)
63  pdf.text(x=10, y=50, txt="Page 1: Table of Contents")
64  pdf.text(x=10, y=60, txt="Page 2: Network Summary")
65  for i in range(1, params["num_families"] + 1):
66  pdf.text(x=10, y=60 + i * 10, txt=f"Page {2+i}: Family Number {i}")
67  pdf.text(x=10,
68  y=60 + (params["num_families"] + 1) * 10,
69  txt=f"Page {3+params['num_families']}: FRAM information")
70 
71  return pdf
72 
73 
74 def create_network_text(params):
75  """ Creates block text for the entire network.
76 
77 
78  Parameters
79  -------------
80  params : dictionary
81  Output report dictionary containing general parameters. See output_report for more details
82 
83  Returns
84  -----------
85  text : string
86  Block of text with information about the network.
87 
88  Notes
89  --------
90  None
91 
92  """
93  text = f'Jobname: {params["jobname"]}\n\
94 Number of fracture families:\t{params["num_families"]}\n\
95 Total number of fractures:\t{params["num_total_fractures"]}\n\
96 Fractures in connected network:\t{params["num_accepted_fractures"]}\n\
97 Domain (m)\n\
98  x : {-0.5 * params["domain"]["x"]} x {0.5 * params["domain"]["x"]}\
99  y : {-0.5 * params["domain"]["y"]} x {0.5 * params["domain"]["y"]} \
100  z : {-0.5 * params["domain"]["z"]} x {0.5 * params["domain"]["z"]}\n'
101 
102  text += f'Entire Network:\n'
103  text += f' P30: {params["Pre-Iso Total Fracture Density (P30)"]:0.2e} / '
104  text += f'P32 : {params["Pre-Iso Total Fracture Intensity (P32)"]:0.2e} / '
105  text += f'P33: {params["Pre-Iso Total Fracture Porosity (P33)"]:0.2e}\n'
106 
107  text += f'Connected Network:\n'
108  text += f' P30: {params["Post-Iso Total Fracture Density (P30)"]:0.2e} / '
109  text += f'P32: {params["Post-Iso Total Fracture Intensity (P32)"]:0.2e} / '
110  text += f'P33: {params["Post-Iso Total Fracture Porosity (P33)"]:0.2e}\n'
111 
112  return text
113 
114 
115 def add_network_page(params, pdf):
116  """ Add page about the entire network
117  Parameters
118  ------------
119  params : dictionary
120  General dictionary of output analysis code. Contains information on number of families, number of fractures, and colors.
121  pdf : fpdf object
122  Current working pdf
123 
124  Returns
125  ---------
126  pdf : fpdf object
127  Current working pdf
128 
129  Notes
130  ------
131  None
132  """
133 
134  # All Fractures
135  if params["verbose"]:
136  print(f"--> Working on Entire Network")
137  pdf.add_page()
138  pdf.text(x=120, y=20, txt=f'Network Summary')
139 
140  pdf.image(f"{params['output_dir']}/network/all_fracture_centers.png",
141  x=10,
142  y=30,
143  w=140)
144  pdf.image(f"{params['output_dir']}/network/network_all_radii.png",
145  x=150,
146  y=27,
147  w=140)
148  pdf.image(f"{params['output_dir']}/network/network_orientations.png",
149  x=0,
150  y=130,
151  w=150)
152 
153  text = create_network_text(params)
154 
155  pdf.set_xy(x=165, y=110)
156  pdf.set_font('Times', size=14)
157  pdf.multi_cell(0, 7, text, 1)
158 
159  return pdf
160 
161 
162 def create_family_text(family):
163  """ Creates block text for one family
164 
165 
166  Parameters
167  -------------
168  family : dictionary
169  Fracture family dictionary
170 
171  Returns
172  -----------
173  text : string
174  Block of text with information about the family.
175 
176  Notes
177  --------
178  None
179 
180  """
181  keys = family.keys()
182  dist = family["Distribution"]
183  text = f'Number of Fractures: {family["final_number_of_fractures"]}, Shape: {family["Shape"]}\n'
184  text += f'Radii Distribution: {dist}\n'
185  if dist == 'Truncated Power-Law':
186  text += f'\t - alpha: {family["Alpha"]}\n'
187  elif dist == 'Lognormal':
188  text += f'\t - mu: {family["Mean"]}, sigma: {family["Standard Deviation"]}\n'
189  elif dist == 'Exponential':
190  text += f'\t - lambda: {family["Lambda"]}\n'
191  if dist != "Constant":
192  text += f'\t - Min. Radius: {family["Minimum Radius (m)"]} m, Max. Radius: {family["Maximum Radius (m)"]} m\n'
193  text += f'Orientation - Kappa: {family["Kappa"]}, Theta-deg: {family["Theta-deg"]}, Phi-deg: {family["Phi-deg"]}\n'
194 
195  if "P32 (Fracture Intensity) Target" in keys:
196  text += f'Target P32: {family["P32 (Fracture Intensity) Target"]}, Final P32: {family["Post-Iso Fracture Intensity (P32)"]}'
197  else:
198  text += f'Final P32: {family["Post-Iso Fracture Intensity (P32)"]}\n'
199  return text
200 
201 
202 def add_family_page(params, family, i, pdf):
203  """ Add page about fracture family.
204 
205  Parameters
206  ------------
207  params : dictionary
208  General dictionary of output analysis code. Contains information on number of families, number of fractures, and colors.
209  family : dictionary
210  Dictionary of information about a fracture family
211  i : int
212  Fracture family id
213  pdf : fpdf object
214  Current working pdf
215 
216  Returns
217  ---------
218  pdf : fpdf object
219  Current working pdf
220 
221  Notes
222  ------
223  None
224  """
225 
226  if params["verbose"]:
227  print(f"--> Working on Family {family['Global Family']}")
228  pdf.add_page()
229  pdf.text(x=120, y=20, txt=f'Fracture Family Number {i}')
230  pdf.image(f"{params['output_dir']}/family_{i}/family_{i}_centers.png",
231  x=5,
232  y=30,
233  w=140)
234  if family["Distribution"] != "Constant":
235  pdf.image(f"{params['output_dir']}/family_{i}/family_{i}_radii.png",
236  x=160,
237  y=30,
238  w=140)
239  pdf.image(f"{params['output_dir']}/family_{i}/family_{i}_orienations.png",
240  x=0,
241  y=130,
242  w=140)
243  text = create_family_text(family)
244  pdf.set_xy(x=165, y=130)
245  pdf.set_font('Times', size=14)
246  pdf.multi_cell(0, 7, text, 1)
247  return pdf
248 
249 
250 def add_fram_page(params, pdf):
251  """ Add Page about FRAM information
252 
253  Parameters
254  ------------
255  params : dictionary
256  General dictionary of output analysis code. Contains information on number of families, number of fractures, and colors.
257  pdf : fpdf object
258  Current working pdf
259 
260  Returns
261  ---------
262  pdf : fpdf object
263  Current working pdf
264 
265  Notes
266  ------
267  None
268  """
269 
270  if params["verbose"]:
271  print("--> FRAM information")
272 
273  pdf.add_page()
274  pdf.text(x=120, y=20, txt=f'FRAM Information')
275  pdf.image(f"{params['output_dir']}/network/fram_information.png",
276  x=20,
277  y=40,
278  w=280)
279  return pdf
280 
281 
282 def make_pdf(params, families, fractures):
283  """ Combines plots and information to make the final output report pdf.
284 
285  Parameters
286  ------------
287  params : dictionary
288  General dictionary of output analysis code. Contains information on number of families, number of fractures, and colors.
289 
290  families: list of fracture family dictionaries
291  Created by get_family_information
292 
293  fractures: list of fracture dictionaries
294  Created by get_fracture_information
295 
296  Returns
297  --------
298  None
299 
300  Notes
301  -------
302  None
303 
304  """
305 
306  print("\n--> Combing Images and Making PDF")
307  # name needs to be a global so it's in the header of each page in the PDF
308  global name
309  name = params["jobname"]
310 
311  pdf = PDF(orientation="L")
312  pdf = add_table_of_contents(params, pdf)
313  pdf = add_network_page(params, pdf)
314 
315  # Family Information
316  for i in range(1, params["num_families"] + 1):
317  pdf = add_family_page(params, families[i - 1], i, pdf)
318 
319  pdf = add_fram_page(params, pdf)
320 
321  # Save PDF
322  pdf.output(f"{name}_output_report.pdf", "F")
def add_family_page(params, family, i, pdf)
Definition: make_pdf.py:202
def make_pdf(params, families, fractures)
Definition: make_pdf.py:282