Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read PDF changed from text to random symbols #654

Closed
mathieuboudreau opened this issue Mar 3, 2022 · 12 comments
Closed

Read PDF changed from text to random symbols #654

mathieuboudreau opened this issue Mar 3, 2022 · 12 comments
Labels
is-bug From a users perspective, this is a bug - a violation of the expected behavior with a compliant PDF PdfReader The PdfReader component is affected workflow-text-extraction From a users perspective, text extraction is the affected feature/workflow

Comments

@mathieuboudreau
Copy link

Hi there,

I've been using this script regularly on PDF for work,

import PyPDF2
from pathlib import Path
import re
import os

search_terms = ["DATA AVAILABILITY STATEMENT",
                "open source",
                "open-source",
                "opensource",
                "open science",
                "github",
                " git "
                "osf",
                "jupyter",
                "notebook",
                "octave",
                "available online",
                "released",
                "shared",
                " code ",
                "numerical phantom",
                "bitbucket",
                "sourceforge",
                "xnat",
                "reproducible research",
                "julia",
                "image set",
                "image sets",
                "raw k-space data",
                "SHA-1",
                "gitlab",
                "Docker",
                "container",
                "MyBinder",
                "Binder",
                "mrhub",
                "MR-Hub",
                "codeocean",
                "Code Ocean"]

folder_path = '.'

for filename in sorted(os.listdir(Path(folder_path))):
    if filename.endswith(".pdf"):
        # open the pdf file
        object = PyPDF2.PdfFileReader(filename)

        # get number of pages
        num_pages = object.getNumPages()
        
        found_keywords = []
        # search through keywords
        for keyword in search_terms:
            # extract text and do the search
            for page_index in range(0, num_pages):
                page_obj = object.getPage(page_index)
                page_text = page_obj.extractText() 

                search_result = re.search(keyword, page_text)

                if search_result is not None:
                    found_keywords.append(keyword)
                    break
        
        if found_keywords:
            print(filename + " contains " + str(found_keywords))

