示例#1
0
def match_2dhist_fit(imglist, reference_catalog, print_fit_parameters=True):
    """Perform cross-matching and final fit using 2dHistogram matching

    Parameters
    ----------
    imglist : list
        List of input image NDData objects with metadata and source catalogs

    reference_catalog : Table
        Astropy Table of reference sources for this field

    print_fit_parameters : bool
        Specify whether or not to print out FIT results for each chip


    Returns
    --------
    fit_rms : float
        Visit level RMS for the FIT

    fit_num : int
        Number of sources used to generate visit level FIT and `fit_rms`

    """
    print(
        "-------------------- STEP 5b: (match_2dhist_fit) Cross matching and fitting --------------------"
    )
    # Specify matching algorithm to use
    match = tweakwcs.TPMatch(searchrad=75,
                             separation=0.1,
                             tolerance=2.0,
                             use2dhist=True)
    # Align images and correct WCS
    tweakwcs.tweak_image_wcs(imglist, reference_catalog, match=match)
    # Interpret RMS values from tweakwcs
    interpret_fit_rms(imglist, reference_catalog)

    # determine the quality of the fit
    fit_rms, fit_num = determine_fit_quality(
        imglist, print_fit_parameters=print_fit_parameters)

    return fit_rms, fit_num
示例#2
0
    def test_pipeline(self, input_filenames):
        """Test of new pipeline alignment components (call separately)

        This test performs separate fits to each chip separately.

        Success Criteria
        -----------------
          * nmatches > 0 on all chips
          * xrms and yrms < 30mas on all chips

        """
        self.input_loc = 'catalog_tests'
        self.curdir = os.getcwd()
        truth_path = [self.input_repo, self.tree, self.input_loc, *self.ref_loc]

        if not isinstance(input_filenames, list):
            input_filenames = [input_filenames]

        # Use this to collect all failures BEFORE throwing AssertionError
        failures=False
        try:
            # Make local copies of input files
            local_files = []
            for infile in input_filenames:
                downloaded_files = self.get_input_file(infile, docopy=True)
                local_files.extend(downloaded_files)

            # generate reference catalog
            refcat = amutils.create_astrometric_catalog(local_files, catalog='GAIADR2')

            # Generate source catalogs for each input image
            source_catalogs = generate_source_catalogs(local_files)

            # Convert input images to tweakwcs-compatible NDData objects and
            # attach source catalogs to them.
            imglist = []
            for group_id,image in enumerate(local_files):
                imglist.extend(amutils.build_nddata(image, group_id,
                                                    source_catalogs[image]['catalog_table']))

            # Specify matching algorithm to use
            match = tweakwcs.TPMatch(searchrad=250, separation=0.1,
                                     tolerance=5, use2dhist=True)

            # Align images and correct WCS
            tweakwcs.tweak_image_wcs(imglist, refcat, match=match)
            for chip in imglist:
                status = chip.meta['tweakwcs_info']['status']
                if status.startswith('FAIL'):
                    failures = True
                    print("STATUS for {}: {}".format(chip.meta['filename'], status))
                    break
        except Exception:
            failures = True
            print("ALIGNMENT EXCEPTION:  Failed to align {}".format(infile))

        if not failures:
            for chip in imglist:
                tweak_info = chip.meta.get('tweakwcs_info', None)
                chip_id = chip.meta.get('chip_id',1)

                # determine 30mas limit in pixels
                xylimit = 30
                # Perform comparisons
                nmatches = tweak_info['nmatches']
                xrms,yrms = tweak_info['rms']
                xrms *= chip.wcs.pscale*1000
                yrms *= chip.wcs.pscale*1000
                if any([nmatches==0, xrms>xylimit, yrms>xylimit]):
                    failures = True
                    msg1 = "Observation {}[{}] failed alignment with "
                    msg2 = "    RMS=({:.4f},{:.4f})mas [limit:{:.4f}mas] and NMATCHES={}"
                    print(msg1.format(infile, chip_id))
                    print(msg2.format(xrms, yrms, xylimit, nmatches))

        assert(not failures)
