コード例 #1
0
    def saveLiveJPG(self, array, startTime):
        """ Save a live.jpg file to the data directory with the latest compressed image. """


        # Name of the file
        live_name = 'live.jpg'

        # Generate the name for the file
        timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(startTime))

        maxpixel, _, _, _ = np.split(array, 4, axis=0)
        maxpixel = np.array(maxpixel[0])

        # Draw text to image
        font = cv2.FONT_HERSHEY_SIMPLEX
        text = self.config.stationID + " " + timestamp + " UTC"
        cv2.putText(maxpixel, text, (10, maxpixel.shape[0] - 6), font, 0.4, (255, 255, 255), 1, \
            cv2.LINE_AA)

        # Save the labelled image to disk
        try:
            # Save the file to disk
            saveImage(os.path.join(self.config.data_dir, live_name), maxpixel)
        except:
            log.error("Could not save {:s} to disk!".format(live_name))
コード例 #2
0
ファイル: BatchFFtoImage.py プロジェクト: satmonkey/RMS
def batchFFtoImage(dir_path, fmt):
    # Go through all files in the given folder
    for file_name in os.listdir(dir_path):

        # Check if the file is an FF file
        if validFFName(file_name):

            # Read the FF file
            ff = readFF(dir_path, file_name)

            # Skip the file if it could not be read
            if ff is None:
                continue

            # Make a filename for the image
            img_file_name = file_name.replace('fits', '') + fmt

            print('Saving: ', img_file_name)

            # Save the maxpixel to disk
            saveImage(os.path.join(dir_path, img_file_name), ff.maxpixel)
コード例 #3
0
def stackFFs(dir_path,
             file_format,
             deinterlace=False,
             subavg=False,
             filter_bright=False,
             flat_path=None,
             file_list=None,
             mask=None):
    """ Stack FF files in the given folder. 

    Arguments:
        dir_path: [str] Path to the directory with FF files.
        file_format: [str] Image format for the stack. E.g. jpg, png, bmp

    Keyword arguments:
        deinterlace: [bool] True if the image shoud be deinterlaced prior to stacking. False by default.
        subavg: [bool] Whether the average pixel image should be subtracted form the max pixel image. False
            by default. 
        filter_bright: [bool] Whether images with bright backgrounds (after average subtraction) should be
            skipped. False by defualt.
        flat_path: [str] Path to the flat calibration file. None by default. Will only be used if subavg is
            False.
        file_list: [list] A list of file for stacking. False by default, in which case all FF files in the
            given directory will be used.
        mask: [MaskStructure] Mask to apply to the stack. None by default.

    Return:
        stack_path, merge_img:
            - stack_path: [str] Path of the save stack.
            - merge_img: [ndarray] Numpy array of the stacked image.
    """

    # Load the flat if it was given
    flat = None
    if flat_path != '':

        # Try finding the default flat
        if flat_path is None:
            flat_path = dir_path
            flat_file = 'flat.bmp'

        else:
            flat_path, flat_file = os.path.split(flat_path)

        flat_full_path = os.path.join(flat_path, flat_file)
        if os.path.isfile(flat_full_path):

            # Load the flat
            flat = loadFlat(flat_path, flat_file)

            print('Loaded flat:', flat_full_path)

    first_img = True

    n_stacked = 0
    total_ff_files = 0
    merge_img = None

    # If the list of files was not given, take all files in the given folder
    if file_list is None:
        file_list = sorted(os.listdir(dir_path))

    # List all FF files in the current dir
    for ff_name in file_list:
        if validFFName(ff_name):

            # Load FF file
            ff = readFF(dir_path, ff_name)

            # Skip the file if it is corruped
            if ff is None:
                continue

            total_ff_files += 1

            maxpixel = ff.maxpixel
            avepixel = ff.avepixel

            # Dinterlace the images
            if deinterlace:
                maxpixel = deinterlaceBlend(maxpixel)
                avepixel = deinterlaceBlend(avepixel)

            # If the flat was given, apply it to the image, only if no subtraction is done
            if (flat is not None) and not subavg:
                maxpixel = applyFlat(maxpixel, flat)
                avepixel = applyFlat(avepixel, flat)

            # Reject the image if the median subtracted image is too bright. This usually means that there
            #   are clouds on the image which can ruin the stack
            if filter_bright:

                img = maxpixel - avepixel

                # Compute surface brightness
                median = np.median(img)

                # Compute top detection pixels
                top_brightness = np.percentile(img, 99.9)

                # Reject all images where the median brightness is high
                # Preserve images with very bright detections
                if (median > 10) and (top_brightness <
                                      (2**(8 * img.itemsize) - 10)):
                    print('Skipping: ', ff_name, 'median:', median,
                          'top brightness:', top_brightness)
                    continue

            # Subtract the average from maxpixel
            if subavg:
                img = maxpixel - avepixel

            else:
                img = maxpixel

            if first_img:
                merge_img = np.copy(img)
                first_img = False
                continue

            print('Stacking: ', ff_name)

            # Blend images 'if lighter'
            merge_img = blendLighten(merge_img, img)

            n_stacked += 1

    # If the number of stacked image is less than 20% of the given images, stack without filtering
    if filter_bright and (n_stacked < 0.2 * total_ff_files):
        return stackFFs(dir_path,
                        file_format,
                        deinterlace=deinterlace,
                        subavg=subavg,
                        filter_bright=False,
                        flat_path=flat_path,
                        file_list=file_list)

    # If no images were stacked, do nothing
    if n_stacked == 0:
        return None, None

    # Extract the name of the night directory which contains the FF files
    night_dir = os.path.basename(dir_path)

    stack_path = os.path.join(
        dir_path,
        night_dir + '_stack_{:d}_meteors.'.format(n_stacked) + file_format)

    print("Saving stack to:", stack_path)

    # Stretch the levels
    merge_img = adjustLevels(merge_img, np.percentile(merge_img, 0.5), 1.3,
                             np.percentile(merge_img, 99.9))

    # Apply the mask, if given
    if mask is not None:
        merge_img = MaskImage.applyMask(merge_img, mask)

    # Save the blended image
    saveImage(stack_path, merge_img)

    return stack_path, merge_img
