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)

Reply via email to