示例#3
0
def perform_align(input_list,
                  archive=False,
                  clobber=False,
                  update_hdr_wcs=False):
    """Main calling function.

    Parameters
    ----------
    input_list : list
        List of one or more IPPSSOOTs (rootnames) to align.

    archive : Boolean
        Retain copies of the downloaded files in the astroquery created sub-directories?

    clobber : Boolean
        Download and overwrite existing local copies of input files?

    update_hdr_wcs : Boolean
        Write newly computed WCS information to image image headers?

    Returns
    -------
    int value 0 if successful, int value 1 if unsuccessful

    """

    # Define astrometric catalog list in priority order
    catalogList = ['GAIADR2', 'GSC241']
    numCatalogs = len(catalogList)

    # 0: print git info
    print(
        "-------------------- STEP 0: Display Git revision info  --------------------"
    )
    full_path = os.path.dirname(__file__) + "/utils"
    repo_path = None
    if "hlapipeline/hlapipeline" in full_path:
        repo_path = full_path.split(
            "hlapipeline/hlapipeline")[0] + "hlapipeline"
    elif "hlapipeline" in full_path:
        repo_path = full_path.split("hlapipeline")[0] + "hlapipeline"
    else:
        pass
    if not os.path.exists(repo_path):
        repo_path = None  # protect against non-existent paths
    if repo_path:
        get_git_rev_info.print_rev_id(
            repo_path)  # Display git repository information
    else:
        print(
            "WARNING: Unable to display Git repository revision information.")

    # 1: Interpret input data and optional parameters
    print("-------------------- STEP 1: Get data --------------------")
    imglist = check_and_get_data(input_list, archive=archive, clobber=clobber)
    print("\nSUCCESS")

    # 2: Apply filter to input observations to insure that they meet minimum criteria for being able to be aligned
    print("-------------------- STEP 2: Filter data --------------------")
    filteredTable = filter.analyze_data(imglist)

    # Check the table to determine if there is any viable data to be aligned.  The
    # 'doProcess' column (bool) indicates the image/file should or should not be used
    # for alignment purposes.
    if filteredTable['doProcess'].sum() == 0:
        print("No viable images in filtered table - no processing done.\n")
        return (1)

    # Get the list of all "good" files to use for the alignment
    processList = filteredTable['imageName'][np.where(
        filteredTable['doProcess'])]
    processList = list(
        processList
    )  #Convert processList from numpy list to regular python list
    print("\nSUCCESS")

    # 3: Build WCS for full set of input observations
    print("-------------------- STEP 3: Build WCS --------------------")
    refwcs = amutils.build_reference_wcs(processList)
    print("\nSUCCESS")

    # 4: Retrieve list of astrometric sources from database
    # While loop to accommodate using multiple catalogs
    doneFitting = False
    catalogIndex = 0
    extracted_sources = None
    while not doneFitting:
        skip_all_other_steps = False
        retry_fit = False
        print(
            "-------------------- STEP 4: Detect astrometric sources --------------------"
        )
        print("Astrometric Catalog: ", catalogList[catalogIndex])
        reference_catalog = generate_astrometric_catalog(
            processList, catalog=catalogList[catalogIndex])
        # The table must have at least MIN_CATALOG_THRESHOLD entries to be useful
        if len(reference_catalog) >= MIN_CATALOG_THRESHOLD:
            print("\nSUCCESS")
        else:
            if catalogIndex < numCatalogs - 1:
                print("Not enough sources found in catalog " +
                      catalogList[catalogIndex])
                print("Try again with the next catalog")
                catalogIndex += 1
                retry_fit = True
                skip_all_other_steps = True
            else:
                print(
                    "Not enough sources found in any catalog - no processing done."
                )
                return (1)
        if not skip_all_other_steps:
            # 5: Extract catalog of observable sources from each input image
            print(
                "-------------------- STEP 5: Source finding --------------------"
            )
            if not extracted_sources:
                extracted_sources = generate_source_catalogs(processList)
                for imgname in extracted_sources.keys():
                    table = extracted_sources[imgname]["catalog_table"]
                    # The catalog of observable sources must have at least MIN_OBSERVABLE_THRESHOLD entries to be useful
                    total_num_sources = 0
                    for chipnum in table.keys():
                        total_num_sources += len(table[chipnum])
                    if total_num_sources < MIN_OBSERVABLE_THRESHOLD:
                        print(
                            "Not enough sources ({}) found in image {}".format(
                                total_num_sources, imgname))
                        return (1)
            # Convert input images to tweakwcs-compatible NDData objects and
            # attach source catalogs to them.
            imglist = []
            for group_id, image in enumerate(processList):
                imglist.extend(
                    amutils.build_nddata(
                        image, group_id,
                        extracted_sources[image]['catalog_table']))
            print("\nSUCCESS")

            # 6: Cross-match source catalog with astrometric reference source catalog, Perform fit between source catalog and reference catalog
            print(
                "-------------------- STEP 6: Cross matching and fitting --------------------"
            )
            # Specify matching algorithm to use
            match = tweakwcs.TPMatch(searchrad=250,
                                     separation=0.1,
                                     tolerance=100,
                                     use2dhist=False)
            # Align images and correct WCS
            tweakwcs.tweak_image_wcs(imglist, reference_catalog, match=match)
            # Interpret RMS values from tweakwcs
            interpret_fit_rms(imglist, reference_catalog)

            tweakwcs_info_keys = OrderedDict(
                imglist[0].meta['tweakwcs_info']).keys()
            imgctr = 0
            for item in imglist:
                retry_fit = False
                #Handle fitting failures (no matches found)
                if item.meta['tweakwcs_info']['status'].startswith(
                        "FAILED") == True:
                    if catalogIndex < numCatalogs - 1:
                        print(
                            "No cross matches found between astrometric catalog and sources found in images"
                        )
                        print("Try again with the next catalog")
                        catalogIndex += 1
                        retry_fit = True
                        break
                    else:
                        print(
                            "No cross matches found in any catalog - no processing done."
                        )
                        return (1)
                max_rms_val = item.meta['tweakwcs_info']['TOTAL_RMS']
                num_xmatches = item.meta['tweakwcs_info']['nmatches']
                # print fit params to screen
                print(
                    "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FIT PARAMETERS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
                )
                if item.meta['chip'] == 1:
                    image_name = processList[imgctr]
                    imgctr += 1
                print("image: {}".format(image_name))
                print("chip: {}".format(item.meta['chip']))
                print("group_id: {}".format(item.meta['group_id']))
                for tweakwcs_info_key in tweakwcs_info_keys:
                    if not tweakwcs_info_key.startswith("matched"):
                        print("{} : {}".format(
                            tweakwcs_info_key,
                            item.meta['tweakwcs_info'][tweakwcs_info_key]))
                # print("Radial shift: {}".format(math.sqrt(item.meta['tweakwcs_info']['shift'][0]**2+item.meta['tweakwcs_info']['shift'][1]**2)))
                print(
                    "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
                )

                if num_xmatches < MIN_CROSS_MATCHES:
                    if catalogIndex < numCatalogs - 1:
                        print(
                            "Not enough cross matches found between astrometric catalog and sources found in images"
                        )
                        print("Try again with the next catalog")
                        catalogIndex += 1
                        retry_fit = True
                        break
                    else:
                        print(
                            "Not enough cross matches found in any catalog - no processing done."
                        )
                        return (1)
                elif max_rms_val > MAX_FIT_RMS:
                    if catalogIndex < numCatalogs - 1:
                        print(
                            "Fit RMS value = {}mas greater than the maximum threshold value {}."
                            .format(
                                item.meta['tweakwcs_info']['FIT_RMS'].value,
                                MAX_FIT_RMS))
                        print("Try again with the next catalog")
                        catalogIndex += 1
                        retry_fit = True
                        break
                    else:
                        print(
                            "Fit RMS values too large using any catalog - no processing done."
                        )
                        return (1)
                else:
                    print("Fit calculations successful.")
        if not retry_fit:
            print("\nSUCCESS")

            # 7: Write new fit solution to input image headers
            print(
                "-------------------- STEP 7: Update image headers with new WCS information --------------------"
            )
            if update_hdr_wcs:
                update_image_wcs_info(imglist, processList)
                print("\nSUCCESS")
            else:
                print("\n STEP SKIPPED")
            return (0)