コード例 #4
0
def processNight(night_data_dir, config, detection_results=None, nodetect=False):
    """ Given the directory with FF files, run detection and archiving. 
    
    Arguments:
        night_data_dir: [str] Path to the directory with FF files.
        config: [Config obj]

    Keyword arguments:
        detection_results: [list] An optional list of detection. If None (default), detection will be done
            on the the files in the folder.
        nodetect: [bool] True if detection should be skipped. False by default.

    Return:
        night_archive_dir: [str] Path to the night directory in ArchivedFiles.
        archive_name: [str] Path to the archive.
        detector: [QueuedPool instance] Handle to the detector.
    """

    # Remove final slash in the night dir
    if night_data_dir.endswith(os.sep):
        night_data_dir = night_data_dir[:-1]

    # Extract the name of the night
    night_data_dir_name = os.path.basename(os.path.abspath(night_data_dir))

    platepar = None
    
    # If the detection should be run
    if (not nodetect):

        # If no detection was performed, run it
        if detection_results is None:

            # Run detection on the given directory
            calstars_name, ftpdetectinfo_name, ff_detected, \
                detector = detectStarsAndMeteorsDirectory(night_data_dir, config)

        # Otherwise, save detection results
        else:

            # Save CALSTARS and FTPdetectinfo to disk
            calstars_name, ftpdetectinfo_name, ff_detected = saveDetections(detection_results, \
                night_data_dir, config)

            # If the files were previously detected, there is no detector
            detector = None


        # Get the platepar file
        platepar, platepar_path, platepar_fmt = getPlatepar(config, night_data_dir)


        # Run calibration check and auto astrometry refinement
        if (platepar is not None) and (calstars_name is not None):

            # Read in the CALSTARS file
            calstars_list = CALSTARS.readCALSTARS(night_data_dir, calstars_name)

            # Run astrometry check and refinement
            platepar, fit_status = autoCheckFit(config, platepar, calstars_list)

            # If the fit was sucessful, apply the astrometry to detected meteors
            if fit_status:

                log.info('Astrometric calibration SUCCESSFUL!')

                # Save the refined platepar to the night directory and as default
                platepar.write(os.path.join(night_data_dir, config.platepar_name), fmt=platepar_fmt)
                platepar.write(platepar_path, fmt=platepar_fmt)

            else:
                log.info('Astrometric calibration FAILED!, Using old platepar for calibration...')


            # # Calculate astrometry for meteor detections
            # applyAstrometryFTPdetectinfo(night_data_dir, ftpdetectinfo_name, platepar_path)

            # If a flat is used, disable vignetting correction
            if config.use_flat:
                platepar.vignetting_coeff = 0.0

            log.info("Recalibrating astrometry on FF files with detections...")

            # Recalibrate astrometry on every FF file and apply the calibration to detections
            recalibrateIndividualFFsAndApplyAstrometry(night_data_dir, os.path.join(night_data_dir, \
                ftpdetectinfo_name), calstars_list, config, platepar)

            

            log.info("Converting RMS format to UFOOrbit format...")

            # Convert the FTPdetectinfo into UFOOrbit input file
            FTPdetectinfo2UFOOrbitInput(night_data_dir, ftpdetectinfo_name, platepar_path)



            # Generate a calibration report
            log.info("Generating a calibration report...")
            try:
                generateCalibrationReport(config, night_data_dir, platepar=platepar)

            except Exception as e:
                log.debug('Generating calibration report failed with the message:\n' + repr(e))
                log.debug(repr(traceback.format_exception(*sys.exc_info())))


            # Perform single station shower association
            log.info("Performing single station shower association...")
            try:
                showerAssociation(config, [os.path.join(night_data_dir, ftpdetectinfo_name)], \
                    save_plot=True, plot_activity=True)

            except Exception as e:
                log.debug('Shower association failed with the message:\n' + repr(e))
                log.debug(repr(traceback.format_exception(*sys.exc_info())))


    else:
        ff_detected = []
        detector = None



    log.info('Plotting field sums...')

    # Plot field sums
    try:
        plotFieldsums(night_data_dir, config)

    except Exception as e:
        log.debug('Plotting field sums failed with message:\n' + repr(e))
        log.debug(repr(traceback.format_exception(*sys.exc_info())))



    # Archive all fieldsums to one archive
    archiveFieldsums(night_data_dir)


    # List for any extra files which will be copied to the night archive directory. Full paths have to be 
    #   given
    extra_files = []


    log.info('Making a flat...')

    # Make a new flat field image
    try:
        flat_img = makeFlat(night_data_dir, config)

    except Exception as e:
        log.debug('Making a flat failed with message:\n' + repr(e))
        log.debug(repr(traceback.format_exception(*sys.exc_info())))
        flat_img = None
        

    # If making flat was sucessfull, save it
    if flat_img is not None:

        # Save the flat in the night directory, to keep the operational flat updated
        flat_path = os.path.join(night_data_dir, os.path.basename(config.flat_file))
        saveImage(flat_path, flat_img)
        log.info('Flat saved to: ' + flat_path)

        # Copy the flat to the night's directory as well
        extra_files.append(flat_path)

    else:
        log.info('Making flat image FAILED!')


    ### Add extra files to archive

    # Add the config file to the archive too
    extra_files.append(os.path.join(os.getcwd(), '.config'))

    # Add the mask
    if (not nodetect):
        if os.path.exists(config.mask_file):
            mask_path = os.path.abspath(config.mask_file)
            extra_files.append(mask_path)


    # Add the platepar to the archive if it exists
    if (not nodetect):
        if os.path.exists(platepar_path):
            extra_files.append(platepar_path)


    # Add the json file with recalibrated platepars to the archive
    if (not nodetect):
        recalibrated_platepars_path = os.path.join(night_data_dir, config.platepars_recalibrated_name)
        if os.path.exists(recalibrated_platepars_path):
            extra_files.append(recalibrated_platepars_path)

    ### ###



    # If the detection should be run
    if (not nodetect):

        # Make a CAL file and a special CAMS FTPdetectinfo if full CAMS compatibility is desired
        if (config.cams_code > 0) and (platepar is not None):

            log.info('Generating a CAMS FTPdetectinfo file...')

            # Write the CAL file to disk
            cal_file_name = writeCAL(night_data_dir, config, platepar)

            # Check if the CAL file was successfully generated
            if cal_file_name is not None:

                cams_code_formatted = "{:06d}".format(int(config.cams_code))

                # Load the FTPdetectinfo
                _, fps, meteor_list = readFTPdetectinfo(night_data_dir, ftpdetectinfo_name, \
                    ret_input_format=True)

                # Replace the camera code with the CAMS code
                for met in meteor_list:

                    # Replace the station name and the FF file format
                    ff_name = met[0]
                    ff_name = ff_name.replace('.fits', '.bin')
                    ff_name = ff_name.replace(config.stationID, cams_code_formatted)
                    met[0] = ff_name


                # Write the CAMS compatible FTPdetectinfo file
                writeFTPdetectinfo(meteor_list, night_data_dir, \
                    ftpdetectinfo_name.replace(config.stationID, cams_code_formatted),\
                    night_data_dir, cams_code_formatted, fps, calibration=cal_file_name, \
                    celestial_coords_given=(platepar is not None))



    night_archive_dir = os.path.join(os.path.abspath(config.data_dir), config.archived_dir, 
        night_data_dir_name)


    log.info('Archiving detections to ' + night_archive_dir)
    
    # Archive the detections
    archive_name = archiveDetections(night_data_dir, night_archive_dir, ff_detected, config, \
        extra_files=extra_files)


    return night_archive_dir, archive_name, detector
