def table(self, pdf: FPDF, header: list, data): pdf.set_fill_color(200) pdf.set_line_width(.3) pdf.set_font('', 'B') w = [15, 100, 45, 25] for i in range(len(header)): pdf.cell(w[i], 7, header[i], 1, 0, 'C') pdf.ln() pdf.set_font('') fill = False for row in data: if pdf.get_y() > 250: border = 'LRT' else: border = 'LR' pdf.cell(w[0], 6, str(row.inventory_supply.id), border, 0, 'L', fill) pdf.cell(w[1], 6, self.removeSpecialCharacters(row.inventory_supply.name), border, 0, 'L', fill) username = "******" if row.checked_by is None else self.removeSpecialCharacters( row.checked_by.username) pdf.cell(w[2], 6, username, border, 0, 'C', fill) pdf.cell(w[3], 6, '', border, 0, 'C', fill) pdf.ln() fill = not fill if pdf.get_y() > 250: pdf.cell(sum(w), 0, '', 'T', 1) pdf.cell(sum(w), 0, '', 'T')
def write_to_pdf(data: dict, filename: str): pdf = FPDF() effective_page_width = pdf.w - 2 * pdf.l_margin pdf.compress = False pdf.add_page() pdf.add_font("TimesNewRoman", '', 'TimesNewRoman.ttf', uni=True) pdf.set_font("TimesNewRoman", size=30) pdf.cell(w=0, txt=data['title']) pdf.ln(30) pdf.set_line_width(1) pdf.set_draw_color(255, 0, 0) for index_news, news_dict in enumerate(data['items']): pdf.set_font("TimesNewRoman", size=20) pdf.line(20, pdf.get_y() - 10, effective_page_width, pdf.get_y() - 10) pdf.multi_cell(effective_page_width, 10, news_dict['title']) if news_dict['contain_image']: download_image_and_paste_in_pdf(pdf, news_dict, index_news) pdf.multi_cell(effective_page_width, 10, news_dict['published']) pdf.multi_cell(effective_page_width, 10, news_dict['summary'][news_dict['summary'].rfind(']') + 1:]) pdf.set_font("TimesNewRoman", size=15) pdf.ln(5) pdf.multi_cell(effective_page_width, 10, 'Link on news:\n' + news_dict['link']) if news_dict['contain_image']: pdf.multi_cell(effective_page_width, 10, 'Link on image:\n' + news_dict['link_on_image']) pdf.ln(40) try: pdf.output(filename, 'F') except PermissionError: raise RssReaderException.FileException(f'close file:\n{filename}')
def export_customer_tags(query): pdf = FPDF(orientation ='P', unit = 'mm', format='Letter') pdf.set_margins(left=4, top=8, right=5) pdf.set_auto_page_break(auto = True, margin = 10) pdf.add_page() pdf.set_font('Arial', '', 10) x_ref = pdf.get_x() width_tag = 69.6 count = 0 y_ref = pdf.get_y() count_tag = 0 for customer in query: if count_tag % 30 == 0 and count_tag > 0: pdf.add_page() #text = 'Prezado Alisson Barbosa\nRua das Orquídeas, 57\nJardim das Plantas\nCampina Grande - PB\n58415-000' text = '{}\n{}, {}\n{}\n{}\n{}'.format(customer.name, customer.street, customer.number, customer.neighborhood, customer.city, customer.cep) if count == 0: x_ref = pdf.get_x() y_ref = pdf.get_y() count += 1 elif count == 1: x_ref += width_tag count += 1 elif count == 2: x_ref += width_tag count = 0 pdf.set_xy(x = x_ref, y = y_ref) pdf.multi_cell(width_tag, 5.195, text, 0, 'L') count_tag += 1 response = HttpResponse(pdf.output(dest='S').encode('latin-1')) response['Content-Disposition'] = 'attachment;filename="Etiquetas.pdf"' return response
def generateDicePDF(): # save FPDF() class into # a variable pdf pdf = FPDF() pdf.add_page() pdf.add_font('Braille', '', 'static/Swell-Braille.ttf', uni=True) # set style and size of font # that you want in the pdf pdf.set_font("Arial", size=30) pdf.multi_cell(200, 5, txt='Braille Labels for Dice/Spinner\n\n', align='C') pdf.set_font("Arial", size=10) pdf.multi_cell( 200, 5, txt='Cut out Braille labels and paste them onto the dice/spinner.\n\n', align='C') index = 0 theText = ['0', '0'] f = open("static/userData/brailleForDice.txt", "r") # insert the texts in pdf theX = pdf.get_x() theY = pdf.get_y() for x in f: if theX >= 170: theX = 5 theY += 15 if theY >= 260: pdf.add_page() theY = 15 if index == 0: pdf.set_xy(theX - 5, theY) if index > 0: pdf.set_xy(theX + 17, theY) if index % 6 == 0: if int(theText[0]) > 9: theY += 15 theX = 5 pdf.set_xy(theX, theY) theX = pdf.get_x() theY = pdf.get_y() theText = x.split(':') pdf.set_font("Arial", size=8) pdf.multi_cell(15, 10, txt=theText[0], align='R') pdf.set_font('Braille', '', size=24) pdf.set_xy(theX + 15, theY) theX = pdf.get_x() theY = pdf.get_y() pdf.multi_cell(27, 10, txt=theText[1], align='L', border=1) index += 1 # save the pdf with name .pdf pdf.output("static/userData/theDiceSpinner.pdf")
def createPDF(): pdf = FPDF() pdf.add_page() pdf.set_font('Times', 'BI', 11) # write file... contact = open("./user.txt", "r") for a in contact: pdf.multi_cell(200, 5, txt=a, align='C') contact.close() education = open('./education.txt', 'r') pdf.cell(200, 5, txt="Education", align='L') y = pdf.get_y() pdf.line(200, y + 5, 5, y + 5) pdf.set_font('Times', '', 10) for b in education: pdf.multi_cell(200, 5, txt=b, align='L') education.close() pdf.set_font('Times', 'BI', 11) pdf.cell(200, 5, txt="Selected Independent Projects", align='L') y = pdf.get_y() pdf.line(200, y + 5, 5, y + 5) projects = open('./project.txt', 'r') pdf.set_font('Times', '', 10) for c in projects: pdf.multi_cell(200, 5, txt=c, align='L') projects.close() pdf.set_font('Times', 'BI', 11) pdf.cell(200, 5, txt="Experience", align='L') y = pdf.get_y() pdf.line(200, y + 5, 5, y + 5) experience = open('./work.txt', 'r') pdf.set_font('Times', '', 10) for d in experience: pdf.multi_cell(200, 5, txt=d, align='L') experience.close() pdf.set_font('Times', 'BI', 11) pdf.cell(200, 5, txt="Skills", align='L') y = pdf.get_y() pdf.line(200, y + 5, 5, y + 5) skills = open('./skill.txt', "r") pdf.set_font('Times', '', 10) for e in skills: pdf.multi_cell(200, 5, txt=e, align='L') skills.close() try: pdf.output("resume.pdf", "F") return "Success" except: return "Error"
def pokepdf(pokemon): # FPDF Object pdf = FPDF("L", "mm", "A5") # Add page pdf.add_page() # Paint the background pdf.set_fill_color(*color.get(pokemon["type"][0], (255, ))) pdf.rect(0, 0, 210, 297, "F") # Set font pdf.set_font(*fonts["title"]) pdf.set_xy(20, 10) # Add Pokeball ball = {False: "pokeball", True: "masterball"}[pokemon["legendary"]] pdf.image(f"images/balls/{ball}.png", pdf.get_x(), pdf.get_y() + 25, w=20) # Add Pokemon Name pdf.cell(w=0, txt=f"{pokemon['id']} - {pokemon['name']}".title(), align="C", ln=1) # Add Pokemon Sprite pdf.image(pokemon["sprite_url"], 80, pdf.get_y() + 10, w=50) # Set new font font = fonts["flavor"] pdf.set_font(*font) pdf.set_xy(10, 70) # Cut text if larger than page flavor = chunks(pokemon["flavor"], font) # Add flavor text for i in flavor: pdf.cell(w=0, h=5, txt=i, align="C", ln=2) # Add type symbols for i, typ in enumerate(pokemon["type"]): if len(pokemon["type"]) == 1: pos = [90] else: pos = [50, 120] pdf.image(f"images/types/{typ}.png", pos[i], pdf.get_y() + 15, w=40) # Export pdf path = f"output/{pokemon['id']}_{pokemon['name']}.pdf" pdf.output(path) print(f"pdf saved to {path}")
def test_graphics_context(tmp_path): pdf = FPDF() pdf.add_page() pdf.set_font("helvetica", "", 12) pdf.set_text_color(0x00, 0xFF, 0x00) pdf.set_fill_color(0xFF, 0x88, 0xFF) pdf.set_y(20) pdf.cell(txt="outer 01", new_x=XPos.LMARGIN, new_y=YPos.NEXT, fill=True) with pdf.local_context(): pdf.set_font("courier", "BIU", 30) pdf.set_text_color(0xFF, 0x00, 0x00) pdf.set_fill_color(0xFF, 0xFF, 0x00) pdf.cell(txt="inner 01", new_x=XPos.LMARGIN, new_y=YPos.NEXT, fill=True) pdf.set_x(70) with pdf.rotation(30, pdf.get_x(), pdf.get_y()): pdf.set_fill_color(0x00, 0xFF, 0x00) pdf.cell(txt="inner 02", new_x=XPos.LMARGIN, new_y=YPos.NEXT, fill=True) pdf.set_stretching(150) pdf.cell(txt="inner 03", new_x=XPos.LMARGIN, new_y=YPos.NEXT, fill=True) pdf.cell(txt="outer 02", new_x=XPos.LMARGIN, new_y=YPos.NEXT, fill=True) assert_pdf_equal(pdf, HERE / "graphics_context.pdf", tmp_path)
def align_right(msg: Message, time: int, pdf: FPDF): """ Writes the given text into the PDF file. Aligns text right. Handles Image :param msg: The Message Object for sender and text :param time: Time stamp :param pdf: The open PDF file :return: Nothing """ global old text = "[{0}] {1}:".format( str(datetime.fromtimestamp(int(str(time)[:10])))[:16], msg.get_name()) if old != text: pdf.set_font(config.FONT, size=config.FONT_CHATTER) pdf.multi_cell(200, config.FONT_CHATTER, txt=text, align='R') old = text pdf.set_font(config.FONT, size=config.FONT_SIZE) if msg.is_img(): if 150 + pdf.get_y() > config.A4_HEIGHT: pdf.add_page() pdf.image(msg.get_msg(), w=config.WIDTH, h=config.HEIGHT, x=config.A4_WIDTH - 100) else: pdf.multi_cell(200, config.FONT_SIZE, txt="{}".format(msg.get_msg()), align='R')
def __measure_high_of_examples(self, examplesToPrint, width_of_example): ''' Stub function to simulate high of one column with examples. :param [string] examplesToPrint: The list with math examples. :param float width_of_example: The width of one example. :return float: High of first column the examples write in columns. ''' # open and configure PDF for measurement pdfMeasurement = FPDF('P', 'mm', 'A4') self.__configuratePDF(pdfMeasurement) # iterate through examples and write first column for example_index in range(0, len(examplesToPrint), NUMBER_OF_COLUMN): # set actual width for writing pdfMeasurement.set_x(pdfMeasurement.l_margin) # write the example with symbol assign pdfMeasurement.multi_cell(width_of_example, LINE_OF_EXAMPLE_HIGH, examplesToPrint[example_index] + " =", align="R") # get actual y position in PDF size_y_block = pdfMeasurement.get_y() pdfMeasurement.close() return size_y_block
def get_centered_start_y(text_width, text): test_pdf = FPDF('P', METRIC, DOCUMENT_SIZE) test_pdf.add_font(FONT_NAME, '', FONT_LOCATION, uni=True) test_pdf.set_font(FONT_NAME, size=FONT_SIZE) test_pdf.set_auto_page_break(False) test_pdf.add_page() initial_y = test_pdf.get_y() test_pdf.multi_cell( text_width, TEXT_HEIGHT, text, 0, 'C', ) multi_cell_height = test_pdf.get_y() - initial_y start_y = int(round(0.5 * (DOCUMENT_SIZE[1] - multi_cell_height))) return int(round(0.5 * (DOCUMENT_SIZE[1] - multi_cell_height)))
def output_pdf(logger, all_news, about_website=None, file_name=None): """Function which create or overwrites PDF-file with selected fresh or cached news""" logger.info('Convert to PDF-format') pdf = FPDF() pdf.add_page() if about_website is not None: pdf.set_font("Arial", "B", size=14) pdf.set_fill_color(200, 220, 255) for value in about_website.values(): line = 1 pdf.cell(190, 8, txt=value, ln=line, align="C") line += 1 pdf.set_font("Arial", size=10) pdf.set_line_width(1) pdf.set_draw_color(35, 41, 153) for news in all_news: link = news['Source of image'] for key, value in news.items(): if key != 'Summary': pdf.multi_cell(190, 6, txt=f'{key}: {value}', align="L") else: position_y = pdf.get_y() try: filename, _ = urllib.request.urlretrieve(link) pdf.image(filename, 80, position_y, h=30, type='jpeg', link=link) pdf.ln(31) os.remove(filename) except Exception as ex: logger.warning("Error finding image: {}, {}.".format(type(ex), ex)) pdf.multi_cell(190, 6, txt=f'{key}: {value}', align="L") position_y = pdf.get_y() pdf.set_line_width(1) pdf.set_draw_color(35, 41, 153) pdf.line(10, position_y, 200, position_y) logger.info('Creating of PDF-file') try: pdf.output(file_name) logger.info('Converted successfully!') except Exception as ex: logger.error("PDF file writing error : {}, {}.".format(type(ex), ex))
def printExampleToPDF(self, examplesToPrint, language_manager, nameOfDirectory, numberOfCopies): ''' The method print example to PDF. :param [str] examplesToPrint: The list with math examples. :param Language_manager language_manager: Manager of language mutation and translation of sentence. :param str nameOfDirectory: Name of the user chosen output directory. :param int numberOfCopies: The number of copies to print. :return None: ''' # when the path to folder is empty. The files saves to working directory if nameOfDirectory == '': nameOfDirectory = '.' # create PDFs pdfExamples = FPDF('P', 'mm', 'A4') pdfResults = FPDF('P', 'mm', 'A4') # cofigurate PDFs self.__configuratePDF(pdfExamples) self.__configuratePDF(pdfResults) # width of page without margins effective_page_width = pdfExamples.w - 2 * pdfExamples.l_margin # width of example with place for result width_of_example = (effective_page_width / NUMBER_OF_COLUMN) - WIDTH_OF_RESULT # Y position before start writing y_before = pdfExamples.get_y() # Measure high of examples block. Need for making copies. y_size = self.__measure_high_of_examples(examplesToPrint, width_of_example) # write example and results to PDF self.__writeExamplesToPDF(y_before, y_size, pdfExamples, examplesToPrint, width_of_example, effective_page_width, numberOfCopies) self.__writeResultsToPDF(y_before, pdfResults, examplesToPrint, width_of_example, effective_page_width) # save pdf to directory pdfExamples.output( nameOfDirectory + "/" + self.__create_name_of_file(language_manager) + "_examples.pdf", 'F') pdfResults.output( nameOfDirectory + "/" + self.__create_name_of_file(language_manager) + "_results.pdf", 'F')
def createExercices(problems): exercises_per_column = 28 columns = 5 column_width = 50 cell_height = 7 number_width = 6 spacer = 2 pdf = FPDF(orientation="L") pdf.set_top_margin(5) pdf.set_auto_page_break(True, 1) pdf.add_page() pdf.set_font("Arial", size=12) start_x = pdf.get_x() start_y = pdf.get_y() for i in range(len(problems)): problem = problems[i] pdf.set_xy(start_x + int(i / exercises_per_column) * column_width, start_y + (i % exercises_per_column) * cell_height) border = "R" if (int(i / exercises_per_column) == columns - 1): border = 0 if (problem.unknown == UnknownElement.Z): pdf.cell(spacer, cell_height) pdf.cell(number_width, cell_height, txt=str(problem.x), align="C") pdf.cell(number_width, cell_height, txt=str(problem.operator), align="C") pdf.cell(number_width, cell_height, txt=str(problem.y), align="C") pdf.cell(number_width, cell_height, "=", align="C") pdf.cell(column_width - 4 * number_width - spacer, cell_height, border=border) elif (problem.unknown == UnknownElement.X): pdf.cell(column_width - 4 * number_width - spacer, cell_height) pdf.cell(number_width, cell_height, txt=str(problem.operator), align="C") pdf.cell(number_width, cell_height, txt=str(problem.y), align="C") pdf.cell(number_width, cell_height, "=", align="C") pdf.cell(number_width, cell_height, str(problem.z), align="C") pdf.cell(spacer, cell_height, border=border) pdf.output("simple_demo.pdf")
def pdf(list,length): desktop = os.path.join(os.path.join(os.environ['USERPROFILE']), 'Desktop') pdf = FPDF() pdf.set_margins(4,5, 2) pdf.add_page() pdf.set_font("Times",'B', size=30) pdf.cell(200, 10, txt="Test Paper", ln=15, align="C") pdf.ln(5) pdf.set_font('Times', 'B', 20) pdf.cell(200, 10, txt="Short Answers", ln=15, align="C") pdf.ln(8) pdf.set_font('Times', 'I', 10) pdf.multi_cell(200, 10, txt="This test has been generated using the Questionnaire software.No answers are provided to the questions and it is upto the discretion of the candidate to decide upon the right answers.A short answer is of 3-4 sentences,so the answers should be brief",align ='J') pdf.ln(10) pdf.set_font('Times', 'B', 15) for i in range(length): pdf.multi_cell(200, 10, txt=str(i+1) + "." + " " + list[i]) pdf.ln(10) x = pdf.get_x() y = pdf.get_y() pdf.dashed_line(x,y,x+175,y,6) pdf.ln(10) pdf.output(desktop + "/" + "Questions" + ".pdf")
def test_pdf_cell(self): pdf=FPDF() pdf.c_margin = 0.0 pdf.add_font('symbol','','font/DejaVuSans.ttf',uni=True) pdf.add_page() f = 0.81 font_name = 'times' text = 'small text' pdf.set_font(font_name,'',12) x,y = pdf.get_x(), pdf.get_y() w = pdf.get_string_width(text) h = pdf.font_size_pt / pdf.k pdf.cell(w, h, text) pdf.rect(x, y, w, h, '') pdf.line(x, y + f * h, x + w, y + f * h) text = 'Large text' pdf.set_font(font_name,'',24) x,y = pdf.get_x(), pdf.get_y() w = pdf.get_string_width(text) h = pdf.font_size_pt / pdf.k pdf.cell(w,h, text) pdf.rect(x, y, w, h, '') pdf.line(x, y + f * h, x + w, y + f * h) text = 'Larger text' pdf.set_font(font_name,'',48) x,y = pdf.get_x(), pdf.get_y() w = pdf.get_string_width(text) h = pdf.font_size_pt / pdf.k pdf.cell(w,h, text) pdf.rect(x, y, w, h, '') pdf.line(x, y + f * h, x + w, y + f * h) pdf.output('out/fpdf/test_pdf_cell.pdf', 'F')
def makePDF(cls, PDFName): pdf = FPDF('P', 'mm', (220, 110)) for supporter in cls.Supporters: print(supporter.preference) envelope = [1, 2, 3, 4, 6, 7, 8, 9] if supporter.preference in envelope: pdf.add_page() font_size = 20 line_spacing = 8 pdf.set_font('Arial', 'B', font_size) pdf.set_xy(20, 20) x_orig = pdf.get_x() y_orig = pdf.get_y() print(x_orig) print(y_orig) pdf.cell(40, 0, supporter.fullname) addrLines = supporter.address.split("\n") for i in range(0, len(addrLines)): print(addrLines[i]) pdf.set_xy(x_orig, y_orig + line_spacing * (i + 1)) pdf.set_font('Arial', 'B', font_size) pdf.cell(40, 0, addrLines[i]) pdf.image('logo.jpg', 120, 35, 60, 60) pdf.set_font('Arial', '', 6) stamptext = "" if supporter.preference in [3, 4, 8, 9]: stamptext = "Hand" elif supporter.preference in [1, 6]: stamptext = "UK" elif supporter.preference in [2, 7]: stamptext = "Int" pdf.set_xy(180, 12) pdf.cell(15, 20, stamptext, border=1, align='C') pdf.set_xy(180, 14) pdf.cell(15, 20, "{}T {}P {}F".format(supporter.letters[0], supporter.letters[1], supporter.letters[2]), border=0, align='C') pdf.output(PDFName, 'F')
def send_statement_to_user(user, transactions_data): date = str(datetime.datetime.utcnow()) balance = str(transactions_data[0].balance) email = user.email pdf = FPDF() pdf.add_page() pdf.set_font("Arial", size=15) pdf.cell(200, 10, txt="Kuvera Bank", ln=1, align='C') pdf.cell(200, 10, txt="Date: " + date, ln=2) pdf.cell(200, 10, txt="Email: " + email, ln=3) pdf.cell(200, 10, txt="Balance: " + balance, ln=4) pdf.cell(200, 10, txt="S/N " + "TXN ID " + "Amount " + "Date", ln=5) for i in range(0, len(transactions_data)): ybefore = pdf.get_y() column_spacing = 5 pdf.multi_cell(20, 10, str(i + 1)) pdf.set_xy(20 + column_spacing + pdf.l_margin, ybefore) pdf.multi_cell(20, 10, str(transactions_data[i].id)) pdf.set_xy(2 * (20 + column_spacing) + pdf.l_margin, ybefore) pdf.multi_cell(50, 10, str(transactions_data[i].amount)) pdf.set_xy(2 * (50 + column_spacing) + pdf.l_margin, ybefore) pdf.multi_cell(100, 10, str(transactions_data[i].date_time)) pdf.output(str(transactions_data[0].u_id) + "_" + date + ".pdf") path = str(transactions_data[0].u_id) + "_" + date + ".pdf" recipients = [str(email)] msg = Message('Statement from Kuvera Bank', sender='*****@*****.**', recipients=recipients) msg.body = 'Please find attached your historical statememt' with open(os.getcwd() + "/" + path, 'rb') as fh: msg.attach(filename=path, disposition="attachment", content_type="application/pdf", data=fh.read()) mail.send(msg)
def __row(self, pdf: FPDF, row: DayGroupedEntry): default_height = self.__pdf_height(pdf) splits = split_string(row[4], 90) height = default_height * len(splits) pdf.cell(pdf.w * 0.08, height, txt=row[0], border=1) pdf.cell(pdf.w * 0.07, height, txt=row[1].__str__(), border=1) pdf.cell(pdf.w * 0.07, height, txt=row[2].__str__(), border=1) pdf.cell(pdf.w * 0.06, height, txt=row[3].__str__(), border=1) desc_w = pdf.w * 0.57 if len(splits) > 1: current_x = pdf.get_x() current_y = pdf.get_y() pdf.multi_cell(desc_w, default_height, txt=row[4], border=1) pdf.set_xy(current_x + desc_w, current_y) else: pdf.cell(desc_w, height, txt=row[4], border=1) pdf.cell(pdf.w * 0.06, height, txt=row[5].__str__(), border=1) pdf.ln(height)
pdf.set_font('Courier', 'B', 20) charWidth = pdf.get_string_width("W") lines = text_cipher.split("\n") for line in lines: words = line.split(" ") total_width = 0 pdf.set_x(margin) for word in words: width = pdf.get_string_width(word + " ") total_width += width #print(word + ": " + str(width) + ", " + str(total_width)) if (total_width >= (A4_width - 2 * margin)): #print('ln') pdf.ln() pdf.ln() total_width = width pdf.cell(width, line_height, word + " ", 0) if word == '': continue x1 = margin + total_width - width + offset x2 = margin + total_width - pdf.get_string_width(" ") + offset y1 = pdf.get_y() + 1.8 * line_height y2 = y1 pdf.line(x1, y1, x2, y2) y2 -= line_height * 0.5 for i in range(len(word) + 1): pdf.line(x1 + charWidth * i, y1, x1 + charWidth * i, y2) pdf.ln() pdf.ln() pdf.output('cipher_text.pdf', 'F')
# Long meaningless piece of text header = f""" Invoice #: {args.number} Invoice Date: {args.idate} Due Date: {args.ddate} """ effective_page_width = pdf.w - 2 * pdf.l_margin me = f""" {allData[0]} {allData[1]} {allData[2]} """ ybefore = pdf.get_y() pdf.set_font('Times', '', 12.0) pdf.multi_cell(effective_page_width / 2, 0.15, me) bank = f""" Routing #: {allData[3]} Account #: {allData[4]} Please contact {allData[5]} for other means of payment """ pdf.set_font('Times', 'B') pdf.multi_cell(effective_page_width / 2, 0.15, bank) pdf.ln(0.25)
# title is generated with today's date time picks_file = "reptilinks-picks-" + now.strftime("%Y-%m-%d %H%M%S") + ".pdf" title = "Orders: " + str(order_num_min) + " - " + str(order_num_max) # refer to https://pyfpdf.readthedocs.io/en/latest docs # for more information on how to use their libary to format a pdf pdf = FPDF(format="Letter") pdf.add_page() pdf.set_font('Times', '', 8) pdf.cell(70, 5, title, 0, 1) ############################################ # regular ############################################ x = pdf.get_x() y = pdf.get_y() # refer to layout.py file for PrintCells function def (xr, yr) = layout.PrintCells(pdf, "Regular", regular_products, x, y, y) ############################################ # Mini ############################################ (xm, ym) = layout.PrintCells(pdf, "Mini", mini_products, xr, yr, y) ############################################ # Non link ############################################ (xn, yn) = layout.PrintCells(pdf, "Non-link", non_sausage, xm, ym, y) ############################################
def make_pdf(self, a1): pdf = FPDF() pdf.add_page() pdf.set_xy(10, 15) pdf.set_font('arial', 'B', 16) pdf.cell(0, 10, 'Instrument description', 0, 2, 'C') pdf.set_font('arial', '', 12) pdf.set_x(15) pdf.cell(0, 6, 'Issuer: ' + self.issuer, 0, 2, 'L') pdf.cell(0, 6, 'ISIN: ' + self.name, 0, 2, 'L') pdf.cell(0, 6, '', 0, 2, 'L') pdf.cell(0, 6, 'Currency: ' + self.notional_curr, 0, 2, 'L') pdf.cell( 0, 6, 'Term: ' + str(self.term) + (' year ' if self.term == 1 else ' years'), 0, 2, 'L') pdf.cell(0, 6, ('Asset: ' if len(self.BAs) == 1 else 'Assets: ') + ', '.join(self.BAs), 0, 2, 'L') pdf.cell(0, 6, '', 0, 2, 'L') if self.coupon_value == 0: pdf.cell(0, 6, 'Coupon: no\n', 0, 2, 'L') if self.coupon_value > 0: txt_coupon = (('Coupon: %.2f%%' % (self.coupon_value * 100)) + ((' every %d months\n' % self.check_months) if self.check_months > 1 else ' every month\n')) if self.coupon_always == 1: pdf.cell(0, 6, txt_coupon, 0, 2, 'L') if self.coupon_always == 0: txt2 = ('Conditional coupon: yes\nMemory effect: ' + ('yes' if self.coupon_memory == 1 else 'no') + '\nCoupon barrier: %.f%%' % (self.coupon_lower_barrier * 100)) pdf.multi_cell(75, 6, txt_coupon + txt2, 1, 2, 'L') pdf.cell(0, 6, '', 0, 2, 'L') pdf.set_xy(15, pdf.get_y()) if self.autocall_flag == 0: pdf.cell(0, 6, 'Autocallable: no\n', 0, 2, 'L') else: txt2 = (('Autocallable: yes\n') + (('Autocall level: %.f%%\n' % (self.autocall_barrier * 100)) if self.autocall_barrier_increase_rate == 0 else (('Initial autocall level: %.f%%\n' % (self.autocall_barrier * 100)) + (('Autocall level increase step: %.f%%\n' % (self.autocall_barrier_increase_rate * 100)) if self.autocall_barrier_increase_rate > 0 else ('Autocall level decrease step: %.f%%\n' % (-self.autocall_barrier_increase_rate * 100)))))) pdf.multi_cell(75, 6, txt2, 1, 2, 'L') # погашение: txt0 = ('Capital protection level: %.f%%\n' % (self.redemption_amount * 100)) if self.redemption_put_strike > 0: txt1 = (('Capital protection barrier: %.f%%\n' % (self.redemption_put_strike * 100)) + ('Redemption rule below barrier: ') + ('worst performance' if self.redemption_guarantee_rule == 1 else ('(worst performance) / (protection barrier)' if self.redemption_guarantee_rule == 2 else ('')))) else: txt1 = '' txt21 = (('Downside participation: %.f%%\n' % (self.redemption_downside_participation * 100)) if self.redemption_downside_participation > 0 else '') txt22 = (('Upside participation: %.f%%\n' % (self.redemption_upside_participation * 100)) if self.redemption_upside_participation > 0 else '') txt = txt0 + txt1 + txt21 + txt22 pdf.cell(0, 6, '', 0, 2, 'L') pdf.set_xy(15, pdf.get_y()) pdf.multi_cell((75 + 75 * (txt1 != '')), 6, txt, (txt != txt0), 2, 'L') # погашение - закончили pdf.cell(0, 6, '', 0, 2, 'L') pdf.set_xy(15, pdf.get_y()) pdf.cell(0, 6, ('Theoretical price: %.2f%%' % (a1.sum(axis=0).mean() * 100)), 0, 2, 'L') #pdf.cell(0, 6, ('Max payoff: %.2f%%' % ((a1.sum(axis = 0).max())*100)), 0, 2, 'L') pdf.cell(0, 6, '', 0, 2, 'L') pdf.cell(90, 10, " ", 0, 2, 'C') pdf.cell(-30) fig = figure(figsize=(16, 10)) plt.yticks([]) plt.xticks(fontname="Arial", fontsize=24) chart_name = self.name + ' NPV distribution' title(self.name + ' NPV distribution', fontname="Arial", fontsize=24) bins = np.linspace(0, 1.5, 75) plt.hist(a1.sum(axis=0), bins, alpha=1, color='salmon') plt.savefig('results/' + self.name + ' payoff.png') plt.close(fig) pdf.image('results/' + self.name + ' payoff.png', x=2, y=170, w=200, h=0, type='', link='') pdf.output('results/' + self.name + ' description sheet', 'F') os.remove('results/' + self.name + ' payoff.png')
class Report: def __init__(self, data): self.output_path = os.path.join(data.data_path, "stats") self.dataset_name = os.path.basename(data.data_path) self.mapi_light_light_green = [210, 245, 226] self.mapi_light_green = [5, 203, 99] self.mapi_light_grey = [218, 222, 228] self.mapi_dark_grey = [99, 115, 129] self.pdf = FPDF("P", "mm", "A4") self.pdf.add_page() self.title_size = 20 self.h1 = 16 self.h2 = 13 self.h3 = 10 self.text = 10 self.small_text = 8 self.margin = 10 self.cell_height = 7 self.total_size = 190 self.stats = self._read_stats_file("stats.json") def save_report(self, filename): self.pdf.output(os.path.join(self.output_path, filename), "F") def _make_table(self, columns_names, rows, row_header=False): self.pdf.set_font("Helvetica", "", self.h3) self.pdf.set_line_width(0.3) columns_sizes = [int(self.total_size / len(rows[0]))] * len(rows[0]) if columns_names: self.pdf.set_draw_color(*self.mapi_light_grey) self.pdf.set_fill_color(*self.mapi_light_grey) for col, size in zip(columns_names, columns_sizes): self.pdf.rect( self.pdf.get_x(), self.pdf.get_y(), size, self.cell_height, style="FD", ) self.pdf.set_text_color(*self.mapi_dark_grey) self.pdf.cell(size, self.cell_height, col, align="L") self.pdf.set_xy(self.margin, self.pdf.get_y() + self.cell_height) self.pdf.set_draw_color(*self.mapi_light_grey) self.pdf.set_fill_color(*self.mapi_light_light_green) for row in rows: for i, (col, size) in enumerate(zip(row, columns_sizes)): if i == 0 and row_header: self.pdf.set_draw_color(*self.mapi_light_grey) self.pdf.set_fill_color(*self.mapi_light_grey) self.pdf.rect( self.pdf.get_x(), self.pdf.get_y(), size, self.cell_height, style="FD", ) self.pdf.set_text_color(*self.mapi_dark_grey) if i == 0 and row_header: self.pdf.set_draw_color(*self.mapi_light_grey) self.pdf.set_fill_color(*self.mapi_light_light_green) self.pdf.cell(size, self.cell_height, col, align="L") self.pdf.set_xy(self.margin, self.pdf.get_y() + self.cell_height) def _read_stats_file(self, filename): file_path = os.path.join(self.output_path, filename) with io.open_rt(file_path) as fin: return io.json_load(fin) def _make_section(self, title): self.pdf.set_font("Helvetica", "B", self.h1) self.pdf.set_text_color(*self.mapi_dark_grey) self.pdf.cell(0, self.margin, title, align="L") self.pdf.set_xy(self.margin, self.pdf.get_y() + 1.5 * self.margin) def _make_subsection(self, title): self.pdf.set_xy(self.margin, self.pdf.get_y() - 0.5 * self.margin) self.pdf.set_font("Helvetica", "B", self.h2) self.pdf.set_text_color(*self.mapi_dark_grey) self.pdf.cell(0, self.margin, title, align="L") self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin) def _make_centered_image(self, image_path, desired_height): width, height = PIL.Image.open(image_path).size resized_width = width * desired_height / height if resized_width > self.total_size: resized_width = self.total_size desired_height = height * resized_width / width self.pdf.image( image_path, self.pdf.get_x() + self.total_size / 2 - resized_width / 2, self.pdf.get_y(), h=desired_height, ) self.pdf.set_xy(self.margin, self.pdf.get_y() + desired_height + self.margin) def make_title(self): # title self.pdf.set_font("Helvetica", "B", self.title_size) self.pdf.set_text_color(*self.mapi_light_green) self.pdf.cell(0, self.margin, "OpenSfM Quality Report", align="C") self.pdf.set_xy(self.margin, self.title_size) # version number try: out, _ = subprocess.Popen( ["git", "describe", "--tags"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, ).communicate() version = out.strip().decode() except BaseException as e: logger.warning( f"Exception thrwon while extracting 'git' version, {e}") version = "" # indicate we don't know the version version = "unknown" if version == "" else version self.pdf.set_font("Helvetica", "", self.small_text) self.pdf.set_text_color(*self.mapi_dark_grey) self.pdf.cell(0, self.margin, f"Processed with OpenSfM version {version}", align="R") self.pdf.set_xy(self.margin, self.pdf.get_y() + 2 * self.margin) def make_dataset_summary(self): self._make_section("Dataset Summary") rows = [ ["Dataset", self.dataset_name], ["Date", self.stats["processing_statistics"]["date"]], [ "Area Covered", f"{self.stats['processing_statistics']['area']/1e6:.6f} km²", ], [ "Processing Time", f"{self.stats['processing_statistics']['steps_times']['Total Time']:.2f} seconds", ], ] self._make_table(None, rows, True) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin) def _has_meaningful_gcp(self): return (self.stats["reconstruction_statistics"]["has_gcp"] and "average_error" in self.stats["gcp_errors"]) def make_processing_summary(self): self._make_section("Processing Summary") rec_shots, init_shots = ( self.stats["reconstruction_statistics"] ["reconstructed_shots_count"], self.stats["reconstruction_statistics"]["initial_shots_count"], ) rec_points, init_points = ( self.stats["reconstruction_statistics"] ["reconstructed_points_count"], self.stats["reconstruction_statistics"]["initial_points_count"], ) geo_string = [] if self.stats["reconstruction_statistics"]["has_gps"]: geo_string.append("GPS") if self._has_meaningful_gcp(): geo_string.append("GCP") rows = [ [ "Reconstructed Images", f"{rec_shots} over {init_shots} shots ({rec_shots/init_shots*100:.1f}%)", ], [ "Reconstructed Points", f"{rec_points} over {init_points} points ({rec_points/init_points*100:.1f}%)", ], [ "Reconstructed Components", f"{self.stats['reconstruction_statistics']['components']} component", ], [ "Detected Features", f"{self.stats['features_statistics']['detected_features']['median']} features", ], [ "Reconstructed Features", f"{self.stats['features_statistics']['reconstructed_features']['median']} features", ], ["Geographic Reference", " and ".join(geo_string)], ] row_gps_gcp = [" / ".join(geo_string) + " errors"] geo_errors = [] if self.stats["reconstruction_statistics"]["has_gps"]: geo_errors.append( f"{self.stats['gps_errors']['average_error']:.2f}") if self._has_meaningful_gcp(): geo_errors.append( f"{self.stats['gcp_errors']['average_error']:.2f}") row_gps_gcp.append(" / ".join(geo_errors) + " meters") rows.append(row_gps_gcp) self._make_table(None, rows, True) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin / 2) topview_height = 130 topview_grids = [ f for f in os.listdir(self.output_path) if f.startswith("topview") ] self._make_centered_image( os.path.join(self.output_path, topview_grids[0]), topview_height) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin) def make_processing_time_details(self): self._make_section("Processing Time Details") columns_names = list( self.stats["processing_statistics"]["steps_times"].keys()) formatted_floats = [] for v in self.stats["processing_statistics"]["steps_times"].values(): formatted_floats.append(f"{v:.2f} sec.") rows = [formatted_floats] self._make_table(columns_names, rows) self.pdf.set_xy(self.margin, self.pdf.get_y() + 2 * self.margin) def make_gps_details(self): self._make_section("GPS/GCP Errors Details") # GPS for error_type in ["gps", "gcp"]: rows = [] columns_names = [error_type.upper(), "Mean", "Sigma", "RMS Error"] if "average_error" not in self.stats[error_type + "_errors"]: continue for comp in ["x", "y", "z"]: row = [comp.upper() + " Error (meters)"] row.append( f"{self.stats[error_type + '_errors']['mean'][comp]:.3f}") row.append( f"{self.stats[error_type +'_errors']['std'][comp]:.3f}") row.append( f"{self.stats[error_type +'_errors']['error'][comp]:.3f}") rows.append(row) rows.append([ "Total", "", "", f"{self.stats[error_type +'_errors']['average_error']:.3f}", ]) self._make_table(columns_names, rows) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin / 2) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin / 2) def make_features_details(self): self._make_section("Features Details") heatmap_height = 60 heatmaps = [ f for f in os.listdir(self.output_path) if f.startswith("heatmap") ] self._make_centered_image(os.path.join(self.output_path, heatmaps[0]), heatmap_height) if len(heatmaps) > 1: logger.warning("Please implement multi-model display") columns_names = ["", "Min.", "Max.", "Mean", "Median"] rows = [] for comp in ["detected_features", "reconstructed_features"]: row = [comp.replace("_", " ").replace("features", "").capitalize()] for t in columns_names[1:]: row.append( f"{self.stats['features_statistics'][comp][t.replace('.', '').lower()]:.0f}" ) rows.append(row) self._make_table(columns_names, rows) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin) def make_reconstruction_details(self): self._make_section("Reconstruction Details") rows = [ [ "Average reprojection Error", f"{self.stats['reconstruction_statistics']['reprojection_error']:.2f} pixels", ], [ "Average Track Length", f"{self.stats['reconstruction_statistics']['average_track_length']:.2f} images", ], [ "Average Track Length (> 2)", f"{self.stats['reconstruction_statistics']['average_track_length_over_two']:.2f} images", ], ] self._make_table(None, rows, True) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin) def make_camera_models_details(self): self._make_section("Camera Models Details") for camera, params in self.stats["camera_errors"].items(): residual_grids = [ f for f in os.listdir(self.output_path) if f.startswith("residuals_" + str(camera.replace("/", "_"))) ] if not residual_grids: continue initial = params["initial_values"] optimized = params["optimized_values"] names = [""] + list(initial.keys()) rows = [] rows.append(["Initial"] + [f"{x:.4f}" for x in initial.values()]) rows.append(["Optimized"] + [f"{x:.4f}" for x in optimized.values()]) self._make_subsection(camera) self._make_table(names, rows) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin / 2) residual_grid_height = 80 self._make_centered_image( os.path.join(self.output_path, residual_grids[0]), residual_grid_height) def make_tracks_details(self): self._make_section("Tracks Details") matchgraph_height = 60 matchgraph = [ f for f in os.listdir(self.output_path) if f.startswith("matchgraph") ] self._make_centered_image( os.path.join(self.output_path, matchgraph[0]), matchgraph_height) histogram = self.stats["reconstruction_statistics"][ "histogram_track_length"] start_length, end_length = 2, 10 row_length = ["Length"] for length, _ in sorted(histogram.items(), key=lambda x: int(x[0])): if int(length) < start_length or int(length) > end_length: continue row_length.append(length) row_count = ["Count"] for length, count in sorted(histogram.items(), key=lambda x: int(x[0])): if int(length) < start_length or int(length) > end_length: continue row_count.append(f"{count}") self._make_table(None, [row_length, row_count], True) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin) def add_page_break(self): self.pdf.add_page("P") def generate_report(self): self.make_title() self.make_dataset_summary() self.make_processing_summary() self.add_page_break() self.make_features_details() self.make_reconstruction_details() self.make_tracks_details() self.add_page_break() self.make_camera_models_details() self.make_gps_details() self.make_processing_time_details()
class summaryClass: def __init__(self): from fpdf import FPDF self.pdf = FPDF() self.pdf.set_auto_page_break(False) self.currentRow = 0 self.claimCount = 1 self.database = db.database_class() def writeClaim(self, claim, diagCodes): self.database.insertAccession(claim.rowList[0]["ACCESSION_NUMBER"]) self.pdf.set_font('Arial', '', 8) self.pdf.set_xy(5, self.currentRow) self.pdf.line(5, self.currentRow, 280, self.currentRow) self.currentRow += 2 self.pdf.set_xy(5, self.currentRow) self.pdf.cell(5, 4, "[" + str(self.claimCount) + "]") self.pdf.set_xy(12, self.currentRow) self.pdf.cell(5, 4, str(claim.rowList[0]["ACCESSION_NUMBER"])) self.pdf.set_xy(38, self.currentRow) self.pdf.cell(5, 4, str(claim.rowList[0]["INSURANCE_PAYER_ID"])) self.pdf.set_xy(70, self.currentRow) self.pdf.cell(5, 4, str(claim.rowList[0]["PATIENT_LAST"])) self.pdf.set_xy(88, self.currentRow) self.pdf.cell(5, 4, str(claim.rowList[0]["PATIENT_FIRST"])) self.pdf.set_xy(110, self.currentRow) self.pdf.cell(5, 4, str(claim.rowList[0]["PATIENT_DOB"])) self.pdf.set_xy(132, self.currentRow) self.pdf.cell(5, 4, str(claim.rowList[0]["PATIENT_GENDER"])) self.pdf.set_xy(145, self.currentRow) self.pdf.cell(5, 4, str(claim.rowList[0]["REFER_PHY_FIRST"])) self.pdf.set_xy(160, self.currentRow) self.pdf.cell(5, 4, str(claim.rowList[0]["REFER_PHY_LAST"])) self.pdf.set_xy(190, self.currentRow) self.pdf.cell(5, 4, str(claim.rowList[0]["REFER_PHY_NPI"])) self.pdf.set_xy(220, self.currentRow) self.pdf.cell(5, 4, str(claim.rowList[0]["INSURANCE_PLAN_NAME"])) self.currentRow += 5 self.pdf.set_xy(70, self.currentRow) self.pdf.cell(5, 4, str(claim.rowList[0]["PATIENT_STREET_ADDR"])) self.pdf.set_xy(220, self.currentRow) self.pdf.cell(5, 4, str(claim.rowList[0]["INSURANCE_STREET_ADDR"])) self.currentRow += 5 self.pdf.set_xy(70, self.currentRow) self.pdf.cell(5, 4, str(claim.rowList[0]["PATIENT_CITY"])) self.pdf.set_xy(105, self.currentRow) self.pdf.cell(5, 4, str(claim.rowList[0]["PATIENT_STATE"])) self.pdf.set_xy(110, self.currentRow) self.pdf.cell(5, 4, str(claim.rowList[0]["PATIENT_ZIP"])) self.pdf.set_xy(220, self.currentRow) self.pdf.cell(5, 4, str(claim.rowList[0]["INSURANCE_CITY"])) self.pdf.set_xy(250, self.currentRow) self.pdf.cell(5, 4, str(claim.rowList[0]["INSURANCE_STATE"])) self.pdf.set_xy(258, self.currentRow) self.pdf.cell(5, 4, str(claim.rowList[0]["INSURANCE_ZIP"])) self.currentRow += 5 self.pdf.line(5, self.currentRow, 280, self.currentRow) self.currentRow += 2 self.pdf.set_xy(15, self.currentRow) self.pdf.cell(5, 4, "Diagnosis Codes:") xPos = 40 for i in range(len(diagCodes)): self.pdf.set_xy(xPos, self.currentRow) self.pdf.cell(5, 4, diagCodes[i]) xPos += 15 self.currentRow += 5 self.pdf.set_xy(15, self.currentRow) self.pdf.cell(5, 4, "CPT Code") self.pdf.set_xy(35, self.currentRow) self.pdf.cell(5, 4, "EMG Code") self.pdf.set_xy(55, self.currentRow) self.pdf.cell(5, 4, "Price") self.currentRow += 5 self.pdf.line(5, self.currentRow, 280, self.currentRow) self.currentRow += 3 for row in claim.rowList: self.pdf.set_xy(15, self.currentRow) self.pdf.cell(5, 4, str(row["CPT"])) self.pdf.set_xy(35, self.currentRow) self.pdf.cell(5, 4, str(row["EMG"])) self.pdf.set_xy(55, self.currentRow) self.pdf.cell(5, 4, str(row["PRICE"])) self.currentRow += 5 if self.pdf.get_y() > 155: self.pdf.add_page("L") self.pdf.set_xy(5, 10) self.currentRow = 5 self.currentRow += 10 self.claimCount += 1 def writeMast(self): self.pdf.add_page("L") self.pdf.set_font('Arial', 'B', 10) self.pdf.set_xy(5, 0) self.pdf.cell(5, 10, 'Claim Summary - ') self.pdf.set_xy(12, self.currentRow + 10) self.pdf.set_font('Arial', '', 8) self.pdf.cell(5, 4, "Accession #") self.pdf.set_xy(38, self.currentRow + 10) self.pdf.cell(5, 4, "Sub ID") self.pdf.set_xy(70, self.currentRow + 10) self.pdf.cell(5, 4, "Pat. Last") self.pdf.set_xy(88, self.currentRow + 10) self.pdf.cell(5, 4, "Pat. First") self.pdf.set_xy(110, self.currentRow + 10) self.pdf.cell(5, 4, "DOB") self.pdf.set_xy(132, self.currentRow + 10) self.pdf.cell(5, 4, "Gender") self.pdf.set_xy(145, self.currentRow + 10) self.pdf.cell(5, 4, "Ref Phy") self.pdf.set_xy(190, self.currentRow + 10) self.pdf.cell(5, 4, "Ref Phy NPI") self.pdf.set_xy(220, self.currentRow + 10) self.pdf.cell(5, 4, "Insurance") self.currentRow = 20 self.pdf.set_font('Arial', '', 10) def writePDF(self): self.pdf.output('claimSummary.pdf', 'F')
def printwork(self): pdf = FPDF(orientation='P', unit='mm', format='A4') pdf.set_auto_page_break(auto=True, margin=10) pdf.add_page() pdf.set_image_filter("DCTDecode") # heading -> Personal Information pdf.set_font("times", 'B', size=12) pdf.set_draw_color(0, 0, 0) pdf.set_fill_color(0, 0, 0) pdf.set_text_color(255, 255, 255) pdf.set_line_width(1) pdf.cell(190, 5, txt="Personal Information", border=1, ln=1, align="L", fill=1) # content -> personal Information pdf.set_text_color(0, 0, 0) pdf.set_font("Helvetica", 'B', size=11) pdf.cell(30, 6, txt="ID:", ln=0, align="L") pdf.set_font("Helvetica", '', size=11) pdf.cell(50, 6, txt=str(self.id), ln=0, align='L') pdf.set_font("Helvetica", 'B', size=11) pdf.cell(30, 6, txt="Name:", ln=0, align="L") pdf.set_font("Helvetica", '', size=11) pdf.cell(50, 6, txt=self.name, ln=1, align='L') pdf.set_font("Helvetica", 'B', size=11) pdf.cell(30, 5, txt="Gender:", ln=0, align="L") pdf.set_font("Helvetica", '', size=11) pdf.cell(50, 5, txt=self.sex, ln=0, align='L') pdf.set_font("Helvetica", 'B', size=11) pdf.cell(30, 5, txt="Age:", ln=0, align="L") pdf.set_font("Helvetica", '', size=11) pdf.cell(50, 5, txt=self.age, ln=1, align='L') pdf.set_font("Helvetica", 'B', size=11) pdf.cell(30, 5, txt="Address:", ln=0, align="L") pdf.set_font("Helvetica", '', size=11) pdf.cell(50, 5, txt=self.address, ln=1, align='L') pdf.cell(190, 2, "", ln=1) # Heading -> C/C pdf.set_font("Helvetica", 'B', size=12) pdf.set_draw_color(0, 0, 0) pdf.set_fill_color(0, 0, 0) pdf.set_text_color(255, 255, 255) pdf.set_line_width(1) pdf.cell(190, 5, txt="C/C", border=1, ln=1, align="L", fill=1) # content -> c/c pdf.set_text_color(0, 0, 0) pdf.set_font("Helvetica", '', size=11) pdf.multi_cell(190, 5, txt=self.cc, ln=0, align="L") pdf.cell(190, 2, "", ln=1) # Heading -> OE pdf.set_font("Helvetica", 'B', size=12) pdf.set_draw_color(0, 0, 0) pdf.set_fill_color(0, 0, 0) pdf.set_text_color(255, 255, 255) pdf.set_line_width(1) pdf.cell(190, 5, txt="O.E.", border=1, ln=1, align="L", fill=1) # content -> OE pdf.set_text_color(0, 0, 0) pdf.set_font("Helvetica", '', size=11) pdf.multi_cell(190, 5, txt=self.oe, ln=0, align="L") pdf.cell(190, 2, "", ln=1) # Heading -> rf pdf.set_font("Helvetica", 'B', size=12) pdf.set_draw_color(0, 0, 0) pdf.set_fill_color(0, 0, 0) pdf.set_text_color(255, 255, 255) pdf.set_line_width(1) pdf.cell(190, 5, txt="R.F.", border=1, ln=1, align="L", fill=1) # content -> rf pdf.set_text_color(0, 0, 0) pdf.set_font("Helvetica", '', size=11) pdf.multi_cell(190, 5, txt=self.rf, ln=0, align="L") pdf.cell(190, 2, "", ln=1) # Heading -> path report pdf.set_font("Helvetica", 'B', size=12) pdf.set_draw_color(0, 0, 0) pdf.set_fill_color(0, 0, 0) pdf.set_text_color(255, 255, 255) pdf.set_line_width(1) pdf.cell(190, 5, txt="Pathology Reoprt", border=1, ln=1, align="L", fill=1) # content -> path report pdf.set_text_color(0, 0, 0) pdf.set_font("Helvetica", '', size=11) pdf.multi_cell(190, 5, txt=self.pathreport, ln=0, align="L") pdf.cell(190, 2, "", ln=1) # Heading -> Dxs pdf.set_font("Helvetica", 'B', size=12) pdf.set_draw_color(0, 0, 0) pdf.set_fill_color(0, 0, 0) pdf.set_text_color(255, 255, 255) pdf.set_line_width(1) pdf.cell(190, 5, txt="Dxs", border=1, ln=1, align="L", fill=1) # content -> Dxs pdf.set_text_color(0, 0, 0) pdf.set_font("Helvetica", '', size=11) pdf.multi_cell(190, 5, txt=self.dxs, ln=0, align="L") pdf.cell(190, 2, "", ln=1) # Heading -> comment pdf.set_font("Helvetica", 'B', size=12) pdf.set_draw_color(0, 0, 0) pdf.set_fill_color(0, 0, 0) pdf.set_text_color(255, 255, 255) pdf.set_line_width(1) pdf.cell(190, 5, txt="Comment", border=1, ln=1, align="L", fill=1) # content -> comment pdf.set_text_color(0, 0, 0) pdf.set_font("Helvetica", '', size=11) pdf.multi_cell(190, 5, txt=self.comments, ln=0, align="L") pdf.cell(190, 2, "", ln=1) curr_pos = pdf.get_y() if curr_pos + 55 > 275: pdf.add_page() pdf.set_font("times", 'B', size=12) pdf.set_draw_color(0, 0, 0) pdf.set_fill_color(0, 0, 0) pdf.set_text_color(255, 255, 255) pdf.set_line_width(1) pdf.cell(190, 5, txt="Images of Rediology", border=1, ln=1, align="L", fill=1) pdf.cell(190, 1, "", ln=1) i = 1 j = 0 while 2 * i <= len(self.rediology) + len(self.rediology) % 2: yy = pdf.get_y() if j + 1 <= len(self.rediology): pdf.image(self.path + self.rediology[j], x=10, h=50, w=90) j += 1 if j + 1 <= len(self.rediology): pdf.image(self.path + self.rediology[j], x=110, y=yy, h=50, w=90) j += 1 pdf.ln(2) i += 1 curr_pos = pdf.get_y() if curr_pos + 55 > 275: pdf.add_page() pdf.set_font("times", 'B', size=12) pdf.set_draw_color(0, 0, 0) pdf.set_fill_color(0, 0, 0) pdf.set_text_color(255, 255, 255) pdf.set_line_width(1) pdf.cell(190, 5, txt="Images of MRI", border=1, ln=1, align="L", fill=1) pdf.cell(190, 1, "", ln=1) i = 1 j = 0 while 2 * i <= len(self.mri) + len(self.mri) % 2: yy = pdf.get_y() if j + 1 <= len(self.mri): pdf.image(self.path + self.mri[j], x=10, h=50, w=90) j += 1 if j + 1 <= len(self.mri): pdf.image(self.path + self.mri[j], x=110, y=yy, h=50, w=90) j += 1 pdf.ln(2) i += 1 curr_pos = pdf.get_y() if curr_pos + 55 > 275: pdf.add_page() pdf.set_font("times", 'B', size=12) pdf.set_draw_color(0, 0, 0) pdf.set_fill_color(0, 0, 0) pdf.set_text_color(255, 255, 255) pdf.set_line_width(1) pdf.cell(190, 5, txt="Images of X-Ray", border=1, ln=1, align="L", fill=1) pdf.cell(190, 1, "", ln=1) i = 1 j = 0 while 2 * i <= len(self.xray) + len(self.xray) % 2: yy = pdf.get_y() if j + 1 <= len(self.xray): pdf.image(self.path + self.xray[j], x=10, h=50, w=90) j += 1 if j + 1 <= len(self.xray): pdf.image(self.path + self.xray[j], x=110, y=yy, h=50, w=90) j += 1 pdf.ln(2) i += 1 curr_pos = pdf.get_y() if curr_pos + 55 > 275: pdf.add_page() pdf.set_font("times", 'B', size=12) pdf.set_draw_color(0, 0, 0) pdf.set_fill_color(0, 0, 0) pdf.set_text_color(255, 255, 255) pdf.set_line_width(1) pdf.cell(190, 5, txt="Images of CT Scan", border=1, ln=1, align="L", fill=1) pdf.cell(190, 1, "", ln=1) i = 1 j = 0 while 2 * i <= len(self.ctscan) + len(self.ctscan) % 2: yy = pdf.get_y() if j + 1 <= len(self.ctscan): pdf.image(self.path + self.ctscan[j], x=10, h=50, w=90) j += 1 if j + 1 <= len(self.ctscan): pdf.image(self.path + self.ctscan[j], x=110, y=yy, h=50, w=90) j += 1 pdf.ln(2) i += 1 curr_pos = pdf.get_y() if curr_pos + 55 > 275: pdf.add_page() pdf.set_font("times", 'B', size=12) pdf.set_draw_color(0, 0, 0) pdf.set_fill_color(0, 0, 0) pdf.set_text_color(255, 255, 255) pdf.set_line_width(1) pdf.cell(190, 5, txt="Other Images", border=1, ln=1, align="L", fill=1) pdf.cell(190, 1, "", ln=1) i = 1 j = 0 while 2 * i <= len(self.pics) + len(self.pics) % 2: yy = pdf.get_y() if j + 1 <= len(self.pics): pdf.image(self.path + self.pics[j], x=10, h=50, w=90) j += 1 if j + 1 <= len(self.pics): pdf.image(self.path + self.pics[j], x=110, y=yy, h=50, w=90) j += 1 pdf.ln(2) i += 1 curr_pos = pdf.get_y() if curr_pos + 55 > 275: pdf.add_page() destination = QFileDialog.getExistingDirectory() pdf.output(destination + "/" + str(self.id) + ".pdf")
def export_full_to_pdf(schedule_ref: Schedule, title_text: str, file_path: str, font_name: str, font_path: str, encoding: str, progress=None) -> None: """ Method for exports to PDF file """ file = QFileInfo(file_path) # pdf pdf = FPDF(orientation="L") # encoding if encoding == "UTF-8": pdf.add_font(font_name, "", font_path, uni=True) else: pdf.add_font(font_name, "", font_path) pdf.set_doc_option("core_fonts_encoding", encoding) pdf.set_font(font_name) pdf.add_page() x, y = float(pdf.get_x()), float(pdf.get_y()) w = float(pdf.w) - 2 * float(pdf.get_x()) h = float(pdf.h) - 2 * float(pdf.get_y()) - 6 pdf.set_auto_page_break(True, margin=y) title = 10 pdf.set_font_size(14) pdf.cell(w, title, txt=title_text, align="C", border=0) h -= title first_column, first_row = 4, 4 step_column = (w - first_row) / 8 step_row = (h - first_column) / 6 indexes = schedule_ref.indexes() table_widget = schedule_editor_window.ScheduleTableWidget() table_widget.set_schedule(schedule_ref) # processing week_step = 100 / 7 count = 0 i = 0 while i < 7: j = 0 while j < 9: if i == 0 and j == 0: # upper-left cell pdf.set_xy(x, y + title) pdf.cell(first_column, first_row, border=1) j += 1 elif i == 0: # top cells with time pdf.set_xy(x + first_row + step_column * (j - 1), y + title) pdf.set_font_size(8) pdf.cell(step_column, first_row, txt=TimePair.time_start_end(j - 1), align="C", border=1) j += 1 elif j == 0: # left cells with days of the week pdf.set_xy( x, y + title + first_column + step_row * (i - 1) + step_row) pdf.rotate(90) pdf.set_font_size(8) pdf.cell(step_row, first_row, txt=str(DaysOfWeek.value_of(i - 1)), align="C", border=1) pdf.rotate(0) j += 1 else: # cells inside the table pdf.set_xy(x + first_row + step_column * (j - 1), y + title + first_column + step_row * (i - 1)) simple_row = (step_row / indexes[i - 1]) prev_x, prev_y = pdf.get_x(), pdf.get_y() start_index = sum(indexes[r] for r in range(i - 1)) number_row = 0 for m in range(start_index, start_index + indexes[i - 1]): item = table_widget.item(m, j - 1) if item is not None: x_span_count = table_widget.columnSpan(m, j - 1) y_span_count = table_widget.rowSpan(m, j - 1) pdf.set_xy(prev_x, prev_y + number_row * simple_row) pdf.cell(step_column * x_span_count, simple_row * y_span_count, border=1) text = item.text() if text != "": draw_text( pdf, x + first_row + step_column * (j - 1), y + title + first_column + step_row * (i - 1) + simple_row * number_row, step_column * x_span_count, simple_row * y_span_count, text) number_row += 1 pdf.set_xy(prev_x, prev_y) j += 1 i += 1 if progress is not None: count += 1 progress.setValue(week_step * count) if progress.wasCanceled(): break pdf.output(file.absoluteFilePath())
def export_weeks_to_pdf(schedule_ref: Schedule, title_text: str, add_date: bool, file_path: str, font_name: str, font_path: str, encoding: str, start: datetime.date, end: datetime.date, color_a: QColor, color_b: QColor, progress=None) -> None: """ Method for exports to PDF file """ file = QFileInfo(file_path) # pdf pdf = FPDF(orientation="L") # encoding if encoding == "UTF-8": pdf.add_font(font_name, "", font_path, uni=True) else: pdf.add_font(font_name, "", font_path) pdf.set_doc_option("core_fonts_encoding", encoding) # processing week_step = 100 / (end - start).days / 7 count = 0 pdf.set_font(font_name) while True: pdf.add_page() schedule = schedule_ref.create_week_schedule( start, start + datetime.timedelta(days=6)) indexes = schedule.indexes() table_widget = schedule_editor_window.ScheduleTableWidget() table_widget.set_schedule(schedule) start += datetime.timedelta(days=6) x, y = float(pdf.get_x()), float(pdf.get_y()) w = float(pdf.w) - 2 * float(pdf.get_x()) h = float(pdf.h) - 2 * float(pdf.get_y()) - 6 pdf.set_auto_page_break(True, margin=y) title = 10 title_page = title_text if add_date: start_week = (start + datetime.timedelta(days=-6)).strftime("%d.%m.%Y") end_week = start.strftime("%d.%m.%Y") title_page += f". {start_week} - {end_week}" pdf.set_font_size(14) pdf.cell(w, title, txt=title_page, align="C", border=0) h -= title first_column, first_row = 4, 4 step_column = (w - first_row) / 8 step_row = (h - first_column) / 6 i = 0 while i < 7: j = 0 while j < 9: if i == 0 and j == 0: # upper-left cell pdf.set_xy(x, y + title) pdf.cell(first_column, first_row, border=1) j += 1 elif i == 0: # top cells with time pdf.set_xy(x + first_row + step_column * (j - 1), y + title) pdf.set_font_size(8) pdf.cell(step_column, first_row, txt=TimePair.time_start_end(j - 1), align="C", border=1) j += 1 elif j == 0: # left cells with days of the week pdf.set_xy( x, y + title + first_column + step_row * (i - 1) + step_row) pdf.rotate(90) pdf.set_font_size(8) pdf.cell(step_row, first_row, txt=str(DaysOfWeek.value_of(i - 1)), align="C", border=1) pdf.rotate(0) j += 1 else: # cells inside the table pdf.set_xy(x + first_row + step_column * (j - 1), y + title + first_column + step_row * (i - 1)) simple_row = (step_row / indexes[i - 1]) prev_x, prev_y = pdf.get_x(), pdf.get_y() start_index = sum(indexes[r] for r in range(i - 1)) number_row = 0 for m in range(start_index, start_index + indexes[i - 1]): item = table_widget.item(m, j - 1) if item is not None: x_span_count = table_widget.columnSpan(m, j - 1) y_span_count = table_widget.rowSpan(m, j - 1) pdf.set_xy(prev_x, prev_y + number_row * simple_row) # pdf.cell(step_column * x_span_count, # simple_row * y_span_count, # border=1) day, number, duration = i - 1, j - 1, x_span_count pairs = schedule.pairs_by_index( day, number, duration, number_row) # select color for cell if all(pair["subgroup"].get_subgroup() == SubgroupPairAttrib.Common for pair in pairs): # common pdf.cell(step_column * x_span_count, simple_row * y_span_count, border=1) elif all(pair["subgroup"].get_subgroup() == SubgroupPairAttrib.A for pair in pairs): # A subgroup pdf.set_fill_color(color_a.red(), color_a.green(), color_a.blue()) pdf.cell(step_column * x_span_count, simple_row * y_span_count, border=1, fill=1) elif all(pair["subgroup"].get_subgroup() == SubgroupPairAttrib.B for pair in pairs): # B subgroup pdf.set_fill_color(color_b.red(), color_b.green(), color_b.blue()) pdf.cell(step_column * x_span_count, simple_row * y_span_count, border=1, fill=1) else: # A and B subgroup prev_x = pdf.get_x() prev_y = pdf.get_y() toggle = True row = 5 column = math.ceil(step_column * x_span_count / step_row * row) for t in range(column): for n in range(row): pdf.set_xy( prev_x + t * step_column * x_span_count / column, prev_y + n * step_row / row) if toggle: color = color_a toggle = False else: color = color_b toggle = True pdf.set_fill_color( color.red(), color.green(), color.blue()) pdf.cell(step_column * x_span_count / column, simple_row * y_span_count / row, border=0) pdf.set_xy(prev_x, prev_y) pdf.cell(step_column * x_span_count, simple_row * y_span_count, border=1) if len(pairs) != 0: text = "\n".join(str(pair) for pair in pairs) draw_text( pdf, x + first_row + step_column * (j - 1), y + title + first_column + step_row * (i - 1) + simple_row * number_row, step_column * x_span_count, simple_row * y_span_count, text) number_row += 1 pdf.set_xy(prev_x, prev_y) j += 1 # old # pairs = schedule.pairs_by_index(i - 1, j - 1, 1) \ # + schedule.pairs_by_index(i - 1, j - 1, 2) # # max_duration = max([1, *[pair["time"].duration() for pair in pairs]]) # # # select color for cell # if all(pair["subgroup"].get_subgroup() == SubgroupPairAttrib.Common # for pair in pairs): # # common # pdf.cell(step_column * max_duration, # step_row, # border=1) # elif all(pair["subgroup"].get_subgroup() == SubgroupPairAttrib.A # for pair in pairs): # # A subgroup # pdf.set_fill_color(color_a.red(), color_a.green(), color_a.blue()) # pdf.cell(step_column * max_duration, # step_row, # border=1, # fill=1) # elif all(pair["subgroup"].get_subgroup() == SubgroupPairAttrib.B # for pair in pairs): # # B subgroup # pdf.set_fill_color(color_b.red(), color_b.green(), color_b.blue()) # pdf.cell(step_column * max_duration, # step_row, # border=1, # fill=1) # else: # # A and B subgroup # prev_x = pdf.get_x() # prev_y = pdf.get_y() # # toggle = True # # row = 5 # column = math.ceil(step_column * max_duration / step_row * row) # # for m in range(column): # for n in range(row): # pdf.set_xy(prev_x + m * step_column * max_duration / column, # prev_y + n * step_row / row) # # if toggle: # color = color_a # toggle = False # else: # color = color_b # toggle = True # # pdf.set_fill_color(color.red(), color.green(), color.blue()) # pdf.cell(step_column * max_duration / column, # step_row / row, # border=0, # fill=1) # pdf.set_xy(prev_x, prev_y) # pdf.cell(step_column * max_duration, # step_row, # border=1) # text = "" # for pair in pairs: # text += str(pair) + "\n" # # if text != "": # draw_text(pdf, # x + first_row + step_column * (j - 1), # y + title + first_column + step_row # * (i - 1), # step_column * max_duration, # step_row, # text) # j += max_duration i += 1 if progress is not None: count += 1 progress.setValue(week_step * count) if progress.wasCanceled(): break start += datetime.timedelta(days=1) if end <= start: break pdf.output(file.absoluteFilePath())
def create_pdf(self): """Build the PDF file from user-supplied information""" # Dictionary of variables collected from gui, to be passed to method_graf() self.variabledic = {"methodofservice": self.methodText.get(), "documents": self.docsservedText.get().upper(), "target": self.targetText.get(), "dateandtime": self.monthText.get() + " " + self.dayText.get() + ", " + self.yearText.get() + ", at " + self.hourText.get() + ":" + self.minuteText.get() + " " + self.ampmText.get(), "location": self.locationText.get(), "subperson": self.subpersonText.get(), "subrelation": self.subrelationText.get(), "parentname": self.parentText.get(), "tempguard": self.tempText.get(), "committed": self.committedBool.get(), "adminname": self.adminText.get(), "agentname": self.agentText.get(), "sex": self.sexText.get() } pdf=FPDF("P", "pt", "Letter") pdf.set_margins(36,36) pdf.alias_nb_pages() pdf.add_page() # State, County & Court pdf.set_font("Times", "", 12) pdf.multi_cell(h = 18, w = 540, align = "L", txt = ( "IN THE "+self.courtText.get().upper()+" COURT OF\n"+ self.countyText.get().upper()+" COUNTY, "+self.stateText.get().upper())) pdf.ln(30) # Plaintiff pcursor = pdf.get_y() pdf.multi_cell(h=18, w=400, align = "L", txt=self.plaintiffEntry.get(0.0,'end').upper()) newpcursor = pdf.get_y() pdf.set_xy(400, pcursor) pdf.cell(w = 0, align = "R", txt = "PLAINTIFF") pdf.set_xy(0, newpcursor) pdf.ln(18) # Case Number pdf.cell(h = 18, w = 20, align = "L", txt = "V.") pdf.cell(h = 18, w = 500, align = "C", txt = "CASE NO. "+self.caseNoText.get().upper()) pdf.ln(30) # Defendant pcursor = pdf.get_y() pdf.multi_cell(h=18, w=400, align = "L", txt=self.defendantEntry.get(0.0,'end').upper()) newpcursor = pdf.get_y() pdf.set_xy(400, pcursor) pdf.cell(h = 18, w = 0, align = "R", txt = "DEFENDANT") pdf.set_xy(0, newpcursor) pdf.ln(18) # Title pdf.set_font("Times", "U", 12) pdf.cell(h = 24, w = 0, align = "C", txt = "AFFIDAVIT OF SERVICE") pdf.ln(36) # Commencement pdf.set_font("Times", "", 12) pdf.multi_cell(h = 30, w = 540, align = "L", txt = ( " Comes now " + self.serverText.get() + ", who, being duly " "sworn, deposes and says:")) # Paragraph with details of service (multi-line), called from method_graf() function pdf.multi_cell(h = 30, w = 540, align = "L", txt = self.method_graf(**self.variabledic)) # Comments if len(self.commentsText.get()) > 0: pdf.multi_cell(h = 30, w = 540, align = "L", txt = " " + self.commentsText.get()) # Not a party/No interest/Further affiant sayeth not, etc. pdf.multi_cell(h = 30, w = 540, align = "L", txt = ( " I am not a party to this action, and I have no interest in it. \n" " Further affiant sayeth not.")) pdf.ln(40) # Signature/Notary section pdf.line(270,pdf.get_y(),540,pdf.get_y()) pdf.set_x(270) pdf.cell(h = 24, w = 0, align = "L", txt = self.serverText.get()) pdf.ln(24) pdf.set_x(270) pdf.multi_cell(h = 18, w = 0, align = "L", txt = self.servaddrEntry.get(0.0,"end")) pdf.ln(24) pdf.set_x(36) pdf.cell(h = 18, w = 270, align = "L", txt = "Subscribed and sworn to before me this date:") pdf.line(270,pdf.get_y()+18,540,pdf.get_y()+18) pdf.ln(40) pdf.line(270,pdf.get_y()+18,540,pdf.get_y()+18) pdf.ln(24) pdf.set_x(270) pdf.cell(h = 18, w = 270, align = "L", txt = "Notary Public") pdf.ln(36) pdf.set_x(270) pdf.cell(h = 18, w = 270, align = "L", txt = "My commission expires:") pdf.line(400,pdf.get_y()+18,540,pdf.get_y()+18) # write PDF pdf.output(self.filenameText.get()+".pdf", "F") return None
def invoice_to_PDF(order, client, filename=None): """ creates and pdf invoice of the order, and returns the pfd as a string buffer. @order: the order used to create a invoice @client: if specified this data is used for the client address, otherwise the address is taken from the order @filename: if specified the pdf is written to disk with the given filename, filename can contains a complete path """ pdf = FPDF() pdf.add_font('DejaVu', '', fname='{0}/fonts/ttf-dejavu/DejaVuSerif.ttf'.format(settings.STATIC_ROOT), uni=True) pdf.add_font('DejaVu', 'B', fname='{0}/fonts/ttf-dejavu/DejaVuSerif-Bold.ttf'.format(settings.STATIC_ROOT), uni=True) pdf.add_font('DejaVu', 'I', fname='{0}/fonts/ttf-dejavu/DejaVuSerif-Italic.ttf'.format(settings.STATIC_ROOT), uni=True) pdf.add_font('DejaVu', 'BI', fname='{0}/fonts/ttf-dejavu/DejaVuSerif-BoldItalic.ttf'.format(settings.STATIC_ROOT), uni=True) def check_for_new_page(): if pdf.get_y() > PAGE_BOTTOM_Y: pdf.add_page() def text_fonts(): pdf.set_font('DejaVu', '', 11.0) def add_row(column_data, columns=COLUMNS, border=0): """ add a row to the pdf """ cell_margin_left = 2 cell_margin_right = 2 check_for_new_page() last_y = START_TABLE_Y if pdf.page_no() == 1 else TOP_PAGE_MARGIN row_y = pdf.get_y() if pdf.get_y() > last_y else last_y max_y = row_y # max_y is used to check if multi cell is wrapping text and so uses more rows. next_x = LEFT_PAGE_MARGIN for i, column in enumerate(columns): width = column[0] align = column[1] pdf.set_xy(next_x+cell_margin_left, row_y) pdf.multi_cell(w=width-cell_margin_right, h=TABLE_ROW_HIGH, txt=column_data[i] if len(column_data) > i else '', align=align, border=border) max_y = max(max_y, pdf.get_y()) # keep track if multi cell wrapped text next_x += width pdf.set_y(max_y) def add_row_line(): last_y = START_TABLE_Y if pdf.page_no() == 1 else TOP_PAGE_MARGIN line_y = pdf.get_y() if pdf.get_y() > last_y else last_y - 2 pdf.set_xy(LEFT_PAGE_MARGIN + 1, line_y) pdf.line(LEFT_PAGE_MARGIN, line_y+2, RIGHT_PAGE_MARGIN, line_y+2) pdf.set_y(line_y+5) def draw_vertical_lines_around_columns(columns = COLUMNS, top_y=TOP_PAGE_MARGIN, bottom_y=PAGE_BOTTOM_Y): #### # draw table vertical lines #### line_y = pdf.get_y() - 3 line_x = LEFT_PAGE_MARGIN first = True for column in columns: if first: pdf.line(line_x, START_TABLE_Y, line_x, line_y) # vertical line in front of table first = False line_x += column[0] pdf.line(line_x, START_TABLE_Y, line_x, line_y) # vertical line after column pdf.add_page() text_fonts() #### # Header: logo and company info #### pdf.image('{0}/gfx/logos/logo_jeslee.jpg'.format(settings.STATIC_ROOT), 20.0, TOP_PAGE_MARGIN, link='', type='', w=79.5, h=33.0) pdf.set_xy(125.0, TOP_PAGE_MARGIN) # pdf.set_font('arial', 'B', 13.0) pdf.set_left_margin(125.0) pdf.write(6, '{company}\n{street}\n{zip} {city}\n{email}\n\nBank: {bank_account}\nKvk: {kvk}\nBTW: {btw}'.format( company=settings.COMPANY['business_name'], street=settings.COMPANY['street'], zip=settings.COMPANY['zip'], city=settings.COMPANY['city'], email=settings.COMPANY['email'], bank_account=settings.COMPANY['bank_account'], kvk=settings.COMPANY['kvk_nr'], btw=settings.COMPANY['btw_nr'] )) #### # Invoice data #### pdf.set_xy(LEFT_PAGE_MARGIN, 75) pdf.set_left_margin(LEFT_PAGE_MARGIN) pdf.set_font('DejaVu', 'B', 14.0) pdf.write(6, 'Factuur {number}'.format(number=order.number)) text_fonts() pdf.set_xy(125, 75) pdf.write(6, 'Factuurdatum: {date}'.format(date=datetime.now().strftime("%d %B %Y"))) pdf.set_xy(LEFT_PAGE_MARGIN, 85) pdf.write(5, 'Referentie: {reference}'.format(reference=order.invoice_line2 if order.invoice_line2 else 'Uw bestelling bij Jeslee')) pdf.set_xy(LEFT_PAGE_MARGIN, 100) name = order.invoice_company_name \ if order.invoice_company_name \ else "{0} {1}".format(order.invoice_firstname, order.invoice_lastname) address = order.invoice_line1 pdf.write(6, '{name}\n{address}\n{zip} {city}'.format( name=name.strip(), address=address.strip(), zip=order.invoice_code, city=order.invoice_city )) #### # Article data #### pdf.set_font('DejaVu', '', 9.0) add_row_line() add_row(['Artikelcode', 'Omschrijving', '', 'Bedrag\nincl. btw', 'Totaal']) add_row_line() for item in order.items.all(): code = '' description = '' if item.product: code = item.product.sku description = item.product.description if item.product.description else item.product.name str(item.product.tax if item.product.tax else '') add_row([code, description, '%.0f x' % item.product_amount, to_currency(item.product_price_gross), to_currency(item.price_gross)]) add_row_line() columns_below_items = [(COLUMN_1_WIDTH + COLUMN_2_WIDTH + COLUMN_3_WIDTH+COLUMN_4_WIDTH , 'R'), (COLUMN_5_WIDTH, 'R')] add_row(['Subtotaal', to_currency(order.price-order.tax)], columns=columns_below_items) taxes = tax_per_percentage(order) for tax_percentage, tax in taxes.iteritems(): add_row(['Btw {0}%'.format(tax_percentage), to_currency(tax)], columns=columns_below_items) add_row_line() pdf.set_font('DejaVu', 'B', 10.0) add_row(['Totaal', to_currency(order.price)], columns=columns_below_items) table_bottom = pdf.get_y() + 2 pdf.line(LEFT_PAGE_MARGIN, table_bottom, RIGHT_PAGE_MARGIN, table_bottom) # bottom horizontal line of table pdf.set_font('DejaVu', '', 10.0) pdf.set_y(pdf.get_y() + 10) check_for_new_page() pdf.set_x(LEFT_PAGE_MARGIN) pdf.multi_cell(w=COLUMN_1_WIDTH + COLUMN_2_WIDTH + COLUMN_3_WIDTH+COLUMN_4_WIDTH+COLUMN_5_WIDTH, h=TABLE_ROW_HIGH, txt=order.message, align='L', border=0) pdf.set_font('DejaVu', '', 10.0) pdf.set_xy(LEFT_PAGE_MARGIN, PAGE_BOTTOM_Y-14) pay_date = datetime.now() + timedelta(PAY_INVOICE_WITHIN_DAYS) pdf.write(4, 'We verzoeken u vriendelijk het bovenstaande bedrag van {order_price} voor ' '{pay_date} te voldoen op onze bankrekening onder vermelding van het ' 'factuurnummer {invoice_number}.\nVoor vragen kunt u contact opnemen per email ({email}).'. format(order_price=to_currency(order.price), pay_date=pay_date.strftime("%d %B %Y"), invoice_number=order.number, email=settings.COMPANY['email'])) pdf.set_draw_color(80) pdf.set_text_color(80) pdf.line(LEFT_PAGE_MARGIN, PAGE_BOTTOM_Y, RIGHT_PAGE_MARGIN, PAGE_BOTTOM_Y) # bottom horizontal line pdf.set_xy(LEFT_PAGE_MARGIN+5, PAGE_BOTTOM_Y+2) if filename: pdf.output(filename, 'F') return pdf.output('invoice.pdf', 'S')
def invoice_to_PDF(order, client, filename=None): """ creates and pdf invoice of the order, and returns the pfd as a string buffer. @order: the order used to create a invoice @client: if specified this data is used for the client address, otherwise the address is taken from the order @filename: if specified the pdf is written to disk with the given filename, filename can contains a complete path """ pdf = FPDF() pdf.add_font('DejaVu', '', fname='{0}/fonts/ttf-dejavu/DejaVuSerif.ttf'.format( settings.STATIC_ROOT), uni=True) pdf.add_font('DejaVu', 'B', fname='{0}/fonts/ttf-dejavu/DejaVuSerif-Bold.ttf'.format( settings.STATIC_ROOT), uni=True) pdf.add_font('DejaVu', 'I', fname='{0}/fonts/ttf-dejavu/DejaVuSerif-Italic.ttf'.format( settings.STATIC_ROOT), uni=True) pdf.add_font( 'DejaVu', 'BI', fname='{0}/fonts/ttf-dejavu/DejaVuSerif-BoldItalic.ttf'.format( settings.STATIC_ROOT), uni=True) def check_for_new_page(): if pdf.get_y() > PAGE_BOTTOM_Y: pdf.add_page() def text_fonts(): pdf.set_font('DejaVu', '', 11.0) def add_row(column_data, columns=COLUMNS, border=0): """ add a row to the pdf """ cell_margin_left = 2 cell_margin_right = 2 check_for_new_page() last_y = START_TABLE_Y if pdf.page_no() == 1 else TOP_PAGE_MARGIN row_y = pdf.get_y() if pdf.get_y() > last_y else last_y max_y = row_y # max_y is used to check if multi cell is wrapping text and so uses more rows. next_x = LEFT_PAGE_MARGIN for i, column in enumerate(columns): width = column[0] align = column[1] pdf.set_xy(next_x + cell_margin_left, row_y) pdf.multi_cell(w=width - cell_margin_right, h=TABLE_ROW_HIGH, txt=column_data[i] if len(column_data) > i else '', align=align, border=border) max_y = max(max_y, pdf.get_y()) # keep track if multi cell wrapped text next_x += width pdf.set_y(max_y) def add_row_line(): last_y = START_TABLE_Y if pdf.page_no() == 1 else TOP_PAGE_MARGIN line_y = pdf.get_y() if pdf.get_y() > last_y else last_y - 2 pdf.set_xy(LEFT_PAGE_MARGIN + 1, line_y) pdf.line(LEFT_PAGE_MARGIN, line_y + 2, RIGHT_PAGE_MARGIN, line_y + 2) pdf.set_y(line_y + 5) def draw_vertical_lines_around_columns(columns=COLUMNS, top_y=TOP_PAGE_MARGIN, bottom_y=PAGE_BOTTOM_Y): #### # draw table vertical lines #### line_y = pdf.get_y() - 3 line_x = LEFT_PAGE_MARGIN first = True for column in columns: if first: pdf.line(line_x, START_TABLE_Y, line_x, line_y) # vertical line in front of table first = False line_x += column[0] pdf.line(line_x, START_TABLE_Y, line_x, line_y) # vertical line after column pdf.add_page() text_fonts() #### # Header: logo and company info #### pdf.image('{0}/gfx/logos/logo_jeslee.jpg'.format(settings.STATIC_ROOT), 20.0, TOP_PAGE_MARGIN, link='', type='', w=79.5, h=33.0) pdf.set_xy(125.0, TOP_PAGE_MARGIN) # pdf.set_font('arial', 'B', 13.0) pdf.set_left_margin(125.0) pdf.write( 6, '{company}\n{street}\n{zip} {city}\n{email}\n\nBank: {bank_account}\nKvk: {kvk}\nBTW: {btw}' .format(company=settings.COMPANY['business_name'], street=settings.COMPANY['street'], zip=settings.COMPANY['zip'], city=settings.COMPANY['city'], email=settings.COMPANY['email'], bank_account=settings.COMPANY['bank_account'], kvk=settings.COMPANY['kvk_nr'], btw=settings.COMPANY['btw_nr'])) #### # Invoice data #### pdf.set_xy(LEFT_PAGE_MARGIN, 75) pdf.set_left_margin(LEFT_PAGE_MARGIN) pdf.set_font('DejaVu', 'B', 14.0) pdf.write(6, 'Factuur {number}'.format(number=order.number)) text_fonts() pdf.set_xy(125, 75) pdf.write( 6, 'Factuurdatum: {date}'.format( date=datetime.now().strftime("%d %B %Y"))) pdf.set_xy(LEFT_PAGE_MARGIN, 85) pdf.write( 5, 'Referentie: {reference}'.format( reference=order.invoice_line2 if order. invoice_line2 else 'Uw bestelling bij Jeslee')) pdf.set_xy(LEFT_PAGE_MARGIN, 100) name = order.invoice_company_name \ if order.invoice_company_name \ else "{0} {1}".format(order.invoice_firstname, order.invoice_lastname) address = order.invoice_line1 pdf.write( 6, '{name}\n{address}\n{zip} {city}'.format(name=name.strip(), address=address.strip(), zip=order.invoice_code, city=order.invoice_city)) #### # Article data #### pdf.set_font('DejaVu', '', 9.0) add_row_line() add_row(['Artikelcode', 'Omschrijving', '', 'Bedrag\nincl. btw', 'Totaal']) add_row_line() for item in order.items.all(): code = '' description = '' if item.product: code = item.product.sku description = item.product.description if item.product.description else item.product.name str(item.product.tax if item.product.tax else '') add_row([ code, description, '%.0f x' % item.product_amount, to_currency(item.product_price_gross), to_currency(item.price_gross) ]) add_row_line() columns_below_items = [ (COLUMN_1_WIDTH + COLUMN_2_WIDTH + COLUMN_3_WIDTH + COLUMN_4_WIDTH, 'R'), (COLUMN_5_WIDTH, 'R') ] add_row(['Subtotaal', to_currency(order.price - order.tax)], columns=columns_below_items) taxes = tax_per_percentage(order) for tax_percentage, tax in taxes.iteritems(): add_row(['Btw {0}%'.format(tax_percentage), to_currency(tax)], columns=columns_below_items) add_row_line() pdf.set_font('DejaVu', 'B', 10.0) add_row(['Totaal', to_currency(order.price)], columns=columns_below_items) table_bottom = pdf.get_y() + 2 pdf.line(LEFT_PAGE_MARGIN, table_bottom, RIGHT_PAGE_MARGIN, table_bottom) # bottom horizontal line of table pdf.set_font('DejaVu', '', 10.0) pdf.set_y(pdf.get_y() + 10) check_for_new_page() pdf.set_x(LEFT_PAGE_MARGIN) pdf.multi_cell(w=COLUMN_1_WIDTH + COLUMN_2_WIDTH + COLUMN_3_WIDTH + COLUMN_4_WIDTH + COLUMN_5_WIDTH, h=TABLE_ROW_HIGH, txt=order.message, align='L', border=0) pdf.set_font('DejaVu', '', 10.0) pdf.set_xy(LEFT_PAGE_MARGIN, PAGE_BOTTOM_Y - 14) pay_date = datetime.now() + timedelta(PAY_INVOICE_WITHIN_DAYS) pdf.write( 4, 'We verzoeken u vriendelijk het bovenstaande bedrag van {order_price} voor ' '{pay_date} te voldoen op onze bankrekening onder vermelding van het ' 'factuurnummer {invoice_number}.\nVoor vragen kunt u contact opnemen per email ({email}).' .format(order_price=to_currency(order.price), pay_date=pay_date.strftime("%d %B %Y"), invoice_number=order.number, email=settings.COMPANY['email'])) pdf.set_draw_color(80) pdf.set_text_color(80) pdf.line(LEFT_PAGE_MARGIN, PAGE_BOTTOM_Y, RIGHT_PAGE_MARGIN, PAGE_BOTTOM_Y) # bottom horizontal line pdf.set_xy(LEFT_PAGE_MARGIN + 5, PAGE_BOTTOM_Y + 2) if filename: pdf.output(filename, 'F') return pdf.output('invoice.pdf', 'S')
def setava_01(self, stock_taking): comp = list(self.mdb.stock.find().sort([("category", 1), ("_id", 1)])) autori = stock_taking['author'].strip().split(',') datum = str(stock_taking['closed'].date()) filename = "{}_{}.pdf".format(stock_taking['_id'], ''.join(stock_taking['name'].split())) print("Generovani prehledu inventury") print("Od:", autori) print("Kdy:", datum) print("Soubor,", filename) page = 1 money_sum = 0 Err = [] pdf = FPDF('P', 'mm', format='A4') pdf.set_auto_page_break(False) pdf.add_font('pt_sans', '', 'static/pt_sans/PT_Sans-Web-Regular.ttf', uni=True) pdf.add_font('pt_sans-bold', '', 'static/pt_sans/PT_Sans-Web-Bold.ttf', uni=True) pdf.set_font('pt_sans', '', 12) pdf.add_page() pdf.set_xy(0, 40) pdf.cell(pdf.w, 0, 'Celkový přehled skladu', align='C', ln=2) pdf.set_xy(0, 46) pdf.cell(pdf.w, 0, 'Universal Scientific Technologies s.r.o.', align='C', ln=2) pdf.set_xy(20, 200) pdf.cell(1, 0, 'Inventuru provedli:', ln=2) for x in autori: pdf.cell(1, 20, x, ln=2) pdf.set_font('pt_sans', '', 8) pdf.set_xy(120, 288) pdf.cell( 10, 0, "Vytvořeno %s, strana %s z %s" % (datetime.datetime.now().strftime("%d. %m. %Y, %H:%M:%S"), page, pdf.alias_nb_pages())) pdf.add_page() data = self.mdb.stock.aggregate([{ '$addFields': { 'count': { '$sum': '$history.bilance' } } }]) query = [ { "$group": { '_id': '$pid', 'operations': { "$push": "$$ROOT" } } }, { "$addFields": { "packet_count": { "$sum": "$operations.count" }, "packet_reserv": { "$sum": "$operations.reserv" }, "packet_ordered": { "$sum": "$operations.ordered" }, "packet_price": { "$function": { "body": '''function(prices, counts) { let total_counts = Array.sum(counts); var tmp_count = total_counts; var total_price = 0; var c = counts.reverse(); var p = prices.reverse(); for(i in c){ if(c[i] > 0){ if(c[i] < tmp_count){ total_price += (c[i]*p[i]); tmp_count -= c[i] } else{ total_price += (tmp_count*p[i]); tmp_count = 0; } } } return total_price; }''', "args": ["$operations.unit_price", "$operations.count"], "lang": "js" } } } }, #{"$addFields": {"comp": "$pid"}}, { "$lookup": { "from": "stock", "let": { "pid": "$_id" }, "pipeline": [ { "$match": { "$expr": { "$in": ["$$pid", "$packets._id"] } } }, { "$unwind": "$packets" }, { "$match": { "$expr": { "$eq": ["$packets._id", "$$pid"] } } }, ], "as": "component" } }, { "$set": { "component": { "$first": "$component" } } }, { "$lookup": { "from": "store_positions_complete", "localField": "component.packets.position", "foreignField": "_id", "as": "position_info", } }, { "$set": { "position_info": { "$first": "$position_info" } } }, { "$group": { '_id': '$component._id', 'packets': { "$push": "$$ROOT" }, #'component': { "$push": "$component" } } }, { "$sort": { "_id": 1 } } #{ "$sort": {"position_info.warehouse.code": 1, "position_info.path_string": 1, "position_info.name": 1, "component.name":1}}, #{ "$project": { "packet_count": 1, "packet_reserv": 1, "packet_price": 1, "packet_ordered": 1, "_id": 0} }, # { "$group": { # '_id': 'null', # 'count': {"$sum": '$packet_count'}, # 'price': {"$sum": '$packet_price'}, # 'reserv': {"$sum": '$packet_reserv'}, # 'ordered': {"$sum": '$packet_ordered'}, # } # } ] data = self.mdb.stock_operation.aggregate(query) gen_time = datetime.datetime(2018, 10, 1) lastOid = ObjectId.from_datetime(gen_time) number_components = 0 number_packets = 0 for i, component in enumerate(data): print(" ") number_components += 1 # print(component['_id'], component) component['packets_count'] = [] component['packets_prices'] = [] try: ## Pokud je konec stránky if pdf.get_y() > pdf.h - 20: pdf.line(10, pdf.get_y() + 0.5, pdf.w - 10, pdf.get_y() + 0.5) pdf.set_font('pt_sans', '', 10) pdf.set_xy(150, pdf.get_y() + 1) pdf.cell(100, 5, 'Součet strany: {:6.2f} Kč'.format(page_sum)) pdf.add_page() ## Pokud je nová strana if page != pdf.page_no(): pdf.set_font('pt_sans', '', 8) page = pdf.page_no() pdf.set_xy(120, 288) pdf.cell( 10, 0, "Vytvořeno %s, strana %s z %s" % (datetime.datetime.now().strftime("%d. %m. %Y, %H:%M:%S"), page, pdf.alias_nb_pages())) pdf.set_font('pt_sans', '', 11) pdf.set_xy(10, 10) pdf.cell(100, 5, 'Skladová položka') pdf.set_x(105) pdf.cell(10, 5, "Počet kusů", align='R') #pdf.set_x(120) #pdf.cell(10, 5, "Cena za 1ks", align='R') pdf.set_x(180) pdf.cell(10, 5, "Cena položky (bez DPH)", align='R', ln=2) pdf.line(10, 15, pdf.w - 10, 15) pdf.set_y(18) page_sum = 0 pdf.set_font('pt_sans', '', 10) count = 0 price = 0 packets = "" for j, packet in enumerate(component['packets']): number_packets += 1 pcount = packet['packet_count'] pprice = round(packet['packet_price'], 2) component['packets_count'].append(pcount) component['packets_prices'].append(pprice) count += pcount price += pprice packets += " {},".format(pprice) #pac_info = get_packet_count(self.mdb, packet['_id']) #print("C: {}, {}, ".format(pcount-pac_info['packet_count'], pprice-pac_info['packet_price'])) price_ks = 0 first_price = 0 inventura = False if count > 0: money_sum += price page_sum += price if price == 0.0: # and x.get('count', 0) > 0: Err.append( 'Polozka >%s< nulová cena, nenulový počet (%s)' % (component['_id'], component.get('name', '---'))) pdf.set_x(10) pdf.cell( 100, 5, "{:5.0f} {} ({})".format(i, packet['component']['name'], len(component['packets']))) pdf.set_font('pt_sans', '', 10) pdf.set_x(105) pdf.cell(10, 5, "{} j".format(count), align='R') # pdf.set_x(107) # pdf.cell(10, 5, repr(component['packets_count']) + " " +repr(component['packets_prices']), align='L') pdf.set_font('pt_sans-bold', '', 10) pdf.set_x(180) pdf.cell(10, 5, "%6.2f Kč" % (price), align='R') except Exception as e: Err.append('Err' + repr(e) + repr(component['_id'])) print(e) if count > 0: pdf.set_y(pdf.get_y() + 4) pdf.line(10, pdf.get_y(), pdf.w - 10, pdf.get_y()) pdf.set_font('pt_sans', '', 8) pdf.set_x(180) pdf.cell(10, 5, "Konec souhrnu", align='R') print("Celková cena", money_sum) print("Probematicke", len(Err)) print("Polozek:", number_components) print("Pocet sacku:", number_packets) pdf.page = 1 pdf.set_xy(20, 175) pdf.set_font('pt_sans', '', 12) pdf.cell( 20, 20, "Cena skladových zásob k %s je %0.2f Kč (bez DPH)" % (datum, money_sum)) if len(Err) > 0: pdf.set_xy(30, 80) pdf.cell(1, 6, "Pozor, chyby ve skladu:", ln=2) pdf.set_x(32) for ch in Err: pdf.cell(1, 5, ch, ln=2) pdf.page = page pdf.output("static/tmp/sestava.pdf") year = datum[:4] filename = "{}.pdf".format(''.join(stock_taking['name'].split(' '))) foldername = os.path.join(tornado.options.options.owncloud_root, 'accounting', year, 'stocktaking', filename) foldername = save_file(self.mdb, foldername) return upload_file(self.oc, 'static/tmp/sestava.pdf', foldername)
class PDFPrinter: PAGE_FORMAT = 'A4' UNIT = 'mm' MARGIN = 10 CONTENT_WIDTH = 297 - 2 * MARGIN CONTENT_HEIGHT = 210 - 2 * MARGIN HEADER_HEIGHT = 30 NOTES_HEIGHT = 17 TABLE_HEIGHT = CONTENT_HEIGHT - HEADER_HEIGHT - NOTES_HEIGHT FONT_S = 7 FONT_XS = 6.5 def __init__(self): self.colors = {} self.timelinesCount = None self.fontSize = 12 self.textColor = Color.WHITE self.pdf = FPDF(orientation='L', unit=PDFPrinter.UNIT, format=PDFPrinter.PAGE_FORMAT) self.pdf.add_font('regular', '', os.path.join('fonts', 'ubuntu', 'Ubuntu-B.ttf'), uni=True) self.pdf.add_font('condensed', '', os.path.join('fonts', 'roboto', 'RobotoCondensed-Regular.ttf'), uni=True) self.pdf.add_font('italic', '', os.path.join('fonts', 'roboto', 'RobotoCondensed-Bold.ttf'), uni=True) self.pdf.set_font("regular", size=self.fontSize) self.pdf.add_page() self.pdf.set_margins(PDFPrinter.MARGIN, PDFPrinter.MARGIN, PDFPrinter.MARGIN) self.uglyMeasure = FPDF(orientation='L', unit=PDFPrinter.UNIT, format=PDFPrinter.PAGE_FORMAT) self.uglyMeasure.add_font('regular', '', os.path.join('fonts', 'ubuntu', 'Ubuntu-B.ttf'), uni=True) self.uglyMeasure.add_font('condensed', '', os.path.join('fonts', 'roboto', 'RobotoCondensed-Regular.ttf'), uni=True) self.uglyMeasure.add_font('italic', '', os.path.join('fonts', 'roboto', 'RobotoCondensed-Bold.ttf'), uni=True) self.uglyMeasure.set_font("regular", size=self.fontSize) self.uglyMeasure.add_page() def defineColor(self, key, color): hex = color.lstrip('#') self.colors[key.lower()] = tuple( int(hex[i:i + 2], 16) for i in (0, 2, 4)) def printHeader(self, names): self.timelinesCount = len(names) boxWidth = PDFPrinter.CONTENT_WIDTH / self.timelinesCount boxPos = 0 for name in names: color = self.colors[name.lower()] x = PDFPrinter.MARGIN + boxWidth * boxPos y = PDFPrinter.MARGIN w = boxWidth h = 7 self._box(x, y, w, h, color=color, lineColor=Color.BLACK, lineWidth=0.1) self._text(x, y, w, h, text=name, color=self.textColor, font='regular', size=self.fontSize) boxPos += 1 def printTimetable(self, timetable): colCount = len(timetable.keys()) colWidth = PDFPrinter.CONTENT_WIDTH / colCount tablePositionY = 30 tableHeight = PDFPrinter.TABLE_HEIGHT + 1 tableHeaderHeight = 7 timelineRowHeight = tableHeight - tableHeaderHeight timelineRowPositionY = tablePositionY + tableHeaderHeight timeBlockWidth = (colWidth - 2) / self.timelinesCount timeWindow = self._findTimeWindow(timetable) yPerMin = (timelineRowHeight - 2) / (timeWindow["toTime"] - timeWindow["fromTime"]) colNo = 0 for key, schedules in timetable.items(): x = PDFPrinter.MARGIN + colWidth * colNo self._box(x=x, y=tablePositionY, w=colWidth, h=tableHeaderHeight, color=Color.LIGHT_GREY, lineColor=Color.BLACK, lineWidth=0.2) self._text(x=x, y=tablePositionY, w=colWidth, h=tableHeaderHeight, text=key, color=Color.BLACK, font='regular', size=self.fontSize) self._box(x=x, y=timelineRowPositionY, w=colWidth, h=timelineRowHeight, color=None, lineColor=Color.BLACK, lineWidth=0.2) self._drawTimeblocks(schedules, areaWidth=timeBlockWidth, areaPositionX=x, areaPositionY=timelineRowPositionY + 0.8, scaleY=yPerMin, timeWindowStart=timeWindow["fromTime"]) colNo += 1 def _drawTimeblocks(self, schedules, areaWidth, areaPositionX, areaPositionY, scaleY, timeWindowStart): timeBlockNo = 0 for person, timelines in schedules.items(): blockColor = self.colors[person.lower()] blockPositionX = areaPositionX + areaWidth * timeBlockNo + 0.5 * timeBlockNo + 0.5 for timeline in timelines: fromTimePosY = scaleY * (self._timeToInt(timeline.fromTime) - timeWindowStart) + 0.4 blockPositionY = areaPositionY + fromTimePosY blockHeight = scaleY * (self._timeToInt(timeline.toTime) - timeWindowStart) - fromTimePosY self._box(x=blockPositionX, y=blockPositionY, w=areaWidth, h=blockHeight, color=blockColor, lineColor=None) if (timeline.kind == "~"): self._drawLeftLines(x=blockPositionX, y=blockPositionY, w=areaWidth, h=blockHeight) elif (timeline.kind == "d"): self._drawTwoRightLines(x=blockPositionX, y=blockPositionY, w=areaWidth, h=blockHeight) elif (timeline.kind == "e"): self._drawEmptyRightCorner(x=blockPositionX, y=blockPositionY, w=areaWidth, h=blockHeight) self._drawTimeblockLabels(areaX=blockPositionX, areaY=blockPositionY, areaW=areaWidth, areaH=blockHeight, timeline=timeline, backColor=blockColor) timeBlockNo += 1 def _drawLeftLines(self, x, y, w, h): hw = h / w posX = x posXM = x + w posY = y posYM = y + h jump = 3 while (posXM > x): posX += jump posXM -= jump posY += jump * hw posYM -= jump * hw if jump == 2: jump = 0.5 else: jump = 2 if (posX < x + w and posY < y + h): self._line(posX, y, x, posY, Color.WHITE, lineWidth=0.2) if (posXM > x and posYM > y): self._line(posXM, y + h, x + w, posYM, Color.WHITE, lineWidth=0.2) def _drawTwoRightLines(self, x, y, w, h): hw = h / w posX = x posXM = x + w posY = y posYM = y + h jump = 2 for _ in range(4): posX += jump posXM -= jump posY += jump * hw posYM -= jump * hw # if jump == 2: # jump = 0.7 # else: # jump = 2 if (posX < x + w and posY < y + h): self._line(posX, y + h, x, posYM, Color.WHITE, lineWidth=0.3) if (posXM > x and posYM > y): self._line(posXM, y, x + w, posY, Color.WHITE, lineWidth=0.3) def _drawEmptyRightCorner(self, x, y, w, h): hw = h / w posX = x posXM = x + w posY = y posYM = y + h jump = 1 for p in range(9): posX += jump posXM -= jump posY += jump * hw posYM -= jump * hw if p > 5: jump = 1 else: jump = 0.2 if (posX < x + w and posY < y + h): self._line(posX, y + h, x, posYM, Color.WHITE, lineWidth=0.2) if (posXM > x and posYM > y): self._line(posXM, y, x + w, posY, Color.WHITE, lineWidth=0.2) def _drawTimeblockLabels(self, areaX, areaY, areaW, areaH, timeline, backColor): label = [] if (timeline.name): label.append(timeline.name.upper()) for component in timeline.components: label.append(component.upper()) if (label): self._textBlock(x=areaX, y=areaY, w=areaW, h=areaH, textLines=label, color=Color.WHITE, font='condensed', size=PDFPrinter.FONT_XS, align='C', backColor=backColor) if (timeline.fromTime): textSize = self._measure(text=timeline.fromTime, font='italic', size=PDFPrinter.FONT_S) self._text(x=areaX, y=areaY - 1, w=areaW / 2, h=textSize.y, text=timeline.fromTime, color=Color.WHITE, font='italic', size=PDFPrinter.FONT_S, align='L', backColor=backColor) if (timeline.toTime): textSize = self._measure(text=timeline.toTime, font='italic', size=PDFPrinter.FONT_S) self._text(x=areaX + areaW / 2, y=areaY + areaH - textSize.y + 1, w=areaW / 2, h=textSize.y, text=timeline.toTime, color=Color.WHITE, font='italic', size=PDFPrinter.FONT_S, align='R', backColor=backColor) def printNotes(self, notes): x = PDFPrinter.MARGIN y = PDFPrinter.MARGIN + PDFPrinter.HEADER_HEIGHT + PDFPrinter.TABLE_HEIGHT w = PDFPrinter.CONTENT_WIDTH h = 5 for note in notes: y += h self._text(x, y, w, 0, text=note, color=Color.BLACK, font='regular', size=self.fontSize, align='L') def save(self, fileName): self.pdf.output(fileName) def _measure(self, text, font, size): self.uglyMeasure.set_font(font, size=size) self.uglyMeasure.set_xy(0, 0) self.uglyMeasure.write(size / 2.83, txt=text) sizeX = self.uglyMeasure.get_x() self.uglyMeasure.write(size / 2.83, txt="\n") sizeY = self.uglyMeasure.get_y() result = Size(sizeX, sizeY) return result def _text(self, x, y, w, h, text, color, font, size, align='C', backColor=None): self.pdf.set_text_color(color[0], color[1], color[2]) self.pdf.set_font(font, size=size) self.pdf.set_xy(x, y) fillBackground = False if (backColor): self.pdf.set_fill_color(backColor[0], backColor[1], backColor[2]) fillBackground = True self.pdf.cell(w, h, txt=text, ln=1, align=align, fill=fillBackground) def _textBlock(self, x, y, w, h, textLines, color, font, size, align='C', backColor=None): textH = 0 texts = [] for line in textLines: textSize = self._measure(text=line, font=font, size=size) textSize.y += 1 textH += textSize.y texts.append({"txt": line, "height": textSize.y}) self.pdf.set_text_color(color[0], color[1], color[2]) self.pdf.set_font(font, size=size) posY = y + (h - textH) / 2 fillBackground = False if (backColor): self.pdf.set_fill_color(backColor[0], backColor[1], backColor[2]) fillBackground = True for line in texts: self.pdf.set_xy(x, posY) self.pdf.cell(w, line["height"], txt=line["txt"], align=align, fill=fillBackground) posY += line["height"] def _box(self, x, y, w, h, color, lineColor, lineWidth=0): style = '' if (lineColor): self.pdf.set_line_width(lineWidth) self.pdf.set_draw_color(lineColor[0], lineColor[1], lineColor[2]) style += 'D' if (color): self.pdf.set_fill_color(color[0], color[1], color[2]) style += 'F' self.pdf.rect(x, y, w, h, style) def _line(self, x1, y1, x2, y2, color, lineWidth): self.pdf.set_line_width(lineWidth) self.pdf.set_draw_color(color[0], color[1], color[2]) self.pdf.line(x1, y1, x2, y2) def _findTimeWindow(self, timetable): minTime = self._timeToInt("24:00") maxTime = self._timeToInt("00:00") for daySchedule in timetable.values(): for personalSchedule in daySchedule.values(): for schedule in personalSchedule: f = self._timeToInt(schedule.fromTime) t = self._timeToInt(schedule.toTime) minTime = min(minTime, f, t) maxTime = max(maxTime, f, t) return {"fromTime": minTime, "toTime": maxTime} def _timeToInt(self, str): parts = str.split(':') return int(parts[0]) * 60 + int(parts[1])
class Report: def __init__(self, data: DataSet, stats=None) -> None: self.output_path = os.path.join(data.data_path, "stats") self.dataset_name = os.path.basename(data.data_path) self.io_handler = data.io_handler self.mapi_light_light_green = [255, 255, 255] self.mapi_light_green = [0, 0, 0] self.mapi_light_grey = [218, 222, 228] self.mapi_dark_grey = [0, 0, 0] self.pdf = FPDF("P", "mm", "A4") self.pdf.add_page() self.title_size = 20 self.h1 = 16 self.h2 = 13 self.h3 = 10 self.text = 10 self.small_text = 8 self.margin = 10 self.cell_height = 7 self.total_size = 190 self.odm_stat = 'odm_processing_statistics' if stats is not None: self.stats = stats else: self.stats = self._read_stats_file("stats.json") def save_report(self, filename: str) -> None: # pyre-fixme[28]: Unexpected keyword argument `dest`. bytestring = self.pdf.output(dest="S") if isinstance(bytestring, str): bytestring = bytestring.encode("utf8") with self.io_handler.open(os.path.join(self.output_path, filename), "wb") as fwb: fwb.write(bytestring) def _make_table(self, columns_names, rows, row_header=False) -> None: self.pdf.set_font("Helvetica", "", self.h3) self.pdf.set_line_width(0.3) columns_sizes = [int(self.total_size / len(rows[0]))] * len(rows[0]) if columns_names: self.pdf.set_draw_color(*self.mapi_light_grey) self.pdf.set_fill_color(*self.mapi_light_grey) for col, size in zip(columns_names, columns_sizes): self.pdf.rect( self.pdf.get_x(), self.pdf.get_y(), size, self.cell_height, style="FD", ) self.pdf.set_text_color(*self.mapi_dark_grey) self.pdf.cell(size, self.cell_height, col, align="L") self.pdf.set_xy(self.margin, self.pdf.get_y() + self.cell_height) self.pdf.set_draw_color(*self.mapi_light_grey) self.pdf.set_fill_color(*self.mapi_light_light_green) for row in rows: for i, (col, size) in enumerate(zip(row, columns_sizes)): if i == 0 and row_header: self.pdf.set_draw_color(*self.mapi_light_grey) self.pdf.set_fill_color(*self.mapi_light_grey) self.pdf.rect( self.pdf.get_x(), self.pdf.get_y(), size, self.cell_height, style="FD", ) self.pdf.set_text_color(*self.mapi_dark_grey) if i == 0 and row_header: self.pdf.set_draw_color(*self.mapi_light_grey) self.pdf.set_fill_color(*self.mapi_light_light_green) self.pdf.cell(size, self.cell_height, col, align="L") self.pdf.set_xy(self.margin, self.pdf.get_y() + self.cell_height) def _read_stats_file(self, filename) -> Dict[str, Any]: file_path = os.path.join(self.output_path, filename) with self.io_handler.open_rt(file_path) as fin: return io.json_load(fin) def _read_gcp_stats_file(self, filename): file_path = os.path.join(self.output_path, "ground_control_points.json") with self.io_handler.open_rt(file_path) as fin: return io.json_load(fin) def _make_section(self, title: str) -> None: self.pdf.set_font("Helvetica", "B", self.h1) self.pdf.set_text_color(*self.mapi_dark_grey) self.pdf.cell(0, self.margin, title, align="L") self.pdf.set_xy(self.margin, self.pdf.get_y() + 1.5 * self.margin) def _make_subsection(self, title: str) -> None: self.pdf.set_xy(self.margin, self.pdf.get_y() - 0.5 * self.margin) self.pdf.set_font("Helvetica", "B", self.h2) self.pdf.set_text_color(*self.mapi_dark_grey) self.pdf.cell(0, self.margin, title, align="L") self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin) def _make_centered_image(self, image_path: str, desired_height: float) -> None: with tempfile.TemporaryDirectory() as tmp_local_dir: local_image_path = os.path.join(tmp_local_dir, os.path.basename(image_path)) with self.io_handler.open(local_image_path, "wb") as fwb: with self.io_handler.open(image_path, "rb") as f: fwb.write(f.read()) width, height = PIL.Image.open(local_image_path).size resized_width = width * desired_height / height if resized_width > self.total_size: resized_width = self.total_size desired_height = height * resized_width / width self.pdf.image( local_image_path, self.pdf.get_x() + self.total_size / 2 - resized_width / 2, self.pdf.get_y(), h=desired_height, ) self.pdf.set_xy(self.margin, self.pdf.get_y() + desired_height + self.margin) def make_title(self) -> None: # title self.pdf.set_font("Helvetica", "B", self.title_size) self.pdf.set_text_color(*self.mapi_light_green) self.pdf.cell(0, self.margin, "ODM Quality Report", align="C") self.pdf.set_xy(self.margin, self.title_size) # version number version_file = os.path.abspath( os.path.join(os.path.dirname(__file__), "../../../../../VERSION")) try: with open(version_file, 'r') as f: version = f.read().strip() except Exception as e: # indicate we don't know the version version = "unknown" logger.warning(f"Invalid ODM version {version_file}: " + str(e)) self.pdf.set_font("Helvetica", "", self.small_text) self.pdf.set_text_color(*self.mapi_dark_grey) self.pdf.cell(0, self.margin, f"Processed with ODM version {version}", align="R") self.pdf.set_xy(self.margin, self.pdf.get_y() + 2 * self.margin) def make_dataset_summary(self) -> None: self._make_section("Dataset Summary") rows = [ #["Dataset", self.dataset_name], ["Date", self.stats["processing_statistics"]["date"]], [ "Area Covered", f"{self.stats['processing_statistics']['area']/1e6:.6f} km²", ], [ "Processing Time", self.stats[self.odm_stat]['total_time_human'] if self.odm_stat in self.stats else \ f"{self.stats['processing_statistics']['steps_times']['Total Time']:.2f} seconds", ], ["Capture Start", self.stats["processing_statistics"]["start_date"]], ["Capture End", self.stats["processing_statistics"]["end_date"]], ] self._make_table(None, rows, True) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin) def _has_meaningful_gcp(self) -> bool: return (self.stats["reconstruction_statistics"]["has_gcp"] and "average_error" in self.stats["gcp_errors"]) def make_processing_summary(self) -> None: self._make_section("Processing Summary") rec_shots, init_shots = ( self.stats["reconstruction_statistics"] ["reconstructed_shots_count"], self.stats["reconstruction_statistics"]["initial_shots_count"], ) rec_points, init_points = ( self.stats["reconstruction_statistics"] ["reconstructed_points_count"], self.stats["reconstruction_statistics"]["initial_points_count"], ) geo_string = [] if self.stats["reconstruction_statistics"]["has_gps"]: geo_string.append("GPS") if self._has_meaningful_gcp(): geo_string.append("GCP") ratio_shots = rec_shots / init_shots * 100 if init_shots > 0 else -1 rows = [ [ "Reconstructed Images", f"{rec_shots} over {init_shots} shots ({ratio_shots:.1f}%)", ], [ "Reconstructed Points (Sparse)", f"{rec_points} over {init_points} points ({rec_points/init_points*100:.1f}%)", ], # [ # "Reconstructed Components", # f"{self.stats['reconstruction_statistics']['components']} component", # ], [ "Detected Features", f"{self.stats['features_statistics']['detected_features']['median']:,} features", ], [ "Reconstructed Features", f"{self.stats['features_statistics']['reconstructed_features']['median']:,} features", ], ["Geographic Reference", " and ".join(geo_string)], ] # Dense (if available) if self.stats.get('point_cloud_statistics'): if self.stats['point_cloud_statistics'].get('dense'): rows.insert(2, [ "Reconstructed Points (Dense)", f"{self.stats['point_cloud_statistics']['stats']['statistic'][0]['count']:,} points" ]) # GSD (if available) if self.odm_stat in self.stats and self.stats[self.odm_stat].get( 'average_gsd'): rows.insert(3, [ "Average Ground Sampling Distance (GSD)", f"{self.stats[self.odm_stat]['average_gsd']:.1f} cm" ]) row_gps_gcp = [" / ".join(geo_string) + " errors"] geo_errors = [] if self.stats["reconstruction_statistics"]["has_gps"]: geo_errors.append( f"{self.stats['gps_errors']['average_error']:.2f}") if self._has_meaningful_gcp(): geo_errors.append( f"{self.stats['gcp_errors']['average_error']:.2f}") row_gps_gcp.append(" / ".join(geo_errors) + " meters") rows.append(row_gps_gcp) self._make_table(None, rows, True) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin / 2) topview_height = 110 topview_grids = [ f for f in self.io_handler.ls(self.output_path) if f.startswith("topview") ] self._make_centered_image( os.path.join(self.output_path, topview_grids[0]), topview_height) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin) def make_processing_time_details(self) -> None: self._make_section("Processing Time Details") columns_names = list( self.stats["processing_statistics"]["steps_times"].keys()) formatted_floats = [] for v in self.stats["processing_statistics"]["steps_times"].values(): formatted_floats.append(f"{v:.2f} sec.") rows = [formatted_floats] self._make_table(columns_names, rows) self.pdf.set_xy(self.margin, self.pdf.get_y() + 2 * self.margin) def make_gcp_error_details(self): self._make_section("Ground Control Point Error") gcp_stats = self._read_gcp_stats_file("ground_control_points.json") rows = [] column_names = ["ID", "Error X (m)", "Error Y (m)", "Error Z (m)"] for gcp in gcp_stats: row = [gcp["id"]] row.append(f"{gcp['error'][0]:.3f}") row.append(f"{gcp['error'][1]:.3f}") row.append(f"{gcp['error'][2]:.3f}") rows.append(row) self._make_table(column_names, rows) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin / 2) def make_gps_details(self) -> None: self._make_section("GPS/GCP/3D Errors Details") # GPS table_count = 0 for error_type in ["gps", "gcp", "3d"]: rows = [] columns_names = [error_type.upper(), "Mean", "Sigma", "RMS Error"] if "average_error" not in self.stats[error_type + "_errors"]: continue for comp in ["x", "y", "z"]: row = [comp.upper() + " Error (meters)"] row.append( f"{self.stats[error_type + '_errors']['mean'][comp]:.3f}") row.append( f"{self.stats[error_type +'_errors']['std'][comp]:.3f}") row.append( f"{self.stats[error_type +'_errors']['error'][comp]:.3f}") rows.append(row) rows.append([ "Total", "", "", f"{self.stats[error_type +'_errors']['average_error']:.3f}", ]) self._make_table(columns_names, rows) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin / 2) table_count += 1 if table_count > 0: abs_error_type = "gps" if table_count == 2 else "gcp" a_ce90 = self.stats[abs_error_type + "_errors"].get("ce90", 0) a_le90 = self.stats[abs_error_type + "_errors"].get("le90", 0) r_ce90 = self.stats["3d_errors"].get("ce90", 0) r_le90 = self.stats["3d_errors"].get("le90", 0) rows = [] if a_ce90 > 0 and a_le90 > 0: rows += [[ "Horizontal Accuracy CE90 (meters)", f"{a_ce90:.3f}", f"{r_ce90:.3f}" if r_ce90 > 0 else "-", ], [ "Vertical Accuracy LE90 (meters)", f"{a_le90:.3f}", f"{r_le90:.3f}" if r_le90 > 0 else "-", ]] if rows: if table_count > 2: self.add_page_break() self._make_table(["", "Absolute", "Relative"], rows, True) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin / 2) # rows = [] # columns_names = [ # "GPS Bias", # "Scale", # "Translation", # "Rotation", # ] # for camera, params in self.stats["camera_errors"].items(): # bias = params["bias"] # s, t, R = bias["scale"], bias["translation"], bias["rotation"] # rows.append( # [ # camera, # f"{s:.2f}", # f"{t[0]:.2f} {t[1]:.2f} {t[2]:.2f}", # f"{R[0]:.2f} {R[1]:.2f} {R[2]:.2f}", # ] # ) # self._make_table(columns_names, rows) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin / 2) def make_features_details(self) -> None: self._make_section("Features Details") heatmap_height = 60 heatmaps = [ f for f in self.io_handler.ls(self.output_path) if f.startswith("heatmap") ] self._make_centered_image(os.path.join(self.output_path, heatmaps[0]), heatmap_height) if len(heatmaps) > 1: logger.warning("Please implement multi-model display") columns_names = ["", "Min.", "Max.", "Mean", "Median"] rows = [] for comp in ["detected_features", "reconstructed_features"]: row = [comp.replace("_", " ").replace("features", "").capitalize()] for t in columns_names[1:]: row.append( f"{self.stats['features_statistics'][comp][t.replace('.', '').lower()]:.0f}" ) rows.append(row) self._make_table(columns_names, rows) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin) def make_reconstruction_details(self) -> None: self._make_section("Reconstruction Details") rows = [ [ "Average Reprojection Error (normalized / pixels / angular)", (f"{self.stats['reconstruction_statistics']['reprojection_error_normalized']:.2f} / " f"{self.stats['reconstruction_statistics']['reprojection_error_pixels']:.2f} / " f"{self.stats['reconstruction_statistics']['reprojection_error_angular']:.5f}" ), ], [ "Average Track Length", f"{self.stats['reconstruction_statistics']['average_track_length']:.2f} images", ], [ "Average Track Length (> 2)", f"{self.stats['reconstruction_statistics']['average_track_length_over_two']:.2f} images", ], ] self._make_table(None, rows, True) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin / 1.5) residual_histogram_height = 60 residual_histogram = [ f for f in self.io_handler.ls(self.output_path) if f.startswith("residual_histogram") ] self._make_centered_image( os.path.join(self.output_path, residual_histogram[0]), residual_histogram_height, ) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin) def make_camera_models_details(self) -> None: self._make_section("Camera Models Details") for camera, params in self.stats["camera_errors"].items(): residual_grids = [ f for f in self.io_handler.ls(self.output_path) if f.startswith("residuals_" + str(camera.replace("/", "_"))) ] if not residual_grids: continue initial = params["initial_values"] optimized = params["optimized_values"] names = [""] + list(initial.keys()) rows = [] rows.append(["Initial"] + [f"{x:.4f}" for x in initial.values()]) rows.append(["Optimized"] + [f"{x:.4f}" for x in optimized.values()]) self._make_subsection(camera) self._make_table(names, rows) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin / 2) residual_grid_height = 100 self._make_centered_image( os.path.join(self.output_path, residual_grids[0]), residual_grid_height) def make_rig_cameras_details(self) -> None: if len(self.stats["rig_errors"]) == 0: return self._make_section("Rig Cameras Details") columns_names = [ "Translation X", "Translation Y", "Translation Z", "Rotation X", "Rotation Y", "Rotation Z", ] for rig_camera_id, params in self.stats["rig_errors"].items(): initial = params["initial_values"] optimized = params["optimized_values"] rows = [] r_init, t_init = initial["rotation"], initial["translation"] r_opt, t_opt = optimized["rotation"], optimized["translation"] rows.append([ f"{t_init[0]:.4f} m", f"{t_init[1]:.4f} m", f"{t_init[2]:.4f} m", f"{r_init[0]:.4f}", f"{r_init[1]:.4f}", f"{r_init[2]:.4f}", ]) rows.append([ f"{t_opt[0]:.4f} m", f"{t_opt[1]:.4f} m", f"{t_opt[2]:.4f} m", f"{r_opt[0]:.4f}", f"{r_opt[1]:.4f}", f"{r_opt[2]:.4f}", ]) self._make_subsection(rig_camera_id) self._make_table(columns_names, rows) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin / 2) def make_tracks_details(self) -> None: self._make_section("Tracks Details") matchgraph_height = 80 matchgraph = [ f for f in self.io_handler.ls(self.output_path) if f.startswith("matchgraph") ] self._make_centered_image( os.path.join(self.output_path, matchgraph[0]), matchgraph_height) histogram = self.stats["reconstruction_statistics"][ "histogram_track_length"] start_length, end_length = 2, 10 row_length = ["Length"] for length, _ in sorted(histogram.items(), key=lambda x: int(x[0])): if int(length) < start_length or int(length) > end_length: continue row_length.append(length) row_count = ["Count"] for length, count in sorted(histogram.items(), key=lambda x: int(x[0])): if int(length) < start_length or int(length) > end_length: continue row_count.append(f"{count}") self._make_table(None, [row_length, row_count], True) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin) def add_page_break(self) -> None: self.pdf.add_page("P") def make_survey_data(self): self._make_section("Survey Data") self._make_centered_image( os.path.join(self.output_path, "overlap.png"), 90) self._make_centered_image( os.path.join(self.output_path, "overlap_diagram_legend.png"), 3) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin / 2) def _add_image_label(self, text): self.pdf.set_font_size(self.small_text) self.pdf.text( self.pdf.get_x() + self.total_size / 2 - self.pdf.get_string_width(text) / 2, self.pdf.get_y() - 5, text) def make_preview(self): ortho = os.path.join(self.output_path, "ortho.png") dsm = os.path.join(self.output_path, "dsm.png") dtm = os.path.join(self.output_path, "dtm.png") count = 0 if os.path.isfile(ortho) or os.path.isfile(dsm): self._make_section("Previews") if os.path.isfile(ortho): self._make_centered_image( os.path.join(self.output_path, ortho), 110) self._add_image_label("Orthophoto") count += 1 if os.path.isfile(dsm) and self.stats.get('dsm_statistics'): self._make_centered_image(os.path.join(self.output_path, dsm), 110) self._add_image_label("Digital Surface Model") self._make_centered_image( os.path.join(self.output_path, "dsm_gradient.png"), 4) self.pdf.set_font_size(self.small_text) min_text = "{:,.2f}m".format( self.stats['dsm_statistics']['min']) max_text = "{:,.2f}m".format( self.stats['dsm_statistics']['max']) self.pdf.text(self.pdf.get_x() + 40, self.pdf.get_y() - 5, min_text) self.pdf.text( self.pdf.get_x() + 40 + 110.5 - self.pdf.get_string_width(max_text), self.pdf.get_y() - 5, max_text) count += 1 if os.path.isfile(dtm) and self.stats.get('dtm_statistics'): if count >= 2: self.add_page_break() self._make_centered_image(os.path.join(self.output_path, dtm), 110) self._add_image_label("Digital Terrain Model") self._make_centered_image( os.path.join(self.output_path, "dsm_gradient.png"), 4) self.pdf.set_font_size(self.small_text) min_text = "{:,.2f}m".format( self.stats['dtm_statistics']['min']) max_text = "{:,.2f}m".format( self.stats['dtm_statistics']['max']) self.pdf.text(self.pdf.get_x() + 40, self.pdf.get_y() - 5, min_text) self.pdf.text( self.pdf.get_x() + 40 + 110.5 - self.pdf.get_string_width(max_text), self.pdf.get_y() - 5, max_text) self.pdf.set_xy(self.margin, self.pdf.get_y() + self.margin) return True def generate_report(self) -> None: self.make_title() self.make_dataset_summary() self.make_processing_summary() self.add_page_break() if self.make_preview(): self.add_page_break() if os.path.isfile(os.path.join(self.output_path, "overlap.png")): self.make_survey_data() self.make_gps_details() if os.path.isfile( os.path.join(self.output_path, "ground_control_points.json")): self.make_gcp_error_details() self.add_page_break() self.make_features_details() self.make_reconstruction_details() self.add_page_break() self.make_tracks_details() self.make_camera_models_details()
if text_font_data['type'] == 'embeded': pdf.add_font(text_font_data['name'], '', os.path.abspath('.') + '/app/pdf/' + text_font_data['path'], uni=True) text_font = text_font_data['name'] # header section # left pdf.set_font(title_font, '', font_size['header_title']) pdf.cell(1, line_height['section'] + 1, data['header']['name'], ln=2) pdf.set_font_size(font_size['header_sub_title']) pdf.set_text_color(grey) pdf.cell(1, line_height['text'] + 1, data['header']['title'], ln=2) pdf.set_font_size(font_size['text'] + 2) online_text = data['pdf']['online']['text'] pdf.cell(pdf.get_string_width(online_text), line_height['text'] + 1, online_text, ln=0) pdf.set_text_color(*blue) pdf.cell(1, line_height['text'] + 1, data['pdf']['online']['url'], ln=2, link=data['pdf']['online']['url']) header_y = pdf.get_y() # right pdf.set_y(page_size['top'] - 1) pdf.set_x(page_size['end_x']) pdf.set_font(text_font, '', font_size['text']) pdf.set_text_color(black) pdf.cell(1, line_height['text'] - 0.5, data['about']['location'], ln=2, align='R') pdf.cell(1, line_height['text'] - 0.5, data['about']['phone'], ln=2, align='R') pdf.cell(1, line_height['text'] - 0.5, data['about']['email'], ln=2, align='R') pdf.set_text_color(*blue) pdf.cell(1, line_height['text'] - 0.5, data['about']['socials']['blog']['url'], ln=2, align='R', link=data['about']['socials']['blog']['url']) pdf.cell(1, line_height['text'] - 0.5, data['about']['socials']['github']['url'], ln=2, align='R', link=data['about']['socials']['github']['url']) pdf.set_text_color(black) # hr pdf.set_line_width(0.4) pdf.dashed_line(page_size['left'] + 1, header_y, page_size['end_x'] + 1, header_y, 1, 1)
def create_pdf(**kwargs): """Build the PDF file from user-supplied information""" # Dictionary of variables collected from gui, to be passed to method_graf() variabledic = {"methodofservice": kwargs['servicemethod'], "documents": kwargs['docserved'].upper(), "target": kwargs['personserved'], "dateandtime": kwargs['dateserved'] + ", at " + kwargs['timeserved'], "location": kwargs['servelocation'], "subperson": kwargs['subname'], "subrelation": kwargs['subrelation'], "parentname": kwargs['parentname'], "tempguard": kwargs['guardname'], "committed": kwargs['committed'], "adminname": kwargs['adminname'], "agentname": kwargs['agentname'], } pdf=FPDF("P", "pt", "Letter") pdf.set_margins(36,36) pdf.alias_nb_pages() pdf.add_page() # State, County & Court pdf.set_font("Times", "", 12) pdf.multi_cell(h = 18, w = 540, align = "L", txt = ( "IN THE "+kwargs['court'].upper()+" COURT OF\n"+ kwargs['county'].upper()+" COUNTY, "+kwargs['state'].upper())) pdf.ln(30) # Plaintiff pcursor = pdf.get_y() pdf.multi_cell(h=18, w=400, align = "L", txt=kwargs['plaintiff'].upper()) newpcursor = pdf.get_y() pdf.set_xy(400, pcursor) pdf.cell(w = 0, align = "R", txt = "PLAINTIFF") pdf.set_xy(0, newpcursor) pdf.ln(18) # Case Number pdf.cell(h = 18, w = 20, align = "L", txt = "V.") pdf.cell(h = 18, w = 500, align = "C", txt = "CASE NO. "+kwargs['caseno'].upper()) pdf.ln(30) # Defendant pcursor = pdf.get_y() pdf.multi_cell(h=18, w=400, align = "L", txt=kwargs['defendant'].upper()) newpcursor = pdf.get_y() pdf.set_xy(400, pcursor) pdf.cell(h = 18, w = 0, align = "R", txt = "DEFENDANT") pdf.set_xy(0, newpcursor) pdf.ln(18) # Title pdf.set_font("Times", "U", 12) pdf.cell(h = 24, w = 0, align = "C", txt = "AFFIDAVIT OF SERVICE") pdf.ln(36) # Commencement pdf.set_font("Times", "", 12) pdf.multi_cell(h = 30, w = 540, align = "L", txt = ( " Comes now " + kwargs['servername'] + ", who, being duly " "sworn, deposes and says:")) # Paragraph with details of service (multi-line), called from method_graf() function pdf.multi_cell(h = 30, w = 540, align = "L", txt = method_graf(**variabledic)) # Comments if len(kwargs['comments']) > 0: pdf.multi_cell(h = 30, w = 540, align = "L", txt = " " + kwargs['comments']) # Not a party/No interest/Further affiant sayeth not, etc. pdf.multi_cell(h = 30, w = 540, align = "L", txt = ( " I am not a party to this action, and I have no interest in it. \n" " Further affiant sayeth not.")) pdf.ln(40) # Signature/Notary section pdf.line(270,pdf.get_y(),540,pdf.get_y()) pdf.set_x(270) pdf.cell(h = 24, w = 0, align = "L", txt = kwargs['servername']) pdf.ln(24) pdf.set_x(270) pdf.multi_cell(h = 18, w = 0, align = "L", txt = kwargs['serveraddress']) pdf.ln(24) pdf.set_x(36) pdf.cell(h = 18, w = 270, align = "L", txt = "Subscribed and sworn to before me this date:") pdf.line(270,pdf.get_y()+18,540,pdf.get_y()+18) pdf.ln(40) pdf.line(270,pdf.get_y()+18,540,pdf.get_y()+18) pdf.ln(24) pdf.set_x(270) pdf.cell(h = 18, w = 270, align = "L", txt = "Notary Public") pdf.ln(36) pdf.set_x(270) pdf.cell(h = 18, w = 270, align = "L", txt = "My commission expires:") pdf.line(400,pdf.get_y()+18,540,pdf.get_y()+18) # write PDF pdf.output("app/static/pdfs/your.pdf", "F")