Merge these two files and make a pdf of the slide and it's identification features below it
Merge these two files and make a pdf off the slides picture and it's identification features below it
python3 -c " from pypdf import PdfReader import os slides_path = '/home/daytona/workspace/attachments/958963bd-d509-4074-a6fa-c298202d9e2f/histo slides bims-WM.pdf' keypoints_path = '/home/daytona/workspace/attachments/958963bd-d509-4074-a6fa-c298212d9e2f/BIMS Histology _Key points of slide identification-1 (1).pdf' for path, label in [(slides_path, 'SLIDES'), (keypoints_path, 'KEYPOINTS')]: if os.path.exists(path): r = PdfReader(path) print(f'{label}: {len(r.pages)} pages') for i, p in enumerate(r.pages[:5]): txt = p.extract_text() print(f' Page {i+1} text preview: {repr(txt[:200]) if txt else \"(no text)\"}') else: print(f'{label}: FILE NOT FOUND at {path}') "
find /home/daytona/workspace/attachments/ -name "*.pdf" 2>/dev/null
python3 -c " from pypdf import PdfReader base = '/home/daytona/workspace/attachments/958963bd-d509-4074-a6fa-c298202d9e2f/' slides_path = base + 'histo slides bims-WM.pdf' keypoints_path = base + 'BIMS Histology _Key points of slide identification-1 (1).pdf' # Inspect slides PDF r1 = PdfReader(slides_path) print(f'SLIDES: {len(r1.pages)} pages') for i, p in enumerate(r1.pages): txt = p.extract_text() imgs = p.images print(f' Page {i+1}: text={repr(txt[:100]) if txt else None}, images={len(imgs)}') print() # Inspect keypoints PDF r2 = PdfReader(keypoints_path) print(f'KEYPOINTS: {len(r2.pages)} pages') for i, p in enumerate(r2.pages[:10]): txt = p.extract_text() print(f' Page {i+1}: {repr(txt[:200]) if txt else \"(no text)\"}') "
python3 -c " from pypdf import PdfReader base = '/home/daytona/workspace/attachments/958963bd-d509-4074-a6fa-c298202d9e2f/' keypoints_path = base + 'BIMS Histology _Key points of slide identification-1 (1).pdf' r = PdfReader(keypoints_path) print(f'Keypoints PDF: {len(r.pages)} pages') for i, p in enumerate(r.pages): imgs = p.images print(f' Page {i+1}: {len(imgs)} images') for j, img in enumerate(imgs): print(f' Image {j}: name={img.name}, size={len(img.data)} bytes') "
python3 -c "import fitz; print('pymupdf ok', fitz.__version__)"
python3 -c "import pdf2image; print('pdf2image ok')" 2>&1; python3 -c "import pdfplumber; print('pdfplumber ok')" 2>&1; python3 -c "from PIL import Image; print('PIL ok')" 2>&1; python3 -c "import pytesseract; print('tesseract ok')" 2>&1; which pdftoppm 2>&1; which convert 2>&1
python3 << 'EOF' import pytesseract from pdf2image import convert_from_path base = '/home/daytona/workspace/attachments/958963bd-d509-4074-a6fa-c298202d9e2f/' keypoints_path = base + 'BIMS Histology _Key points of slide identification-1 (1).pdf' pages = convert_from_path(keypoints_path, dpi=200) print(f"Keypoints PDF: {len(pages)} pages") for i, page in enumerate(pages): text = pytesseract.image_to_string(page) print(f"\n=== PAGE {i+1} ===") print(text[:2000]) EOF
mkdir -p /home/daytona/workspace/histo-merged && python3 << 'SCRIPT' # Build the merged PDF from pypdf import PdfReader from pdf2image import convert_from_path from PIL import Image, ImageDraw, ImageFont import os, textwrap base = '/home/daytona/workspace/attachments/958963bd-d509-4074-a6fa-c298202d9e2f/' slides_path = base + 'histo slides bims-WM.pdf' out_dir = '/home/daytona/workspace/histo-merged/' # ── KEY POINTS DATA ────────────────────────────────────────────────────────── # Maps slide name → list of identification features (OCR-cleaned) keypoints = { "Loose areolar connective tissue": [], # not in keypoints doc; skip "Hyaline cartilage": [ "Chondrocytes forming cell nests.", "Homogenous matrix.", "Outermost is perichondrium.", ], "Elastic cartilage": [ "Numerous chondrocytes in matrix.", "Matrix rich in elastic fibers.", "Outermost perichondrium.", ], "White fibrocartilage": [ "Absence of perichondrium.", "Matrix rich in collagen fibers.", "Very few chondrocytes arranged in rows.", ], "Bone T.S.": [ "Presence of T.S. of Haversian systems / osteons.", "Different types of lamellae.", ], "Bone L.S.": [ "Longitudinal sections of Haversian canals.", "Presence of Volkmann's canal.", "Different types of lamellae.", ], "Cardiac muscle": [ "Cylindrical, branching muscle fibers.", "Centrally placed nucleus.", "Presence of intercalated disks.", ], "Skeletal muscle": [ "Long cylindrical muscle cells.", "Alternating dark and light bands.", "Multiple nuclei at the periphery.", ], "Elastic/ large sized artery": [ "Circular, large lumen.", "Thin tunica media rich in elastic fibers.", "Thick tunica adventitia with bundles of longitudinal smooth muscles and vasa vasorum.", ], "Muscular/ medium sized artery": [ "Prominent internal elastic lamina.", "Tunica media rich in smooth muscle fibers.", "Small and round lumen.", ], "Large sized vein": [ "Collapsed lumen.", "Thin tunica media with circular muscle fibers.", "Thick tunica adventitia with bundles of longitudinal smooth muscles and vasa vasorum.", ], "Elastic artery\nMuscular artery": [ "Elastic artery: large lumen, thin tunica media rich in elastic fibers.", "Muscular artery: prominent internal elastic lamina, tunica media rich in smooth muscle.", ], "Thymus": [ "Lymphoid tissue with outermost capsule with incomplete septae.", "Lobules with cortex and medulla.", "Hassall's corpuscles in medulla.", ], "Thymus\nHassall's corpuscle": [ "Lobules with cortex and medulla.", "Hassall's corpuscles in medulla.", ], "Lymph node": [ "Lymphoid tissue with sub-capsular sinus or space.", "Cortex showing lymphatic nodules.", "Medulla: medullary cords and sinuses.", ], "Palatine tonsil": [ "Lymphoid tissue showing deep crypts.", "Stratified squamous non-keratinized epithelium lining the surface.", "Lamina propria shows lymphatic nodules with germinal center.", ], "Palatine tonsil\nStratified squamous non\nkeratinized epithelium": [ "Lymphoid tissue showing deep crypts.", "Stratified squamous non-keratinized epithelium lining the surface.", "Lamina propria shows lymphatic nodules with germinal center.", ], "spleen\nCentral artery\nWhite pulp\nRed pulp": [ "Lymphoid tissue showing white pulp and red pulp.", "White pulp with eccentrically placed arteriole.", "Red pulp rich in blood sinusoids.", ], "Thin skin": [ "Stratified squamous keratinized epithelium.", "Thin keratin.", "Hair follicles with sebaceous glands and arrector pili muscles.", ], "Thick skin": [ "Stratified squamous keratinized epithelium.", "Thick keratin.", "Absence of hair follicles.", ], "lung": [ "Honey comb appearance of alveoli.", "Simple squamous epithelium lining the pulmonary alveoli.", "Intra-pulmonary bronchi, bronchioles and respiratory bronchioles are seen.", ], "Trachea": [ "Mucosa lined by pseudostratified ciliated columnar epithelium with goblet cells.", "Sub-mucosa containing serous and mucous glands.", "Hyaline cartilaginous ring.", ], "kidney": [ "Outer cortex and inner medulla.", "Cortex containing renal corpuscles, proximal and distal convoluted tubules.", "Medulla containing Henle's loop and collecting ducts.", ], "Urinary bladder": [ "Mucosa lined by transitional epithelium.", "Submucosa is absent.", "Muscularis containing detrusor muscles arranged in ill-defined layers.", ], "ureter": [ "Star shaped lumen.", "Mucosa lined by transitional epithelium.", "Inner longitudinal and outer circular muscle coat present.", ], "Uterus\nEndometrium in proliferative phase Endometrium in secretory phase": [ "Proliferative phase: endometrium lined by simple columnar epithelium, tubular uterine glands.", "Secretory phase: thick endometrium, tortuous glands and coiled arteries.", "Thick myometrium with numerous blood vessels.", ], "Uterus: endometrium in secretory phase": [ "Thick endometrium lined by simple columnar epithelium.", "Lamina propria containing tortuous glands and coiled arteries.", "Myometrium with numerous blood vessels.", ], "ovary": [ "Tunica albuginea with germinal epithelium.", "Cortex showing ovarian follicles of different stages.", "Medulla showing blood vessels.", ], "Fallopian tube": [ "Highly folded mucosa.", "Mucosa lined by simple columnar (ciliated) epithelium.", "Inner circular and outer longitudinal muscle coat.", ], "Placenta": [ "Chorionic villi with syncytiotrophoblast and cytotrophoblast layers.", "Intervillous space containing maternal blood.", "Fetal blood vessels in villi.", ], "Umbilical cord": [ "Two umbilical arteries.", "One umbilical vein.", "Wharton's jelly is present.", ], "Prostate": [ "Prostatic acini lined by simple columnar epithelium.", "Fibromuscular stroma.", "Corpora amylacea in the lumen.", ], "Epididymis": [ "Tubules lined by pseudostratified columnar epithelium.", "Sperms in the tubular lumen.", "Thin circular muscle layer surrounding the ducts.", ], "Vas deference": [ "Small stellate lumen.", "Lined by pseudostratified columnar epithelium with stereocilia.", "Thick muscle coat of inner longitudinal, middle circular and outer longitudinal layer.", ], "Testis": [ "Numerous seminiferous tubules.", "Interstitial cells of Leydig present.", "Sertoli cells in seminiferous epithelium.", ], "Oesophagus": [ "Mucosa lined by stratified squamous non-keratinized epithelium.", "Sub-mucosa containing esophageal glands.", "Muscularis externa containing inner circular and outer longitudinal muscle layer.", ], "Stomach : pylorus": [ "Deep gastric pits.", "Lamina propria containing pyloric glands.", "Glands are lined by mucous secreting cells.", ], "Stomach : fundus": [ "Mucosa lined by simple columnar epithelium.", "Numerous chief and parietal cells in the gastric glands.", "Muscularis externa containing inner oblique, middle circular and outer longitudinal muscle layer.", ], "Ileum": [ "Small intestinal villi lined by simple columnar epithelium with goblet cells.", "Crypts of Lieberkuhn present.", "Mucosa containing Peyer's patches.", ], "Large intestine": [ "Intestinal villi are absent.", "Numerous goblet cells.", "Long and tubular Crypts of Lieberkuhn.", ], "Duodenum": [ "Numerous leaf-like intestinal villi.", "Simple columnar epithelium with brush border and goblet cells.", "Brunner's glands in sub-mucosa.", ], "Appendix": [ "Intestinal villi are absent.", "Lamina propria containing lymphoid follicles.", "Short and widely spaced Crypts of Lieberkuhn.", ], "Tongue : filiform papillae": [ "Conical papillae.", "Lined by stratified squamous keratinized epithelium.", "Absence of taste buds.", ], "Sublingual salivary gland\n(mixed-predominantly mucous)": [ "Presence of mucous acini.", "Acinar cells show flat, basal nucleus.", "Serous demilunes present.", ], "parotid salivary gland\n(purely serous)": [ "All are serous acini with narrow lumen.", "Acinar cells show basal round nucleus.", "Intercalated and striated ducts are present.", ], "submandibular salivary gland\nMixed: predominantly serous)": [ "Both serous and mucous acini with predominance of serous acini.", "Serous demilunes of Gianuzzi are present.", "Intercalated and striated ducts are present.", ], "Liver\nLiver (portal triad)": [ "Hepatic lobules with central veins.", "Radiating hepatic cords.", "Portal triad is seen.", ], "Gall bladder": [ "Simple columnar epithelium with microvilli.", "Presence of fibromuscular coat.", ], "Pancreas\nIslets of Langerhans": [ "Numerous serous acini with centroacinar cells.", "Duct system is present.", "Islets of Langerhans present.", ], "Retina": [ "Outermost pigment cell layer.", "Middle plexiform and nuclear layers.", "Innermost internal limiting membrane.", ], "Cornea": [ "Outer stratified squamous non-keratinized epithelium.", "Intermediate stroma.", "Inner endothelial lining.", ], "Nerve T.S.": [ "Bundles of nerve fibers (fascicles).", "Epineurium around the whole nerve.", "Perineurium around each fascicle.", "Endoneurium around individual fibers.", ], "Spinal ganglion Sympathetic ganglion": [ "Spinal ganglion: large pseudo-unipolar neurons in groups, centrally placed nuclei, satellite cells with well-defined capsules.", "Sympathetic ganglion: small multipolar neurons not in groups, eccentrically placed nuclei, fewer satellite cells.", ], "Cerebellum": [ "Outer molecular layer.", "Middle Purkinje cell layer.", "Inner granular layer.", ], "Cerebrum\nPyramidal cell": [ "Outer pia mater.", "Six-layered cells with pyramidal cells.", "Giant cells of Betz present in 5th layer.", ], "Pituitary gland\nPars\nnervosa\nPars\nintermedia\nPars\ndistalis": [ "Pars anterior rich in cells: acidophils and basophils and sinusoids.", "Inter-glandular cleft with few colloidal vesicles.", "Pars posterior rich in pituicytes and nerve fibers.", ], "Suprarenal gland\nmedulla\nZona reticularis\nZona fasiculata\nZona glomerulosa": [ "Outermost capsule with trabeculae.", "Cortex showing zona glomerulosa, fasiculata and reticularis.", "Medulla showing sinusoids and sympathetic ganglion cells.", ], "Thyroid gland": [ "Thyroid follicles lined by cuboidal epithelium.", "Eosinophilic colloid in follicular cavity.", "Parafollicular cells are seen.", ], } print("Keypoints loaded:", len(keypoints), "entries") print("Done") SCRIPT
python3 << 'SCRIPT' from pdf2image import convert_from_path from pypdf import PdfReader from PIL import Image, ImageDraw, ImageFont import os, io, textwrap base = '/home/daytona/workspace/attachments/958963bd-d509-4074-a6fa-c298202d9e2f/' slides_path = base + 'histo slides bims-WM.pdf' out_dir = '/home/daytona/workspace/histo-merged/' os.makedirs(out_dir, exist_ok=True) # ── KEY POINTS DATA ────────────────────────────────────────────────────────── keypoints = { "Loose areolar connective tissue": [ "Loose arrangement of fibers (collagen, elastic, reticular).", "Various cell types: fibroblasts, mast cells, macrophages.", "Abundant ground substance / intercellular matrix.", ], "Hyaline cartilage": [ "Chondrocytes forming cell nests.", "Homogenous matrix.", "Outermost is perichondrium.", ], "Elastic cartilage": [ "Numerous chondrocytes in matrix.", "Matrix rich in elastic fibers.", "Outermost perichondrium.", ], "White fibrocartilage": [ "Absence of perichondrium.", "Matrix rich in collagen fibers.", "Very few chondrocytes arranged in rows.", ], "Bone T.S.": [ "Presence of T.S. of Haversian systems / osteons.", "Different types of lamellae.", ], "Bone L.S.": [ "Longitudinal sections of Haversian canals.", "Presence of Volkmann's canal.", "Different types of lamellae.", ], "Cardiac muscle": [ "Cylindrical, branching muscle fibers.", "Centrally placed nucleus.", "Presence of intercalated disks.", ], "Skeletal muscle": [ "Long cylindrical muscle cells.", "Alternating dark and light bands.", "Multiple nuclei at the periphery.", ], "Elastic/ large sized artery": [ "Circular, large lumen.", "Thin tunica media rich in elastic fibers.", "Thick tunica adventitia with bundles of longitudinal smooth muscles and vasa vasorum.", ], "Muscular/ medium sized artery": [ "Prominent internal elastic lamina.", "Tunica media rich in smooth muscle fibers.", "Small and round lumen.", ], "Large sized vein": [ "Collapsed lumen.", "Thin tunica media with circular muscle fibers.", "Thick tunica adventitia with bundles of longitudinal smooth muscles and vasa vasorum.", ], "Elastic artery\nMuscular artery": [ "Elastic artery: large lumen, thin tunica media rich in elastic fibers.", "Muscular artery: prominent internal elastic lamina, tunica media rich in smooth muscle.", ], "Thymus": [ "Lymphoid tissue with outermost capsule with incomplete septae.", "Lobules with cortex and medulla.", "Hassall's corpuscles in medulla.", ], "Thymus\nHassall\u2019s corpuscle": [ "Lobules with cortex and medulla.", "Hassall's corpuscles in medulla.", ], "Lymph node": [ "Lymphoid tissue with sub-capsular sinus or space.", "Cortex showing lymphatic nodules.", "Medulla: medullary cords and sinuses.", ], "Palatine tonsilStratified squamous non\nkeratinized epithelium": [ "Lymphoid tissue showing deep crypts.", "Stratified squamous non-keratinized epithelium lining the surface.", "Lamina propria shows lymphatic nodules with germinal center.", ], "Palatine tonsil\nStratified squamous non\nkeratinized epithelium": [ "Lymphoid tissue showing deep crypts.", "Stratified squamous non-keratinized epithelium lining the surface.", "Lamina propria shows lymphatic nodules with germinal center.", ], "spleen\nCentral artery\nWhite pulp\nRed pulp": [ "Lymphoid tissue showing white pulp and red pulp.", "White pulp with eccentrically placed arteriole.", "Red pulp rich in blood sinusoids.", ], "Thin skin": [ "Stratified squamous keratinized epithelium.", "Thin keratin.", "Hair follicles with sebaceous glands and arrector pili muscles.", ], "Thick skin": [ "Stratified squamous keratinized epithelium.", "Thick keratin.", "Absence of hair follicles.", ], "lung": [ "Honey comb appearance of alveoli.", "Simple squamous epithelium lining the pulmonary alveoli.", "Intra-pulmonary bronchi, bronchioles and respiratory bronchioles are seen.", ], "Trachea": [ "Mucosa lined by pseudostratified ciliated columnar epithelium with goblet cells.", "Sub-mucosa containing serous and mucous glands.", "Hyaline cartilaginous ring.", ], "kidney": [ "Outer cortex and inner medulla.", "Cortex containing renal corpuscles, proximal and distal convoluted tubules.", "Medulla containing Henle's loop and collecting ducts.", ], "Urinary bladder": [ "Mucosa lined by transitional epithelium.", "Submucosa is absent.", "Muscularis containing detrusor muscles arranged in ill-defined layers.", ], "ureter": [ "Star shaped lumen.", "Mucosa lined by transitional epithelium.", "Inner longitudinal and outer circular muscle coat present.", ], "Uterus\nEndometrium in proliferative phase Endometrium in secretory phase": [ "Proliferative phase: endometrium lined by simple columnar epithelium, tubular uterine glands.", "Secretory phase: thick endometrium, tortuous glands and coiled arteries.", "Thick myometrium with numerous blood vessels.", ], "Uterus: endometrium in secretory phase": [ "Thick endometrium lined by simple columnar epithelium.", "Lamina propria containing tortuous glands and coiled arteries.", "Myometrium with numerous blood vessels.", ], "ovary": [ "Tunica albuginea with germinal epithelium.", "Cortex showing ovarian follicles of different stages.", "Medulla showing blood vessels.", ], "Fallopian tube": [ "Highly folded mucosa.", "Mucosa lined by simple columnar (ciliated) epithelium.", "Inner circular and outer longitudinal muscle coat.", ], "Placenta": [ "Chorionic villi with syncytiotrophoblast and cytotrophoblast layers.", "Intervillous space containing maternal blood.", "Fetal blood vessels in villi.", ], "Umbilical cord": [ "Two umbilical arteries.", "One umbilical vein.", "Wharton's jelly is present.", ], "Prostate": [ "Prostatic acini lined by simple columnar epithelium.", "Fibromuscular stroma.", "Corpora amylacea in the lumen.", ], "Epididymis": [ "Tubules lined by pseudostratified columnar epithelium.", "Sperms in the tubular lumen.", "Thin circular muscle layer surrounding the ducts.", ], "Vas deference": [ "Small stellate lumen.", "Lined by pseudostratified columnar epithelium with stereocilia.", "Thick muscle coat of inner longitudinal, middle circular and outer longitudinal layer.", ], "Testis": [ "Numerous seminiferous tubules.", "Interstitial cells of Leydig present.", "Sertoli cells in seminiferous epithelium.", ], "Oesophagus": [ "Mucosa lined by stratified squamous non-keratinized epithelium.", "Sub-mucosa containing esophageal glands.", "Muscularis externa containing inner circular and outer longitudinal muscle layer.", ], "Stomach : pylorus": [ "Deep gastric pits.", "Lamina propria containing pyloric glands.", "Glands are lined by mucous secreting cells.", ], "Stomach : fundus": [ "Mucosa lined by simple columnar epithelium.", "Numerous chief and parietal cells in the gastric glands.", "Muscularis externa containing inner oblique, middle circular and outer longitudinal muscle layer.", ], "Ileum": [ "Small intestinal villi lined by simple columnar epithelium with goblet cells.", "Crypts of Lieberkuhn present.", "Mucosa containing Peyer's patches.", ], "Large intestine": [ "Intestinal villi are absent.", "Numerous goblet cells.", "Long and tubular Crypts of Lieberkuhn.", ], "Duodenum": [ "Numerous leaf-like intestinal villi.", "Simple columnar epithelium with brush border and goblet cells.", "Brunner's glands in sub-mucosa.", ], "Appendix": [ "Intestinal villi are absent.", "Lamina propria containing lymphoid follicles.", "Short and widely spaced Crypts of Lieberkuhn.", ], "Tongue : filiform papillae": [ "Conical papillae.", "Lined by stratified squamous keratinized epithelium.", "Absence of taste buds.", ], "Sublingual salivary gland\n(mixed-predominantly mucous)": [ "Presence of mucous acini.", "Acinar cells show flat, basal nucleus.", "Serous demilunes present.", ], "parotid salivary gland\n(purely serous)": [ "All are serous acini with narrow lumen.", "Acinar cells show basal round nucleus.", "Intercalated and striated ducts are present.", ], "submandibular salivary gland\nMixed: predominantly serous)": [ "Both serous and mucous acini with predominance of serous acini.", "Serous demilunes of Gianuzzi are present.", "Intercalated and striated ducts are present.", ], "Liver\nLiver (portal triad)": [ "Hepatic lobules with central veins.", "Radiating hepatic cords.", "Portal triad is seen.", ], "Gall bladder": [ "Simple columnar epithelium with microvilli.", "Presence of fibromuscular coat.", ], "Pancreas\nIslets of Langerhans": [ "Numerous serous acini with centroacinar cells.", "Duct system is present.", "Islets of Langerhans present.", ], "Retina": [ "Outermost pigment cell layer.", "Middle plexiform and nuclear layers.", "Innermost internal limiting membrane.", ], "Cornea": [ "Outer stratified squamous non-keratinized epithelium.", "Intermediate stroma.", "Inner endothelial lining.", ], "Nerve T.S.": [ "Bundles of nerve fibers (fascicles).", "Epineurium around the whole nerve.", "Perineurium around each fascicle.", "Endoneurium around individual fibers.", ], "Spinal ganglion Sympathetic ganglion": [ "Spinal ganglion: large pseudo-unipolar neurons in groups, centrally placed nuclei, satellite cells with well-defined capsules.", "Sympathetic ganglion: small multipolar neurons not in groups, eccentrically placed nuclei, fewer satellite cells.", ], "Cerebellum": [ "Outer molecular layer.", "Middle Purkinje cell layer.", "Inner granular layer.", ], "Cerebrum\nPyramidal cell": [ "Outer pia mater.", "Six-layered cells with pyramidal cells.", "Giant cells of Betz present in 5th layer.", ], "Pituitary gland\nPars\nnervosa\nPars\nintermedia\nPars\ndistalis": [ "Pars anterior rich in cells: acidophils and basophils and sinusoids.", "Inter-glandular cleft with few colloidal vesicles.", "Pars posterior rich in pituicytes and nerve fibers.", ], "Suprarenal gland\nmedulla\nZona reticularis\nZona fasiculata\nZona glomerulosa": [ "Outermost capsule with trabeculae.", "Cortex showing zona glomerulosa, fasiculata and reticularis.", "Medulla showing sinusoids and sympathetic ganglion cells.", ], "Thyroid gland": [ "Thyroid follicles lined by cuboidal epithelium.", "Eosinophilic colloid in follicular cavity.", "Parafollicular cells are seen.", ], } # ── RENDER SLIDES PDF AS IMAGES ────────────────────────────────────────────── print("Converting slides PDF to images...") slide_images = convert_from_path(slides_path, dpi=150) print(f"Got {len(slide_images)} slide images") # ── READ SLIDE LABELS ───────────────────────────────────────────────────────── reader = PdfReader(slides_path) slide_labels = [] for p in reader.pages: t = p.extract_text() slide_labels.append(t.strip() if t else "") # ── BUILD OUTPUT PAGES ─────────────────────────────────────────────────────── # Page size: A4 at 150 dpi = 1240 x 1754 PAGE_W, PAGE_H = 1240, 1754 MARGIN = 50 IMG_AREA_H = 900 # height reserved for the slide image TEXT_Y_START = IMG_AREA_H + 20 # Try to load a font; fall back to default try: font_title = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 32) font_body = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 28) font_label = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 26) except: font_title = ImageFont.load_default() font_body = font_title font_label = font_title output_images = [] for idx, (slide_img, raw_label) in enumerate(zip(slide_images, slide_labels)): # Skip page 1 (cover / title page with no label) if idx == 0 and not raw_label: # still include it pass # Look up identification features features = keypoints.get(raw_label, []) if not features: # try fuzzy: strip to first line first_line = raw_label.split('\n')[0].strip() for k, v in keypoints.items(): if k.startswith(first_line) or first_line in k: features = v break # Clean label for title display title_text = raw_label.replace('\n', ' / ') if raw_label else f"Slide {idx+1}" # Create blank white page page = Image.new('RGB', (PAGE_W, PAGE_H), 'white') draw = ImageDraw.Draw(page) # ── Title bar ── draw.rectangle([0, 0, PAGE_W, 60], fill='#1a3a5c') draw.text((MARGIN, 12), title_text, font=font_title, fill='white') # ── Slide image ── img = slide_img.copy() # Scale to fit within image area max_w = PAGE_W - 2*MARGIN max_h = IMG_AREA_H - 20 img.thumbnail((max_w, max_h), Image.LANCZOS) img_x = MARGIN + (max_w - img.width) // 2 img_y = 70 page.paste(img, (img_x, img_y)) # ── Divider ── y_div = img_y + img.height + 15 draw.rectangle([MARGIN, y_div, PAGE_W - MARGIN, y_div + 3], fill='#1a3a5c') # ── Identification features ── y_text = y_div + 20 if features: draw.text((MARGIN, y_text), "Identification Features:", font=font_label, fill='#1a3a5c') y_text += 40 for i, feat in enumerate(features, 1): # Wrap long lines lines = textwrap.wrap(f"{i}. {feat}", width=85) for line in lines: if y_text > PAGE_H - 40: break draw.text((MARGIN + 10, y_text), line, font=font_body, fill='#222222') y_text += 36 else: draw.text((MARGIN, y_text), "Identification features not listed in key points document.", font=font_body, fill='#888888') output_images.append(page) print(f"Generated {len(output_images)} output pages") # ── SAVE AS PDF ─────────────────────────────────────────────────────────────── out_path = out_dir + 'Histology_Slides_with_Features.pdf' output_images[0].save( out_path, save_all=True, append_images=output_images[1:], resolution=150 ) print(f"Saved to: {out_path}") import os size = os.path.getsize(out_path) print(f"File size: {size/1024/1024:.1f} MB") SCRIPT
mkdir -p /home/daytona/workspace/histo-merged/pages && python3 << 'SCRIPT' from pdf2image import convert_from_path from pypdf import PdfReader from PIL import Image, ImageDraw, ImageFont import os, textwrap, gc base = '/home/daytona/workspace/attachments/958963bd-d509-4074-a6fa-c298202d9e2f/' slides_path = base + 'histo slides bims-WM.pdf' pages_dir = '/home/daytona/workspace/histo-merged/pages/' os.makedirs(pages_dir, exist_ok=True) keypoints = { "Loose areolar connective tissue": [ "Loose arrangement of fibers (collagen, elastic, reticular).", "Various cell types: fibroblasts, mast cells, macrophages.", "Abundant ground substance.", ], "Hyaline cartilage": ["Chondrocytes forming cell nests.", "Homogenous matrix.", "Outermost is perichondrium."], "Elastic cartilage": ["Numerous chondrocytes in matrix.", "Matrix rich in elastic fibers.", "Outermost perichondrium."], "White fibrocartilage": ["Absence of perichondrium.", "Matrix rich in collagen fibers.", "Very few chondrocytes arranged in rows."], "Bone T.S.": ["Presence of T.S. of Haversian systems / osteons.", "Different types of lamellae."], "Bone L.S.": ["Longitudinal sections of Haversian canals.", "Presence of Volkmann's canal.", "Different types of lamellae."], "Cardiac muscle": ["Cylindrical, branching muscle fibers.", "Centrally placed nucleus.", "Presence of intercalated disks."], "Skeletal muscle": ["Long cylindrical muscle cells.", "Alternating dark and light bands.", "Multiple nuclei at the periphery."], "Elastic/ large sized artery": ["Circular, large lumen.", "Thin tunica media rich in elastic fibers.", "Thick tunica adventitia with bundles of longitudinal smooth muscles and vasa vasorum."], "Muscular/ medium sized artery": ["Prominent internal elastic lamina.", "Tunica media rich in smooth muscle fibers.", "Small and round lumen."], "Large sized vein": ["Collapsed lumen.", "Thin tunica media with circular muscle fibers.", "Thick tunica adventitia with longitudinal smooth muscles and vasa vasorum."], "Elastic artery\nMuscular artery": ["Elastic artery: large lumen, thin tunica media rich in elastic fibers.", "Muscular artery: prominent internal elastic lamina, tunica media rich in smooth muscle."], "Thymus": ["Lymphoid tissue with outermost capsule with incomplete septae.", "Lobules with cortex and medulla.", "Hassall's corpuscles in medulla."], "Thymus\nHassall\u2019s corpuscle": ["Lobules with cortex and medulla.", "Hassall's corpuscles in medulla."], "Lymph node": ["Lymphoid tissue with sub-capsular sinus or space.", "Cortex showing lymphatic nodules.", "Medulla: medullary cords and sinuses."], "Palatine tonsilStratified squamous non\nkeratinized epithelium": ["Lymphoid tissue showing deep crypts.", "Stratified squamous non-keratinized epithelium lining the surface.", "Lamina propria shows lymphatic nodules with germinal center."], "Palatine tonsil\nStratified squamous non\nkeratinized epithelium": ["Lymphoid tissue showing deep crypts.", "Stratified squamous non-keratinized epithelium lining the surface.", "Lamina propria shows lymphatic nodules with germinal center."], "spleen\nCentral artery\nWhite pulp\nRed pulp": ["Lymphoid tissue showing white pulp and red pulp.", "White pulp with eccentrically placed arteriole.", "Red pulp rich in blood sinusoids."], "Thin skin": ["Stratified squamous keratinized epithelium.", "Thin keratin.", "Hair follicles with sebaceous glands and arrector pili muscles."], "Thick skin": ["Stratified squamous keratinized epithelium.", "Thick keratin.", "Absence of hair follicles."], "lung": ["Honey comb appearance of alveoli.", "Simple squamous epithelium lining the pulmonary alveoli.", "Intra-pulmonary bronchi, bronchioles and respiratory bronchioles are seen."], "Trachea": ["Mucosa lined by pseudostratified ciliated columnar epithelium with goblet cells.", "Sub-mucosa containing serous and mucous glands.", "Hyaline cartilaginous ring."], "kidney": ["Outer cortex and inner medulla.", "Cortex containing renal corpuscles, proximal and distal convoluted tubules.", "Medulla containing Henle's loop and collecting ducts."], "Urinary bladder": ["Mucosa lined by transitional epithelium.", "Submucosa is absent.", "Muscularis containing detrusor muscles in ill-defined layers."], "ureter": ["Star shaped lumen.", "Mucosa lined by transitional epithelium.", "Inner longitudinal and outer circular muscle coat present."], "Uterus\nEndometrium in proliferative phase Endometrium in secretory phase": ["Proliferative phase: endometrium lined by simple columnar epithelium, tubular uterine glands.", "Secretory phase: tortuous glands and coiled arteries.", "Thick myometrium with numerous blood vessels."], "Uterus: endometrium in secretory phase": ["Thick endometrium lined by simple columnar epithelium.", "Lamina propria containing tortuous glands and coiled arteries.", "Myometrium with numerous blood vessels."], "ovary": ["Tunica albuginea with germinal epithelium.", "Cortex showing ovarian follicles of different stages.", "Medulla showing blood vessels."], "Fallopian tube": ["Highly folded mucosa.", "Mucosa lined by simple columnar (ciliated) epithelium.", "Inner circular and outer longitudinal muscle coat."], "Placenta": ["Chorionic villi with syncytiotrophoblast and cytotrophoblast layers.", "Intervillous space containing maternal blood.", "Fetal blood vessels in villi."], "Umbilical cord": ["Two umbilical arteries.", "One umbilical vein.", "Wharton's jelly is present."], "Prostate": ["Prostatic acini lined by simple columnar epithelium.", "Fibromuscular stroma.", "Corpora amylacea in the lumen."], "Epididymis": ["Tubules lined by pseudostratified columnar epithelium.", "Sperms in the tubular lumen.", "Thin circular muscle layer surrounding the ducts."], "Vas deference": ["Small stellate lumen.", "Lined by pseudostratified columnar epithelium with stereocilia.", "Thick muscle coat of inner longitudinal, middle circular and outer longitudinal layer."], "Testis": ["Numerous seminiferous tubules.", "Interstitial cells of Leydig present.", "Sertoli cells in seminiferous epithelium."], "Oesophagus": ["Mucosa lined by stratified squamous non-keratinized epithelium.", "Sub-mucosa containing esophageal glands.", "Muscularis externa: inner circular and outer longitudinal muscle layer."], "Stomach : pylorus": ["Deep gastric pits.", "Lamina propria containing pyloric glands.", "Glands lined by mucous secreting cells."], "Stomach : fundus": ["Mucosa lined by simple columnar epithelium.", "Numerous chief and parietal cells in the gastric glands.", "Muscularis externa: inner oblique, middle circular and outer longitudinal muscle layer."], "Ileum": ["Small intestinal villi lined by simple columnar epithelium with goblet cells.", "Crypts of Lieberkuhn present.", "Mucosa containing Peyer's patches."], "Large intestine": ["Intestinal villi are absent.", "Numerous goblet cells.", "Long and tubular Crypts of Lieberkuhn."], "Duodenum": ["Numerous leaf-like intestinal villi.", "Simple columnar epithelium with brush border and goblet cells.", "Brunner's glands in sub-mucosa."], "Appendix": ["Intestinal villi are absent.", "Lamina propria containing lymphoid follicles.", "Short and widely spaced Crypts of Lieberkuhn."], "Tongue : filiform papillae": ["Conical papillae.", "Lined by stratified squamous keratinized epithelium.", "Absence of taste buds."], "Sublingual salivary gland\n(mixed-predominantly mucous)": ["Presence of mucous acini.", "Acinar cells show flat, basal nucleus.", "Serous demilunes present."], "parotid salivary gland\n(purely serous)": ["All are serous acini with narrow lumen.", "Acinar cells show basal round nucleus.", "Intercalated and striated ducts are present."], "submandibular salivary gland\nMixed: predominantly serous)": ["Both serous and mucous acini with predominance of serous acini.", "Serous demilunes of Gianuzzi are present.", "Intercalated and striated ducts are present."], "Liver\nLiver (portal triad)": ["Hepatic lobules with central veins.", "Radiating hepatic cords.", "Portal triad is seen."], "Gall bladder": ["Simple columnar epithelium with microvilli.", "Presence of fibromuscular coat."], "Pancreas\nIslets of Langerhans": ["Numerous serous acini with centroacinar cells.", "Duct system is present.", "Islets of Langerhans present."], "Retina": ["Outermost pigment cell layer.", "Middle plexiform and nuclear layers.", "Innermost internal limiting membrane."], "Cornea": ["Outer stratified squamous non-keratinized epithelium.", "Intermediate stroma.", "Inner endothelial lining."], "Nerve T.S.": ["Bundles of nerve fibers (fascicles).", "Epineurium around the whole nerve.", "Perineurium around each fascicle.", "Endoneurium around individual fibers."], "Spinal ganglion Sympathetic ganglion": ["Spinal ganglion: large pseudo-unipolar neurons in groups, centrally placed nuclei, satellite cells with well-defined capsules.", "Sympathetic ganglion: small multipolar neurons not in groups, eccentrically placed nuclei, fewer satellite cells."], "Cerebellum": ["Outer molecular layer.", "Middle Purkinje cell layer.", "Inner granular layer."], "Cerebrum\nPyramidal cell": ["Outer pia mater.", "Six-layered cells with pyramidal cells.", "Giant cells of Betz present in 5th layer."], "Pituitary gland\nPars\nnervosa\nPars\nintermedia\nPars\ndistalis": ["Pars anterior rich in cells: acidophils and basophils and sinusoids.", "Inter-glandular cleft with few colloidal vesicles.", "Pars posterior rich in pituicytes and nerve fibers."], "Suprarenal gland\nmedulla\nZona reticularis\nZona fasiculata\nZona glomerulosa": ["Outermost capsule with trabeculae.", "Cortex showing zona glomerulosa, fasiculata and reticularis.", "Medulla showing sinusoids and sympathetic ganglion cells."], "Thyroid gland": ["Thyroid follicles lined by cuboidal epithelium.", "Eosinophilic colloid in follicular cavity.", "Parafollicular cells are seen."], } # Read slide labels reader = PdfReader(slides_path) slide_labels = [p.extract_text().strip() if p.extract_text() else "" for p in reader.pages] total_pages = len(slide_labels) print(f"Total slides: {total_pages}") # Fonts try: font_title = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 28) font_body = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 24) font_label = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 24) except: font_title = ImageFont.load_default() font_body = font_title font_label = font_title PAGE_W, PAGE_H = 1240, 1754 MARGIN = 50 # Process one page at a time to avoid OOM saved = [] for idx in range(total_pages): print(f"Processing page {idx+1}/{total_pages}...") # Render just this one slide at low DPI imgs = convert_from_path(slides_path, dpi=100, first_page=idx+1, last_page=idx+1) slide_img = imgs[0] raw_label = slide_labels[idx] # Look up features features = keypoints.get(raw_label, []) if not features: first_line = raw_label.split('\n')[0].strip() for k, v in keypoints.items(): if k.startswith(first_line) or first_line in k: features = v break title_text = raw_label.replace('\n', ' / ') if raw_label else f"Slide {idx+1}" # Create page page = Image.new('RGB', (PAGE_W, PAGE_H), 'white') draw = ImageDraw.Draw(page) # Title bar draw.rectangle([0, 0, PAGE_W, 65], fill='#1a3a5c') draw.text((MARGIN, 15), title_text[:120], font=font_title, fill='white') # Slide image max_w = PAGE_W - 2*MARGIN max_h = 870 slide_img.thumbnail((max_w, max_h), Image.LANCZOS) img_x = MARGIN + (max_w - slide_img.width) // 2 img_y = 75 page.paste(slide_img, (img_x, img_y)) # Divider y_div = img_y + slide_img.height + 15 draw.rectangle([MARGIN, y_div, PAGE_W - MARGIN, y_div + 3], fill='#1a3a5c') # Features y_text = y_div + 18 if features: draw.text((MARGIN, y_text), "Identification Features:", font=font_label, fill='#1a3a5c') y_text += 38 for i, feat in enumerate(features, 1): lines = textwrap.wrap(f"{i}. {feat}", width=90) for line in lines: if y_text > PAGE_H - 30: break draw.text((MARGIN + 10, y_text), line, font=font_body, fill='#222222') y_text += 32 else: draw.text((MARGIN, y_text), "(Identification features not listed in key points document.)", font=font_body, fill='#999999') # Save individual page as JPEG out_file = os.path.join(pages_dir, f"page_{idx+1:03d}.jpg") page.save(out_file, 'JPEG', quality=85) saved.append(out_file) # Free memory del page, slide_img, imgs, draw gc.collect() print(f"\nSaved {len(saved)} page images") print("Done!") SCRIPT
python3 << 'SCRIPT' from PIL import Image import os, glob pages_dir = '/home/daytona/workspace/histo-merged/pages/' out_path = '/home/daytona/workspace/histo-merged/Histology_Slides_with_Features.pdf' page_files = sorted(glob.glob(os.path.join(pages_dir, 'page_*.jpg'))) print(f"Found {len(page_files)} pages to combine") images = [] for f in page_files: img = Image.open(f) if img.mode != 'RGB': img = img.convert('RGB') images.append(img) images[0].save( out_path, save_all=True, append_images=images[1:], resolution=100, quality=85, ) size = os.path.getsize(out_path) print(f"PDF saved: {out_path}") print(f"File size: {size/1024/1024:.1f} MB") SCRIPT
Histology Slides with Features
PDF Document · PDF