コード例 #5
0
ファイル: FRbinMosaic.py プロジェクト: tammojan/RMS
def makeFRmosaic(dir_path, border=5):
    """ Make a mosaic out of an FR bin file. """

    dir_path, file_name = os.path.split(dir_path)

    # Load the FR file
    fr = readFR(dir_path, file_name)

    # Go through all lines in the file
    for i in range(fr.lines):

        # Determine the maximum size of the window
        max_size = max([fr.size[i][z] for z in range(fr.frameNum[i])])

        # Determine the width and the height in frame segments
        height = int(np.ceil(np.sqrt(fr.frameNum[i])))
        width = int(np.ceil(fr.frameNum[i] / height))

        # Compute the image width and height
        w_img = int(np.ceil(width * (border + max_size)))
        h_img = int(np.ceil(height * (border + max_size)))

        # Create an empty mosaic image
        mosaic_img = np.zeros((h_img, w_img), dtype=np.uint8)

        x_min = w_img
        x_max = 0
        y_min = h_img
        y_max = 0

        # Go through all frames
        for z in range(fr.frameNum[i]):

            # # Get the center position of the detection on the current frame
            # yc = fr.yc[i][z]
            # xc = fr.xc[i][z]

            # # Get the frame number
            # t = fr.t[i][z]

            # Get the size of the window
            size = fr.size[i][z]

            # Compute the position of the frame on the image (tiling)
            h_ind = int(z % height)
            v_ind = int(z / height)

            # Compute the position of the frame on the image in image coordinates
            frame_x = h_ind * max_size + border + (max_size - size) // 2 + 1
            frame_y = v_ind * max_size + border + (max_size - size) // 2 + 1

            # Get the frame size
            fr_y, fr_x = fr.frames[i][z].shape

            # Assign the frame to the mosaic
            mosaic_img[frame_y:(frame_y + fr_y),
                       frame_x:(frame_x + fr_x)] = fr.frames[i][z]

            # Keep track of the min and max value of the extent of the frames
            x_min = min(x_min, frame_x)
            x_max = max(x_max, frame_x + fr_x)
            y_min = min(y_min, frame_y)
            y_max = max(y_max, frame_y + fr_y)

        # Draw a grid
        for h_ind in range(height + 1):

            # Draw horizontal lines
            mosaic_img[h_ind * max_size + border, :] = 255

        for v_ind in range(width + 1):

            # Draw horizontal lines
            mosaic_img[:, v_ind * max_size + border] = 255

        # Cut the image to the size of the frames
        mosaic_img = mosaic_img[y_min:y_max, x_min:x_max]

        # Save the image to disk
        img_file_name = ".".join(file_name.split('.')[:-1]) + '_mosaic.png'
        saveImage(os.path.join(dir_path, img_file_name), mosaic_img)

        # Plot the image
        plt.imshow(mosaic_img, cmap='gray', vmin=0, vmax=255)
        plt.show()
