Exemple #1
0
def create_RED45_mosaic(obsid, overwrite=False):
    gp_root = io.get_ground_projection_root()

    logger.info('Processing the EDR data associated with ' + obsid)

    mos_path = gp_root / obsid / f'{obsid}_mosaic_RED45.cub'

    # bail out if exists:
    if mos_path.exists() and not overwrite:
        print(f'{mos_path} already exists and I am not allowed to overwrite.')
        return obsid, True

    products = get_RED45_mosaic_inputs(obsid, gp_root)

    for prod in products:
        prod.download()
        nocal_hi(prod)

    norm_paths = []
    for channel_products in [products[:2], products[2:]]:
        norm_paths.append(stitch_cubenorm(*channel_products))

    # handmos part
    norm4, norm5 = norm_paths
    im0 = CubeFile.open(str(norm4))  # use CubeFile to get lines and samples
    # get binning mode from label
    bin_ = int(
        getkey(from_=str(norm4),
               objname="isiscube",
               grpname="instrument",
               keyword="summing"))

    # because there is a gap btw RED4 & 5, nsamples need to first make space
    # for 2 cubs then cut some overlap pixels
    try:
        handmos(from_=str(norm4),
                mosaic=str(mos_path),
                nbands=1,
                outline=1,
                outband=1,
                create='Y',
                outsample=1,
                nsamples=im0.samples * 2 - 48 // bin_,
                nlines=im0.lines)
    except ProcessError as e:
        print("STDOUT:", e.stdout)
        print("STDERR:", e.stderr)

    im0 = CubeFile.open(str(norm5))  # use CubeFile to get lines and samples

    # deal with the overlap gap between RED4 & 5:
    handmos(from_=str(norm5),
            mosaic=str(mos_path),
            outline=1,
            outband=1,
            create='N',
            outsample=im0.samples - 48 // bin_ + 1)
    for norm in [norm4, norm5]:
        norm.unlink()
    return obsid, True
def getPDSid(infile):
    """
    Use ISIS to get the PDS Product ID of a cube.

    Using ISIS `getkey` is preferred over extracting the Product ID
    using the PVL library because of an edge case where PVL will
    erroneously convert Product IDs from string to floating point.

    Parameters
    ----------
    infile : str
             A string file path from which the Product ID will be extracted.


    Returns
    -------
    prod_id : str
        The PDS Product ID.
    """
    for key in ['product_id', 'productid']:
        try:
            prod_id = isis.getkey(from_=infile, keyword=key, recursive="TRUE")
            break
        except ProcessError as e:
            prod_id = None

    if not prod_id:
        return None

    # in later versions of ISIS, key values are returned as bytes
    if isinstance(prod_id, bytes):
        prod_id = prod_id.decode()
    prod_id = prod_id.replace('\n', '')
    return prod_id
Exemple #3
0
    def check_label(self):
        """ Check label for target and fix if necessary.

        Forcing the target name to Saturn here, because some observations of
        the rings have moons as a target, but then the standard map projection
        onto the Saturn ring plane fails.

        See also
        --------
        https://isis.astrogeology.usgs.gov/IsisSupport/index.php/topic,3922.0.html
        """
        if not self.is_ring_data:
            return
        targetname = getkey(
            from_=self.pm.raw_cub, grp="instrument", keyword="targetname"
        )

        if targetname.lower() != "saturn":
            editlab(
                from_=self.pm.raw_cub,
                options="modkey",
                keyword="TargetName",
                value="Saturn",
                grpname="Instrument",
            )
Exemple #4
0
def is_lossy(label):
    """Check Label file for the compression type. """
    val = getkey(from_=label, keyword='INST_CMPRS_TYPE').decode().strip()
    if val == 'LOSSY':
        return True
    else:
        return False
Exemple #5
0
def is_lossy(label):
    """Check Label file for the compression type. """
    val = getkey(from_=label, keyword='INST_CMPRS_TYPE').decode().strip()
    if val == 'LOSSY':
        return True
    else:
        return False
Exemple #6
0
def download_LOLA_for_NAC_pair(left_nac, right_nac=None, nac_dir='/data/nac'):
    """
    Function that downloads Lunar Orbital Laser Altimeter (LOLA) Reduced Data Records (RDR) for a given pair of LRO NAC
    paths. If no right_nac is given, will retrieve LOLA data for bounds of left_nac only.

    For a pair, the download will be saved to a file [nac_dir]/[left pair id]xx[right pair id]_lola.csv

    :param left_nac: Path to a map-projected NAC file in ISIS .cub format
    :param right_nac: Path to a map-projected NAC file in ISIS .cub format
    :return: Full path of downloaded LOLA EDR .csv
    """
    from pysis.isis import getkey
    from pysis.exceptions import ProcessError
    left_file_path = path.join(nac_dir, left_nac)
    try:
        left_bounds = (
            getkey(from_=left_file_path, grpname='Mapping', keyword='MinimumLongitude').strip(),
            getkey(from_=left_file_path, grpname='Mapping', keyword='MinimumLatitude').strip(),
            getkey(from_=left_file_path, grpname='Mapping', keyword='MaximumLongitude').strip(),
            getkey(from_=left_file_path, grpname='Mapping', keyword='MaximumLatitude').strip()
        )
        if right_nac:
            right_file_path = path.join(nac_dir, right_nac)
            right_bounds = (
                getkey(from_=right_file_path, grpname='Mapping', keyword='MinimumLongitude').strip(),
                getkey(from_=right_file_path, grpname='Mapping', keyword='MinimumLatitude').strip(),
                getkey(from_=right_file_path, grpname='Mapping', keyword='MaximumLongitude').strip(),
                getkey(from_=right_file_path, grpname='Mapping', keyword='MaximumLatitude').strip()
            )
            lola_filename = path.join(nac_dir, f'{left_nac.split(".")[0]}xx{right_nac.split(".")[0]}_lola.csv')
        else:
            right_bounds = [None] * 4
            lola_filename = path.join(nac_dir, f'{left_nac.split(".")[0]}_lola.csv')
        minlon, minlat = [
            right_bound if float(right_bound) < float(left_bound)
            else left_bound
            for right_bound, left_bound
            in zip(right_bounds[0:2], left_bounds[0:2])
        ]
    except ProcessError as e:
        print("STDOUT:", e.stdout)
        print("STDERR:", e.stderr)

    maxlon, maxlat = [
        right_bound if float(right_bound) > float(left_bound)
        else left_bound
        for right_bound, left_bound
        in zip(right_bounds[2:4], left_bounds[2:4])
    ]
    minlon, minlat, maxlon, maxlat = [float(val) for val in (minlon, minlat, maxlon, maxlat)]

    download_LOLA_by_bounds(minlon=minlon, minlat=minlat, maxlon=maxlon, maxlat=maxlat, lola_filename=lola_filename)
Exemple #7
0
def create_RED45_mosaic(obsid, overwrite=False):
    gp_root = io.get_ground_projection_root()

    logger.info('Processing the EDR data associated with ' + obsid)

    mos_path = gp_root / obsid / f'{obsid}_mosaic_RED45.cub'

    # bail out if exists:
    if mos_path.exists() and not overwrite:
        print(f'{mos_path} already exists and I am not allowed to overwrite.')
        return obsid, True

    products = get_RED45_mosaic_inputs(obsid, gp_root)

    for prod in products:
        prod.download()
        nocal_hi(prod)

    norm_paths = []
    for channel_products in [products[:2], products[2:]]:
        norm_paths.append(stitch_cubenorm(*channel_products))

    # handmos part
    norm4, norm5 = norm_paths
    im0 = CubeFile.open(str(norm4))  # use CubeFile to get lines and samples
    # get binning mode from label
    bin_ = int(getkey(from_=str(norm4), objname="isiscube", grpname="instrument",
                      keyword="summing"))

    # because there is a gap btw RED4 & 5, nsamples need to first make space
    # for 2 cubs then cut some overlap pixels
    try:
        handmos(from_=str(norm4), mosaic=str(mos_path), nbands=1, outline=1, outband=1,
                create='Y', outsample=1, nsamples=im0.samples * 2 - 48 // bin_,
                nlines=im0.lines)
    except ProcessError as e:
        print("STDOUT:", e.stdout)
        print("STDERR:", e.stderr)

    im0 = CubeFile.open(str(norm5))  # use CubeFile to get lines and samples

    # deal with the overlap gap between RED4 & 5:
    handmos(from_=str(norm5), mosaic=str(mos_path), outline=1, outband=1, create='N',
            outsample=im0.samples - 48 // bin_ + 1)
    for norm in [norm4, norm5]:
        norm.unlink()
    return obsid, True
Exemple #8
0
def get_single_band_cube(cube,out_cube,band_list,keyname):
    """
    Convenience function to extract a single band from an ISIS cube based on a prioritized list of band numbers,
    and the name of a keyword to search for in the BandBin group of the cube.
    This is necessary for generating browse/thumbnail images from multiband images where certain bands are preferred
    over others for use in the output, but there is no way of knowing whether the preferred band is present without
    inspecting the ingested ISIS cube.

    Parameters
    ----------
    cube : str
             A string file path to the input cube.

    out_cube : str
             A string file path to the desired output cube.

    band_list : list
             A list of ints representing band numbers to search for in cube, in decreasing order of priority

    keyname : str
             The name of the keyword to look for in the BandBin group of the input cube.

    Returns
    -------
    isis.cubeatt() : function
        Calls the ISIS function, cubeatt, in order to write out a single band cube


    """
    bands_in_cube = isis.getkey(from_=cube, objname="IsisCube", grpname="BandBin", keyword=keyname)
    if isinstance(bands_in_cube, bytes):
        bands_in_cube = bands_in_cube.decode()
    bands_in_cube = bands_in_cube.replace('\n', '').replace(' ', '').split(',')
    bands_in_cube = [int(x) for x in bands_in_cube]
    
    for band in band_list:
        if band in bands_in_cube:
            isis.cubeatt(from_=cube + '+' + str(band), to=out_cube)
            break
        else:
            continue

    return
Exemple #9
0
def main( argv = None ):

    inputlbl = None
    outputConfig = None
    run = None
    template = None

    if argv is None:
        argv = sys.argv

    argv = gdal.GeneralCmdLineProcessor( argv )
    if argv is None:
        return 1

    nArgc = len(argv)

#/* -------------------------------------------------------------------- */
#/*      Parse arguments.                                                */
#/* -------------------------------------------------------------------- */
    i = 1
    while i < nArgc:

        if EQUAL(argv[i], '-run'):
            run = True
        elif EQUAL(argv[i], '-template'):
            i = i + 1
            template = argv[i]
        elif inputlbl is None:
            inputlbl = argv[i]
        elif outputConfig is None:
            outputConfig = argv[i]
        else:
            return Usage(argv[0])
        i = i + 1

    if inputlbl is None:
        return Usage(argv[0])
    if outputConfig is None:
        return Usage(argv[0])
    if template is None:
        template = 'pds4_template.xml'

    #open output config file
    fileConfig = open(outputConfig, 'w')
    print('writing {}'.format(outputConfig))

    #Write first comment line
    theLine = '#{0} {1} {2}\n'.format(sys.argv[0], sys.argv[1], sys.argv[2])
    fileConfig.write(theLine)

    #Next lines are not available in ISIS3 label
    theLine = '-co VAR_TARGET_TYPE=Satellite\n'
    fileConfig.write(theLine)

    theLine = '-co VAR_INVESTIGATION_AREA_LID_REFERENCE="urn:nasa:pds:context:instrument_host:spacecraft.lro"\n'
    fileConfig.write(theLine)

    try:
        target = getkey(from_=inputlbl, keyword='TargetName', grp='Mapping')
        theLine = '-co VAR_TARGET={}'.format(target)
        fileConfig.write(theLine)
    except KeyError:
        print('No Target in ISIS3 Label')

    try:
        mission = getkey(from_=inputlbl, keyword='InstrumentHostName', grp='Archive')
        theLine = '-co VAR_INVESTIGATION_AREA_NAME="{}"\n'.format(mission.rstrip())
        fileConfig.write(theLine)
    except KeyError:
        print('No InstrumentHostName in ISIS3 Label')

    try:
        dataSetID = getkey(from_=inputlbl, keyword='DataSetId', grp='Archive')
        theLine = '-co VAR_LOGICAL_IDENTIFIER={}'.format(dataSetID)
        fileConfig.write(theLine)
    except KeyError:
        print('No DataSetId in ISIS3 Label')

    try:
        observeID = getkey(from_=inputlbl, keyword='InstrumentId', grp='Archive')
        theLine = '-co VAR_OBSERVING_SYSTEM_NAME={}'.format(observeID)
        fileConfig.write(theLine)
    except KeyError:
        print('No InstrumentId in ISIS3 Label')

    try:
        fileName = getkey(from_=inputlbl, keyword='ProductId', grp='Archive')
        theLine = '-co VAR_TITLE={}'.format(fileName)
        fileConfig.write(theLine)
    except KeyError:
        print('No ProductId in ISIS3 Label')

    fileConfig.close()

    #write out helper line for gdal - can run from here too
    outPDS4 = inputlbl.replace('.cub','_pds4.xml')

    theCmd='gdal_translate -of PDS4 -co IMAGE_FORMAT=GEOTIFF -co TEMPLATE={0} --optfile {1} {2} {3}'.format(template, outputConfig, inputlbl, outPDS4)

    if run is None:
        print('\nRecommended gdal run:')
        print('{}\n'.format(theCmd))
    else: #run gdal
        os.system(theCmd)
Exemple #10
0
def calibrate_ciss(img_name, ringdata=True, map_project=False):
    """
    Calibrate raw Cassini ISS images using ISIS.

    ISIS is using an official released version the calibration routine `cisscal`
    that is being developed under IDL, but has been converted to C++ for ISIS.
    I am using the pipeline as described here:
    https://isis.astrogeology.usgs.gov/IsisWorkshop/index.php/Working_with_Cassini_ISS_Data
    It is customary to indicate the pipeline of ISIS apps that a file went through
    with a chain of extensions, e.g. '.cal.dst.map.cub', indicating calibration, destriping,
    and map projection.

    Parameters
    ----------
    img_name : pathlib.Path, str
        Absolute path to image

    Returns
    -------
    str : absolute path to map-projected ISIS cube.
    """
    # Check if img_name is maybe a PathManager object with a `raw_label` attribute:
    try:
        img_name = str(img_name.raw_label)
    except AttributeError:
        # doesn't seem to be the case, so I assume it's just a path
        img_name = str(img_name)
    (cub_name,
     cal_name,
     dst_name,
     map_name) = file_variations(img_name,
                                 ['.cub',
                                  '.cal.cub',
                                  '.cal.dst.cub',
                                  '.cal.dst.map.cub'])
    ciss2isis(from_=img_name, to=cub_name)
    logging.info("Import to ISIS done.")
    targetname = getkey(from_=cub_name,
                        grp='instrument',
                        keyword='targetname')
    # forcing the target name to Saturn here, because some observations of
    # the rings have moons as a target, but then the standard map projection
    # onto the Saturn ring plane fails.
    # see also
    # https://isis.astrogeology.usgs.gov/IsisSupport/index.php/topic,3922.0.html
    if targetname.lower() != 'saturn':
        editlab(from_=cub_name, options='modkey',
                keyword='TargetName', value='Saturn',
                grpname='Instrument')

    # perform either normal spiceinit or one for ringdata
    if ringdata is True:
        spiceinit(from_=cub_name, cksmithed='yes', spksmithed='yes',
                  shape='ringplane')
    else:
        spiceinit(from_=cub_name, cksmithed='yes', spksmithed='yes')
    logging.info("spiceinit done.")
    cisscal(from_=cub_name, to=cal_name, units='I/F')
    logging.info('cisscal done.')
    dstripe(from_=cal_name, to=dst_name, mode='horizontal')
    logging.info('Destriping done.')
    if map_project:
        ringscam2map(from_=dst_name, to=map_name, defaultrange='Camera',
                     map=ISISDATA / 'base/templates/maps/ringcylindrical.map')
        isis2std(from_=map_name, to=map_name[:-3]+'tif', format='tiff')
        logging.info('Map projecting done. Function finished.')
    else:
        isis2std(from_=dst_name, to=dst_name[:-3]+'tif', format='tiff',
                 minpercent=0, maxpercent=100)
        logging.warning('Map projection was skipped, set map_project to True if wanted.')
    return map_name