and for all PDFs I used before a few months ago, the page text was correctly being read as text (e.g. the PDF downloadable here: https://onlinelibrary.wiley.com/doi/10.1002/mrm.28965).

However, now recent PDFs (like this one: https://onlinelibrary.wiley.com/doi/10.1002/mrm.29078) are reading the pages as random symbols, like this (generated by adding print(page_text)):

ƒ
˙−
ˇˇ

ƒ
ˇ˘

−

ˇ˙
ˇ˝−
˜˚
˜ˇ

˜˜


˜˘−

“

“–‡”
“‹
“‹
⁄”


©



−
©

“‹
ƒ
−
ƒ

“‹

−



“‹

ƒ
⁄‡‡”


‹

⁄‡
−
“‹



Žƒ

So clearly, my keyword detection isn't working anymore.

I can't seem to find a difference in the PDF files (they are both Adobe InDesign 15.1 (Windows), Adobe PDF Library 15.0; modified using iText 4.2.0 by 1T3XT). Any clue on how to resolve this for the newer PDFs I'm using?

@MartinThoma MartinThoma added is-bug From a users perspective, this is a bug - a violation of the expected behavior with a compliant PDF PdfReader The PdfReader component is affected labels Apr 6, 2022
@johns1c
Copy link

johns1c commented Apr 9, 2022

The difference is in the Font objects.

The new one has a large number of embedded font objects which are all custom encoded. PyPDF2 is not very good at anything other than the standard encodings.

The old one has 5 fonts and although some are custom WinAnsi encoding is used

in the old one

@johns1c
Copy link

johns1c commented Apr 9, 2022

is this a Bug or an Limitation?

Interestingly although my viewer (where I have patched PyPDF2 to handle a wider range of encoding) does handle the new one it crashes handing the old one which has indirect content streams which then include forms objects.

@MartinThoma
Copy link
Member

is this a Bug or an Limitation?

It is a limitation which is perceived by the user as a bug :-) Although we might not have the capacity to fix this right now, I would say in general we want to fix this. I see it from the users perspective (hence it's a bug, not a new feature). But that's only terminology^^

@johns1c
Copy link

johns1c commented Apr 10, 2022

Fix available see github johns1c/pypdf2

The files below show the results of running my amended copy (based on 1.26.0) with running the latest version installed yesterday 2022-04-09.

test654_page0_1_26_0.txt

test654_page0_1_27_2.txt

I coded the amendment some time ago and believe it handles custom encoding as well as to_unicode tables. My version of wx.lib.pdfviewer uses this code and seems to handle the vast majority of PDFs.

Martin - do you think that my code could be incorporated into the "production" version?

1 I will check that I have the latest code on github

  1. it needs code review - both the approach and the detail code
  2. it needs a test suite

I am willing to do the work but I might need some hand holding.

Chris Johnson

@MartinThoma MartinThoma added the workflow-text-extraction From a users perspective, text extraction is the affected feature/workflow label Apr 16, 2022
@MartinThoma
Copy link
Member

do you think that my code could be incorporated into the "production" version?

Yes, for sure!

I am willing to do the work but I might need some hand holding.

That's what we (me and the PyPDF2 community) are here for :-) Just make a PR, we will walk through it :-)

@MartinThoma
Copy link
Member

I see that you haven't forked from PyPDF2: https://github.com/johns1c/PyPDF2

Could you maybe fork from PyPDF2: https://docs.github.com/en/get-started/quickstart/fork-a-repo

then make the changes that fixed the issue + create a PR?

@johns1c
Copy link

johns1c commented Apr 17, 2022 via email

@johns1c
Copy link

johns1c commented Apr 19, 2022 via email

@MartinThoma
Copy link
Member

Good morning!

  1. Just click on the Fork-button on the upper-right in Github. The fork can have a different name, but Github will take care of it. The important part is that the git history is the same
  2. You don't have access to anything. Forking is making a copy. You don't have access to any credentials. Don't worry :-)
  3. That's impossible to answer, but I hope that by now the tests cover most typical use-cases.
  4. Yes! You can install from a local copy by pip install -e . in that folder. The -e stands for "editable". It means that your installation points to that directory. So you don't have to re-install for changes - it will automatically use the files you're editing.
  5. Don't worry about that. Yes, there will be a lot of changes in the next months, but it might be nothing that affects your PR. We will cross that bridge if we get there.

@MartinThoma
Copy link
Member

This issue has been fixed with #924

Example

from PyPDF2 import PdfReader

reader = PdfReader("magnetic.pdf")   # https://onlinelibrary.wiley.com/doi/10.1002/mrm.29078
text = reader.pages[0].extract_text()

text then is:

138 |     Magn Reson Med. 2022;87:138–149.

wileyonlinelibrary.com/journal/mrm
Received: 28 April 2021 | Revised: 30 June 2021 | Accepted: 23 July 2021DOI: 10.1002/mrm.28965  

RESEARCH ARTICLE
Clinical translation of hyperpolarized  13C pyruvate and urea MRI for simultaneous metabolic and perfusion imaging
Hecong/uni00A0Qin1,2 |   Shuyu/uni00A0Tang 1 |   Andrew M./uni00A0Riselli 1 |   Robert A./uni00A0Bok1 |   Romelyn/uni00A0Delos Santos
1 |   Mark/uni00A0van Criekinge 1 |   Jeremy W./uni00A0Gordon 1 |   Rahul/uni00A0Aggarwal
3 |   Rui/uni00A0Chen4 |   Gregory/uni00A0Goddard5 |   Chunxin Tracy/uni00A0Zhang 5 |    Albert/uni00A0Chen
4 |   Galen/uni00A0Reed4 |   Daniel M./uni00A0Ruscitto4 |   James/uni00A0Slater1 |   Renuka/uni00A0Sriram1 |   Peder E. Z./uni00A0Larson
1,2 |   Daniel B./uni00A0Vigneron 1,2 |   John/uni00A0Kurhanewicz 1,2

1Department of Radiology and Biomedical Imaging, University of California, San Francisco, San Francisco, California, USA
2Graduate Program in Bioengineering, University of California, Berkeley and San Francisco, San Francisco, California, USA
3Department of Medicine, University of California, San Francisco, San Francisco, California, USA
4General Electric Healthcare, Milwaukee, Wisconsin, USA
5General Electric Research, Niskayuna, New York, USA
This is an open access article under the terms of the Creat ive Commo ns Attri butio n- NonCo mmerc ial- NoDerivs License, which permits use and distribution in any medium, provided the original work is properly cited, the use is non- commercial and no modifications or adaptations are made.© 2021 The Authors. Magnetic Resonance in Medicine published by Wiley Periodicals LLC on behalf of International Society for Magnetic Resonance in Medicine. CorrespondenceJohn Kurhanewicz, Professor of Radiology and Biomedical Imaging, Pharmaceutical Chemistry, and Urology, University of California, San Francisco (UCSF), 1700 4th St., Suite 203, Box 2520, San Francisco, CA 94143, USA.Email: John.Kurhanewicz@ucsf.eduPresent addressShuyu Tang, HeartVista Inc., Los Altos, California, USAFunding informationNational Institute of Health, Grant/Award Number: P41EB013598 and R01CA214554
 Purpose: The combined hyperpolarized (HP)  13C pyruvate and urea MRI has pro-vided a simultaneous assessment of glycolytic metabolism and tissue perfusion for improved cancer diagnosis and therapeutic evaluation in preclinical studies. This work aims to translate this dual- probe HP imaging technique to clinical research.Methods: A co- polarization system was developed where [1- 
13C]pyruvic acid (PA) and [
13C, 15N2]urea in water solution were homogeneously mixed and polarized on a 5T SPINlab system. Physical and chemical characterizations and toxicology stud-ies of the combined probe were performed. Simultaneous metabolic and perfusion imaging was performed on a 3T clinical MR scanner by alternatively applying a multi- slice 2D spiral sequence for [1- 
13C]pyruvate and its downstream metabolites and a 3D balanced steady- state free precession (bSSFP) sequence for [
13C, 15N2]urea.Results: The combined PA/urea probe has a glass- formation ability similar to neat PA and can generate nearly 40% liquid- state 
13C polarization for both pyruvate and urea in 3- 4 h. A standard operating procedure for routine on- site production was developed and validated to produce 40 mL injection product of approximately 150 mM pyruvate and 35 mM urea. The toxicology study demonstrated the safety profile of the combined probe. Dynamic metabolite- specific imaging of [1- 
13C]pyruvate,   [1- 
13C]lactate, [1- 13C]alanine, and [13C, 15N2]urea was achieved with adequate 

@mathieuboudreau
Copy link
Author

Thanks a lot everyone! Really appreciate the work you put into this fix/feature, and overall package!

@MartinThoma
Copy link
Member

by now #924 is not relased. I will relase PyPDF2==2.1.0 today.

MartinThoma added a commit that referenced this issue Jun 6, 2022
The highlight of the 2.1.0 release is the most massive improvement to the
text extraction capabilities of PyPDF2 since 2016 🥳🎊 A very big thank you goes
to [pubpub-zz](https://github.com/pubpub-zz) who took a lot of time and
knowledge about the PDF format to finally get those improvements into PyPDF2.
Thank you 🤗💚

In case the new function causes any issues, you can use `_extract_text_old`
for the old functionality. Please also open a bug ticket in that case.

There were several people who have attempted to bring similar improvements to
PyPDF2. All of those were valuable. The main reason why they didn't get merged
is the big amount of open PRs / issues. pubpub-zz was the most comprehensive
PR which also incorporated the latest changes of PyPDF2 2.0.0.

Thank you to [VictorCarlquist](https://github.com/VictorCarlquist) for #858 and
[asabramo](https://github.com/asabramo) for #464 🤗

New Features (ENH):
-  Massive text extraction improvement (#924). Closed many open issues:
    - Exceptions / missing spaces in extract_text() method (#17) 🕺
      - Whitespace issues in extract_text() (#42) 💃
      - pypdf2 reads the hifenated words in a new line (#246)
    - PyPDF2 failing to read unicode character (#37)
      - Unable to read bullets (#230)
    - ExtractText yields nothing for apparently good PDF (#168) 🎉
    - Encoding issue in extract_text() (#235)
    - extractText() doesn't work on Chinese PDF (#252)
    - encoding error (#260)
    - Trouble with apostophes in names in text "O'Doul" (#384)
    - extract_text works for some PDF files, but not the others (#437)
    - Euro sign not being recognized by extractText (#443)
    - Failed extracting text from French texts (#524)
    - extract_text doesn't extract ligatures correctly (#598)
    - reading spanish text - mark convert issue (#635)
    - Read PDF changed from text to random symbols (#654)
    - .extractText() reads / as 1. (#789)
-  Update glyphlist (#947) - inspired by #464
-  Allow adding PageRange objects (#948)

Bug Fixes (BUG):
-  Delete .python-version file (#944)
-  Compare StreamObject.decoded_self with None (#931)

Robustness (ROB):
-  Fix some conversion errors on non conform PDF (#932)

Documentation (DOC):
-  Elaborate on PDF text extraction difficulties (#939)
-  Add logo (#942)
-  rotate vs Transformation().rotate (#937)
-  Example how to use PyPDF2 with AWS S3 (#938)
-  How to deprecate (#930)
-  Fix typos on robustness page (#935)
-  Remove scripts (pdfcat) from docs (#934)

Developer Experience (DEV):
-  Ignore .python-version file
-  Mark deprecated code with no-cover (#943)
-  Automatically create Github releases from tags (#870)

Testing (TST):
-  Text extraction for non-latin alphabets (#954)
-  Ignore PdfReadWarning in benchmark (#949)
-  writer.remove_text (#946)
-  Add test for Tree and _security (#945)

Code Style (STY):
-  black, isort, Flake8, splitting buildCharMap (#950)

Full Changelog: 2.0.0...2.1.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
is-bug From a users perspective, this is a bug - a violation of the expected behavior with a compliant PDF PdfReader The PdfReader component is affected workflow-text-extraction From a users perspective, text extraction is the affected feature/workflow
Projects
None yet
Development

No branches or pull requests

3 participants