Just a suggestion- to make it even easier to diagnose, try a simple script only processes a fits file, without QT.
That will be a far simpler build, and it may be more obvious what’s missing. -CHB Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception [email protected] On Sun, Mar 16, 2025 at 3:56 PM skyjudith JAI <[email protected]> wrote: > My complete code is very long but I've made a 'minimumtest.py' which shows > the same behaviour, i.e. works in python but fails after pyinstaller. The > minimum code is below (sorry I don't see where I can include it as an > attachment). I was aligning 9 fits images but each is 7.4 Mb. Is there > somewhere I can put the fits files? > Judith > > import sys > import os > import numpy as np > from astropy.io import fits > import astroalign as aa > from PyQt5.QtWidgets import ( > QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton, > QFileDialog, QLabel > ) > from PyQt5.QtCore import QTimer > import pyqtgraph as pg > import warnings > warnings.simplefilter("ignore", DeprecationWarning) > > class FITSAlignmentApp(QMainWindow): > def __init__(self): > super().__init__() > > self.setWindowTitle("FITS Alignment Test") > self.setGeometry(100, 100, 800, 600) > > # Main widget > central_widget = QWidget(self) > self.setCentralWidget(central_widget) > > # Layout > layout = QVBoxLayout(central_widget) > > # Load button > self.load_button = QPushButton("Load FITS Files", self) > self.load_button.clicked.connect(self.load_fits_files) > layout.addWidget(self.load_button) > > # Status label > self.status_label = QLabel("Select FITS files to align", self) > layout.addWidget(self.status_label) > > # PyQtGraph ImageView > self.image_view = pg.ImageView() > layout.addWidget(self.image_view) > > # Timer for sequential loading > self.timer = QTimer() > self.timer.timeout.connect(self.show_next_image) > self.image_index = 0 > self.images = [] > self.aligned_images = [] > self.transforms = [] > > def load_fits_files(self): > """ Open file dialog and load multiple FITS files with delay """ > files, _ = QFileDialog.getOpenFileNames( > self, "Select FITS Files", os.getcwd(), # Start in the > current working directory > "FITS Files (*.fits *.fit *.fts *.FITS *.FIT *.FTS);;All Files > (*)" > ) > > if not files: > self.status_label.setText("No files selected.") > return > > # Load images > self.images = [] > for file in files: > try: > with fits.open(file) as hdul: > data = hdul[0].data > if data is not None: > self.images.append(data.astype(np.float64)) > except Exception as e: > self.status_label.setText(f"Error loading {file}: {e}") > return > > if len(self.images) < 2: > self.status_label.setText("Need at least 2 images to align.") > return > > self.status_label.setText(f"Loaded {len(self.images)} images. > Aligning...") > > # Use the first image as the reference > self.reference_image = self.images[0] > self.aligned_images = [self.reference_image] # First image is > already "aligned" > > # Align each image to the reference > self.transforms = [] > for i, img in enumerate(self.images[1:], start=1): > try: > # Compute the transformation parameters > transform, footprint = aa.find_transform(img, > self.reference_image) > > dx, dy = transform.translation # Extract x, y shifts > rotation_rad = transform.rotation # Extract rotation in > radians > rotation_deg = np.degrees(rotation_rad) # Convert to > degrees > > # Apply the transformation to align the image > print(f"Original Image {i} Shape: {img.shape}") > aligned_img, footprint = aa.apply_transform(transform, > img, self.reference_image) > # Ensure aligned_img is a NumPy array > aligned_img = np.array(aligned_img, dtype=np.float64) > print(f"Transformed Image {i} Shape: {aligned_img.shape}") > aligned_img = np.array(aligned_img, dtype=np.float64) > > print(f"Image {i}: Δx = {dx:.2f}, Δy = {dy:.2f}, Δrot = > {rotation_deg:.2f}°") > > # Ensure aligned image has the same shape as the reference > image > aligned_img = np.array(aligned_img, dtype=np.float64) > > if aligned_img.shape != self.reference_image.shape: > print(f"Warning: Shape mismatch in Image {i}. > Resizing...") > min_shape = ( > min(aligned_img.shape[0], > self.reference_image.shape[0]), > min(aligned_img.shape[1], > self.reference_image.shape[1]), > ) > aligned_img = aligned_img[:min_shape[0], :min_shape[1]] > self.reference_image = > self.reference_image[:min_shape[0], :min_shape[1]] > > self.aligned_images.append(aligned_img) > self.transforms.append(transform) > > > except Exception as e: > print(f"Error aligning image {i}: {e}") > self.aligned_images.append(img) # If alignment fails, > keep original > > self.status_label.setText("Alignment complete. Displaying > images...") > self.image_index = 0 > self.timer.start(1000) # 1-second delay between images > > def extract_transform(self, transform): > """ Extract translation and rotation from transformation matrix. > """ > dx = transform[0, 2] # Translation in x > dy = transform[1, 2] # Translation in y > rotation_radians = np.arctan2(transform[1, 0], transform[0, 0]) > rotation_degrees = np.degrees(rotation_radians) # Convert to > degrees > return dx, dy, rotation_degrees > > def show_next_image(self): > """ Show aligned images one by one before displaying the median """ > if self.image_index < len(self.aligned_images): > current_image = self.aligned_images[self.image_index] > focus_min, focus_max = self.compute_focus_range(current_image) > self.image_view.setImage(current_image, levels=(focus_min, > focus_max)) > self.status_label.setText(f"Showing aligned image > {self.image_index + 1}/{len(self.aligned_images)}") > self.image_index += 1 > else: > # Stop the timer and compute the median > self.timer.stop() > self.display_median_image() > > def display_median_image(self): > """ Compute and display the median-combined image """ > self.status_label.setText("Computing median image...") > median_image = np.nanmedian(np.stack(self.aligned_images), axis=0) > focus_min, focus_max = self.compute_focus_range(median_image) > self.image_view.setImage(median_image, levels=(focus_min, > focus_max)) > self.status_label.setText("Showing median image.") > > def compute_focus_range(self, data): > """ Compute focus_min and focus_max dynamically """ > valid_data = data[data != 0] # Exclude exact zero values > if valid_data.size > 0: > median = np.nanmedian(valid_data) > std = np.nanstd(valid_data) > min_val = np.nanmin(valid_data) > max_val = np.nanmax(valid_data) > else: > # Fallback if all values are zero > median = np.nanmedian(data) > std = np.nanstd(data) > min_val = np.nanmin(data) > max_val = np.nanmax(data) > > # Expand range slightly for better visualization > focus_min = max(median - std, min_val) > focus_max = min(median + std, max_val) > > return focus_min, focus_max > > if __name__ == "__main__": > app = QApplication(sys.argv) > window = FITSAlignmentApp() > window.show() > sys.exit(app.exec_()) > > > > > > > On Sunday, March 16, 2025 at 2:52:33 PM UTC-4 bwoodsend wrote: > > Presumably whatever submodule/package/data file is responsible for > supporting these FITS files is not being collected. I can't help beyond > that without either a minimal example + FITS file to play with or a some > clue as to what package/file is issuing that error message which will tell > us where to look for what exactly is missing. > > -- > You received this message because you are subscribed to the Google Groups > "PyInstaller" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To view this discussion visit > https://groups.google.com/d/msgid/pyinstaller/4da01cd9-0d2f-47ef-96f3-05b87ee1989bn%40googlegroups.com > <https://groups.google.com/d/msgid/pyinstaller/4da01cd9-0d2f-47ef-96f3-05b87ee1989bn%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "PyInstaller" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion visit https://groups.google.com/d/msgid/pyinstaller/CALGmxE%2Bs7_q-cwRTU7abB3HYR3V2YjArywUQj_NyK2yZztSSag%40mail.gmail.com.
