so far no success. I've pared everything down to the simplest possible
code. The code is attached.
typing
python simple_align.py BG1.FIT BG2.FIT
gives output indicating that the alignment works fine.
however, after
pyinstaller --onedir --clean \
--hidden-import=numpy \
--hidden-import=astropy \
--hidden-import=astroalign \
--hidden-import=skimage \
--collect-all sep \
--copy-metadata sep \
--exclude-module=cv2 \
simple_align.py
then going to the dist directory
./simple_align BG1.FIT BG2.FIT
I get
Error during alignment: Input type for source not supported.
It looks like I need to send the 2 fits files in 2 more posts, since they
are too large for one message.
Judith
On Mon, Mar 17, 2025 at 5:05 PM 'Chris Barker' via PyInstaller <
[email protected]> wrote:
> 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
> <https://groups.google.com/d/msgid/pyinstaller/CALGmxE%2Bs7_q-cwRTU7abB3HYR3V2YjArywUQj_NyK2yZztSSag%40mail.gmail.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/CABuiZsg1%3D8tCchLbVu1byXOrUR4KuVqPYQBWZa3ze1u3WaTruA%40mail.gmail.com.
import sys
import numpy as np
from astropy.io import fits
import astroalign as aa
# Force astroalign to use the non-OpenCV routines
aa._HAVE_CV2 = False
if len(sys.argv) < 3:
print("Usage: python simple_align.py ref.fits toalign.fits")
sys.exit(1)
ref_file = sys.argv[1]
target_file = sys.argv[2]
# Load the reference FITS file
with fits.open(ref_file) as hdul:
ref_image = np.ascontiguousarray(hdul[0].data, dtype=np.float32)
# Load the target FITS file
with fits.open(target_file) as hdul:
target_image = np.ascontiguousarray(hdul[0].data, dtype=np.float32)
try:
# Find transformation parameters between target and reference
transform, footprint = aa.find_transform(target_image, ref_image)
dx, dy = transform.translation
rotation_deg = np.degrees(transform.rotation)
print(f"Transformation found: Δx = {dx:.2f}, Δy = {dy:.2f}, Rotation = {rotation_deg:.2f}°")
# Apply the transformation to align the target image
aligned_image, footprint = aa.apply_transform(transform, target_image, ref_image)
print("Alignment applied successfully.")
except Exception as e:
print("Error during alignment:", e)