Source code for diffractio.utils_dxf

# !/usr/bin/env python3

# ----------------------------------------------------------------------
# Name:        utils_dxf.py
# Purpose:     Common functions to dxf files. It mainly uses ezdxf pachage
#
#
# Author:      Luis Miguel Sanchez Brea
#
# Created:     2024
# Copyright:   (c) Luis Miguel Sanchez-Brea AOCG / UCM
# License:     GPLv3 License
# ----------------------------------------------------------------------
# EZDXF by Manfred Moitzi


from __future__ import annotations

import os
import sys

from PIL import Image

import ezdxf
from ezdxf import recover
from ezdxf import bbox
from ezdxf.addons.drawing import RenderContext, Frontend
from ezdxf.addons.drawing.matplotlib import MatplotlibBackend
from ezdxf.layouts import Modelspace


from .utils_typing import npt, Any, NDArray,  NDArrayFloat, NDArrayComplex
from .import np, plt


[docs] def set_pixel_density(fig: plt.Figure, ax: plt.Axes, ppu: int): """_summary_ Args: fig (plt.Figure): _description_ ax (plt.Axes): _description_ ppu (int): pixels per drawing unit. """ xmin, xmax = ax.get_xlim() width = xmax - xmin ymin, ymax = ax.get_ylim() height = ymax - ymin dpi = fig.dpi width_inch = width * ppu / dpi height_inch = height * ppu / dpi fig.set_size_inches(width_inch, height_inch)
[docs] def set_pixel_size(fig: plt.Figure, size: tuple[int, int]): """_summary_ Args: fig (plt.Figure): _description_ size (tuple[int, int]): _description_ Returns: _type_: _description_ """ x, y = size fig.set_size_inches(x / fig.dpi, y / fig.dpi) return fig
[docs] def binarize(image, center_level=128): """_summary_ Args: image (_type_): _description_ center_level (int, optional): _description_. Defaults to 128. Returns: _type_: _description_ """ image_new = np.zeros_like(image) image_new[image < center_level] = 0 image_new[image > center_level] = 1 return image_new
[docs] def load_dxf(filename_dxf: str, num_pixels: tuple[int, int], verbose: bool = False): """_summary_ Args: filename_dxf (_type_): _description_ num_pixels (_type_): _description_ filename_png (str, optional): _description_. Defaults to ''. Returns: _type_: _description_ """ # Example frame: # frame: dict or bool = False, # r0 = np.array((0*um, 0)) # extent_dxf = [-500*um, +500*um, -250*um, +250*um] # temporal, for debugging filename_png = '' has_draw = False try: doc, auditor = recover.readfile(filename_dxf) except IOError: print(f'Not a DXF file or a generic I/O error.') sys.exit(1) except ezdxf.DXFStructureError: print(f'{"Invalid or corrupted DXF file."}') sys.exit(2) if filename_png == '': filename_png2 = "temp.png" else: filename_png2 = filename_png msp = doc.modelspace() # The auditor.errors attribute stores severe errors, # which may raise exceptions when rendering. if not auditor.has_errors: fig: plt.Figure = plt.figure() ax: plt.Axes = fig.add_axes([0, 0, 1, 1]) ctx = RenderContext(doc) ctx.current_layout_properties.set_colors(bg='#000000') out = MatplotlibBackend(ax) Frontend(ctx, out).draw_layout(msp, finalize=True) # set margins as you like (as relative factor of width and height) ax.margins(0) # export image with a size of 1000x600 pixels fig = set_pixel_size(fig, num_pixels) fig.savefig(filename_png2, facecolor='#000000', edgecolor='#FFFFFF') fig.clear() cache = bbox.Cache() # get overall bounding box bounding_box = bbox.extents(msp, cache=cache) p1 = bounding_box.extmin p2 = bounding_box.extmax p_min = np.array((p1[0], p1[1])) p_max = np.array((p2[0], p2[1])) im_frame = Image.open(filename_png2) np_frame = np.array(im_frame.getdata()) im = np.asarray(np_frame[:, 0].reshape([num_pixels[1], num_pixels[0]])) image_new = binarize(im, 128) # if frame is not False: # r0 = frame['r0'] # ext_dxf = frame['extension'] # points0 = np.array([(ext_dxf[0], ext_dxf[2]), (ext_dxf[1], ext_dxf[2]), # (ext_dxf[1], ext_dxf[3]), (ext_dxf[0], ext_dxf[3])]) # points0 = points0 + r0 # msp.add_lwpolyline(points0, close=True, dxfattribs={"color": 6}) if verbose: print("p_min = ", p_min) print("p_max = ", p_max) print("frame size: ", im_frame.size) # print(im_frame.format) # print(im_frame.mode) # print(image_new.min(), image_new.max()) if filename_png == '': os.remove(filename_png2) if has_draw: plt.figure() plt.imshow(image_new, cmap='gray') plt.colorbar() plt.clim(0, 1) return image_new, p_min, p_max, msp