コード例 #6
0
ファイル: StackImgs.py プロジェクト: tammojan/RMS
            # Deinterlace the image
            if cml_args.deinterlace:
                img = deinterlaceBlend(img)


            if first_img:
                merge_img = np.copy(img)
                first_img = False
                continue

            # Blend images 'if lighter'
            merge_img = blendLighten(merge_img, img)


    stack_path = os.path.join(dir_path, 'stacked.' + cml_args.output_file_format[0])

    print("Saving to:", stack_path)
    
    # Save the blended image
    saveImage(stack_path, merge_img)

    # Plot the blended image
    plt.imshow(merge_img, cmap='gray')

    plt.show()




コード例 #7
0
ファイル: MakeFlat.py プロジェクト: tammojan/RMS
        help="""Use image files (bmp, png, jpg) for flat instead of FF files. Images of the file type with the higest frequency in the directory will be taken.""")

    # Parse the command line arguments
    cml_args = arg_parser.parse_args()

    #########################

    dir_path = cml_args.dir_path[0]

    # Load the configuration file
    config = cr.parse(".config")

    # Make the flat
    ff_median = makeFlat(dir_path,
                         config,
                         nostars=cml_args.nostars,
                         use_images=cml_args.images)

    if ff_median is not None:

        # Save the flat in the input directory
        input_dir_flat = os.path.join(dir_path, config.flat_file)
        saveImage(input_dir_flat, ff_median)
        print('Flat saved to:', input_dir_flat)

        import matplotlib.pyplot as plt
        plt.imshow(ff_median, cmap='gray', vmin=0, vmax=255)
        plt.show()

    else:
        print('Flat filed could not be made!')
コード例 #8
0
        help='File format of the image, e.g. jpg or png.')

    # Parse the command line arguments
    cml_args = arg_parser.parse_args()

    #########################

    dir_path = cml_args.dir_path[0]

    # Go through all files in the given folder
    for file_name in os.listdir(dir_path):

        # Check if the file is an FF file
        if validFFName(file_name):

            # Read the FF file
            ff = readFF(dir_path, file_name)

            # Skip the file if it could not be read
            if ff is None:
                continue

            # Make a filename for the image
            img_file_name = file_name.replace('fits',
                                              '') + cml_args.file_format[0]

            print('Saving: ', img_file_name)

            # Save the maxpixel to disk
            saveImage(os.path.join(dir_path, img_file_name), ff.maxpixel)