Esempio n. 1
0
def make_unfiltered(in_path,
                    nrm_path,
                    temp_token,
                    color_code,
                    color_band,
                    keep=False):
    tt = f"{temp_token}_{color_code}"
    in_p = Path(in_path)
    unfiltered_p = in_p.with_name(
        in_p.name.replace("COLOR", "UNFILTERED_COLOR"))
    shutil.copyfile(in_p, unfiltered_p)
    # run ISIS algebra program to create unfiltered
    # (normalized-IR/RED)*RED files
    alg_unfiltered_path = in_p.with_suffix(f".{tt}.algebra.cub")
    isis.algebra(
        nrm_path,
        from2="{}+2".format(in_p),
        to=alg_unfiltered_path,
        operator="MULTIPLY",
    )
    # Update the output file with the non-filtered normalized IR and BG bands
    isis.handmos(
        alg_unfiltered_path,
        mosaic=unfiltered_p,
        outsample=1,
        outline=1,
        matchbandbin=False,
        outband=color_band,
    )
    if not keep:
        alg_unfiltered_path.unlink()
    return unfiltered_p
Esempio n. 2
0
def make_LR_mosaic(left_path, right_path, left_samps, mosaic_path, lines,
                   samps):
    isis.handmos(
        left_path,
        mosaic=mosaic_path,
        create="YES",
        nlines=lines,
        nsamp=samps,
        nbands=1,
        outsamp=1,
        outline=1,
        outband=1,
    )
    isis.handmos(
        right_path,
        mosaic=mosaic_path,
        outsamp=(left_samps + 1),
        outline=1,
        outband=1,
    )
    return
Esempio n. 3
0
def subtract_over_thresh(
    in_path: Path, out_path: Path, thresh: int, delta: int, keep=False
):
    """This is a convenience function that runs ISIS programs to add or
    subtract a value to DN values for pixels that are above or below
    a threshold.

    For all pixels in the *in_path* ISIS cube, if *delta* is positive,
    then pixels with a value greater than *thresh* will have *delta*
    subtracted from them.  If *delta* is negative, then all pixels
    less than *thresh* will have *delta* added to them.
    """

    # Originally, I wanted to just do this simply with fx:
    # eqn = "\(f1 + ((f1{glt}={thresh}) * {(-1 * delta)}))"
    # However, fx writes out floating point pixel values, and we really
    # need to keep DNs as ints as long as possible.  Sigh.

    shutil.copyfile(in_path, out_path)

    mask_p = in_path.with_suffix(".threshmask.cub")
    mask_args = {"from": in_path, "to": mask_p}
    if delta > 0:
        mask_args["min"] = thresh
    else:
        mask_args["max"] = thresh
    isis.mask(**mask_args)

    delta_p = in_path.with_suffix(".delta.cub")
    isis.algebra(
        mask_p, from2=in_path, to=delta_p, op="add", a=0, c=(-1 * delta)
    )

    isis.handmos(delta_p, mosaic=out_path)

    if not keep:
        mask_p.unlink()
        delta_p.unlink()

    return
Esempio n. 4
0
def handmos_side(cubes, base_cube, out_p: os.PathLike, left=True):
    """Runs handmos to add cubes which are to one side or the other
       of the *base_cube*."""
    # handmos left side
    side = 1
    priority = "beneath"
    if left:
        side = -1
        priority = "ontop"
    ssm = 1
    slm = 1
    for c in cubes[(cubes.index(base_cube) + side)::side]:
        slm -= side * round(c.line_offset)
        ssm -= side * round(c.samp_offset)
        isis.handmos(
            c.next_path,
            mosaic=out_p,
            priority=priority,
            outline=slm,
            outsample=ssm,
            outband=1,
        )
    return
Esempio n. 5
0
def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        "-o", "--output", required=False, default=".mdr.iof.cub"
    )
    parser.add_argument("-e", "--edr", required=True)
    parser.add_argument(
        "-c",
        "--conf",
        required=False,
        type=argparse.FileType('r'),
        default=pkg_resources.resource_stream(
            __name__,
            'data/hical.pipelines.conf'
        ),
    )
    parser.add_argument("mdr", metavar="MDR_file")
    parser.add_argument(
        "-l",
        "--log",
        required=False,
        default="WARNING",
        help="The log level to show for this program, can "
        "be a named log level or a numerical level.",
    )
    parser.add_argument(
        "-k",
        "--keep",
        required=False,
        default=False,
        action="store_true",
        help="Normally, the program will clean up any "
        "intermediary files, but if this option is given, it "
        "won't.",
    )

    args = parser.parse_args()

    util.set_logger(args.verbose, args.logfile, args.log)

    edr_path = Path(args.edr)
    mdr_path = Path(args.mdr)

    to_del = isis.PathSet()

    h2i_path = to_del.add(edr_path.with_suffix(".hi2isis.cub"))

    out_path = util.path_w_suffix(args.output, edr_path)

    # The first thing Alan's program did was to crop the image down to only the
    # 'imaging' parts.  We're not doing that so the resultant file has a
    # geometry similar to what comes out of ISIS hical.

    # Convert the EDR to a cube file
    isis.hi2isis(edr_path, to=h2i_path)

    # Convert Alan's MDR to a cube file
    mdr_cub_path = to_del.add(mdr_path.with_suffix(".alan.cub"))
    logger.info(f"Running gdal_translate {mdr_path} -of ISIS3 {mdr_cub_path}")
    gdal.Translate(str(mdr_cub_path), str(mdr_path), format="ISIS3")

    h2i_s = int(isis.getkey_k(h2i_path, "Dimensions", "Samples"))
    h2i_l = int(isis.getkey_k(h2i_path, "Dimensions", "Lines"))
    mdr_s = int(isis.getkey_k(mdr_cub_path, "Dimensions", "Samples"))
    mdr_l = int(isis.getkey_k(mdr_cub_path, "Dimensions", "Lines"))

    if h2i_s != mdr_s:
        label = pvl.load(str(h2i_path))
        hirise_cal_info = get_one(
            label, "Table", "HiRISE Calibration Ancillary"
        )

        buffer_pixels = get_one(hirise_cal_info, "Field", "BufferPixels")[
            "Size"
        ]
        dark_pixels = get_one(hirise_cal_info, "Field", "DarkPixels")["Size"]
        rev_mask_tdi_lines = hirise_cal_info["Records"]

        if h2i_s + buffer_pixels + dark_pixels == mdr_s:
            logger.info(
                f"The file {mdr_cub_path} has "
                f"{buffer_pixels + dark_pixels} more sample pixels "
                f"than {h2i_path}, assuming those are dark and "
                "buffer pixels and will crop accordingly."
            )
            if h2i_l + rev_mask_tdi_lines != mdr_l:
                logger.critical(
                    'Even assuming this is a "full" channel '
                    "image, this has the wrong number of lines. "
                    f"{mdr_cub_path} should have "
                    f"{h2i_l + rev_mask_tdi_lines}, but "
                    f"has {mdr_l} lines. Exiting"
                )
                sys.exit()
            else:
                crop_path = to_del.add(mdr_cub_path.with_suffix(".crop.cub"))
                # We want to start with the next pixel (+1) after the cal
                # pixels.
                isis.crop(
                    mdr_cub_path,
                    to=crop_path,
                    sample=buffer_pixels + 1,
                    nsamples=h2i_s,
                    line=rev_mask_tdi_lines + 1,
                )
                mdr_cub_path = crop_path
                mdr_l = int(isis.getkey_k(mdr_cub_path, "Dimensions", "Lines"))

        else:
            logger.critical(
                f"The number of samples in {h2i_path} ({h2i_s}) "
                f"and {mdr_cub_path} ({mdr_s}) are different. "
                "Exiting."
            )
            sys.exit()

    if h2i_l != mdr_l:
        logger.critical(
            f"The number of lines in {h2i_path} ({h2i_l}) "
            f"and {mdr_cub_path} ({mdr_l}) are different. "
            "Exiting."
        )
        sys.exit()

    # Convert the EDR to the right bit type for post-HiCal Pipeline:
    h2i_16b_p = to_del.add(h2i_path.with_suffix(".16bit.cub"))
    isis.bit2bit(
        h2i_path,
        to=h2i_16b_p,
        bit="16bit",
        clip="minmax",
        minval=0,
        maxval=1.5,
    )
    shutil.copyfile(h2i_16b_p, out_path)

    # If it is a channel 1 file, Alan mirrored it so that he could process
    # the two channels in an identical way (which we also took advantage
    # of above if the buffer and dark pixels were included), so we need to
    # mirror it back.
    cid = hirise.get_ChannelID_fromfile(h2i_16b_p)
    if cid.channel == "1":
        mirror_path = to_del.add(mdr_cub_path.with_suffix(".mirror.cub"))
        isis.mirror(mdr_cub_path, to=mirror_path)
        mdr_cub_path = mirror_path

    # Is the MDR in DN or I/F?
    maximum_pxl = float(
        pvl.loads(isis.stats(mdr_cub_path).stdout)["Results"]["Maximum"]
    )
    if maximum_pxl < 1.5:
        logger.info("MDR is already in I/F units.")
        mdr_16b_p = to_del.add(mdr_cub_path.with_suffix(".16bit.cub"))
        isis.bit2bit(
            mdr_cub_path,
            to=mdr_16b_p,
            bit="16bit",
            clip="minmax",
            minval=0,
            maxval=1.5,
        )
        isis.handmos(mdr_16b_p, mosaic=out_path)
    else:
        logger.info("MDR is in DN units and will be converted to I/F.")

        fpa_t = statistics.mean(
            [
                float(
                    isis.getkey_k(
                        h2i_16b_p, "Instrument", "FpaPositiveYTemperature"
                    )
                ),
                float(
                    isis.getkey_k(
                        h2i_16b_p, "Instrument", "FpaNegativeYTemperature"
                    )
                ),
            ]
        )
        print(f"fpa_t {fpa_t}")

        conf = pvl.load(args.conf)

        tdg = t_dep_gain(get_one(conf["Hical"], "Profile", cid.ccdname), fpa_t)
        suncorr = solar_correction()
        sclk = isis.getkey_k(
            h2i_16b_p, "Instrument", "SpacecraftClockStartCount"
        )
        target = isis.getkey_k(h2i_16b_p, "Instrument", "TargetName")
        suncorr = solar_correction(sunDistanceAU(sclk, target))
        sed = float(
            isis.getkey_k(h2i_16b_p, "Instrument", "LineExposureDuration")
        )
        zbin = get_one(conf["Hical"], "Profile", "GainUnitConversion")[
            "GainUnitConversionBinFactor"
        ]

        # The 'ziof' name is from the ISIS HiCal/GainUnitConversion.h, it is a
        # divisor in the calibration equation.
        print(f"zbin {zbin}")
        print(f"tdg {tdg}")
        print(f"sed {sed}")
        print(f"suncorr {suncorr}")
        ziof = zbin * tdg * sed * 1e-6 * suncorr
        eqn = f"\(F1 / {ziof})"  # noqa W605

        mdriof_p = to_del.add(mdr_cub_path.with_suffix(".iof.cub"))
        to_s = "{}+SignedWord+{}:{}".format(mdriof_p, 0, 1.5)
        isis.fx(f1=mdr_cub_path, to=to_s, equ=eqn)

        isis.handmos(mdriof_p, mosaic=out_path)

    if not args.keep:
        to_del.unlink()
Esempio n. 6
0
def HiFurrow_Fix(in_cube: os.PathLike,
                 out_cube: os.PathLike,
                 max_mean: float,
                 keep=False):
    """Perform a normalization of the furrow region of bin 2 or 4
    HiRISE images. The input to this script is a HiRISE stitch
    product containing both channels of a CCD.
    """
    in_cub = Path(in_cube)

    binning = int(isis.getkey_k(in_cub, "Instrument", "Summing"))
    lines = int(isis.getkey_k(in_cub, "Dimensions", "Lines"))
    samps = int(isis.getkey_k(in_cub, "Dimensions", "Samples"))

    if binning != 2 and binning != 4:
        raise ValueError("HiFurrow_Fix only supports correction for "
                         "bin 2 or 4 data.")
    if binning == 2 and samps != 1024:
        raise ValueError(f"HiFurrowFix: improper number of samples: {samps}, "
                         "for a stitch product with bin 2 (should be 1024).")

    # This string will get placed in the filename for all of our
    # temporary files. It will (hopefully) prevent collisions with
    # existing files and also allow for easy clean-up if keep=True
    temp_token = datetime.now().strftime("HFF-%y%m%d%H%M%S")
    to_del = isis.PathSet()

    # For bin2 and bin4 imaging, specify width of furrow based on
    # image average DN range
    range_low = {2: (512, 513), 4: (256, 257)}  # 2 pixel furrow width
    range_mid = {2: (511, 514), 4: (255, 258)}  # 4 pixel furrow width
    range_hgh = {2: (511, 514), 4: (255, 258)}  # 4 pixel furrow width
    range_max = {2: (510, 515), 4: (254, 259)}  # 6 pixel furrow width

    # Original code had low/mid/hgh for bin2 and bin4, but they
    # were hard-coded to be identical.
    dn_range_low = 9000
    dn_range_mid = 10000
    dn_range_hgh = 12000

    if max_mean > dn_range_hgh:
        dn_range = range_max[binning]
    elif max_mean > dn_range_mid:
        dn_range = range_hgh[binning]
    elif max_mean > dn_range_low:
        dn_range = range_mid[binning]
    else:
        dn_range = range_low[binning]

    lpf_samp = int((dn_range[1] - dn_range[0] + 1) / 2) * 4 + 1
    lpf_line = int(lpf_samp / 2) * 20 + 1

    # Create a mask file
    # DN=1 for non-furrow area
    # DN=0 for furrow area
    eqn = rf"\(1*(sample<{dn_range[0]})+ 1*(sample>{dn_range[1]}) + 0)"
    fx_cub = to_del.add(in_cub.with_suffix(f".{temp_token}.fx.cub"))
    isis.fx(to=fx_cub,
            mode="OUTPUTONLY",
            lines=lines,
            samples=samps,
            equation=eqn)

    # Create a file where the furrow area is set to null
    mask1_cub = to_del.add(in_cub.with_suffix(f".{temp_token}.mask1.cub"))
    isis.mask(
        in_cub,
        mask=fx_cub,
        to=mask1_cub,
        min_=1,
        max_=1,
        preserve="INSIDE",
        spixels="NULL",
    )

    # Lowpass filter to fill in the null pixel area
    lpf_cub = to_del.add(in_cub.with_suffix(f".{temp_token}.lpf.cub"))
    isis.lowpass(
        mask1_cub,
        to=lpf_cub,
        sample=lpf_samp,
        line=lpf_line,
        null=True,
        hrs=False,
        his=False,
        lis=False,
    )

    # Create a file where non-furrow columns are set to null
    mask2_cub = to_del.add(in_cub.with_suffix(f".{temp_token}.mask2.cub"))
    isis.mask(
        in_cub,
        mask=fx_cub,
        to=mask2_cub,
        min_=0,
        max_=0,
        preserve="INSIDE",
        spixels="NULL",
    )

    # Highpass filter the furrow region
    hpf_cub = to_del.add(in_cub.with_suffix(f".{temp_token}.hpf.cub"))
    isis.highpass(mask2_cub, to=hpf_cub, sample=1, line=lpf_line)

    # Add lowpass and highpass together to achieve desired result
    alg_cub = to_del.add(in_cub.with_suffix(f".{temp_token}.alg.cub"))
    isis.algebra(from_=lpf_cub,
                 from2=hpf_cub,
                 to=alg_cub,
                 operator="ADD",
                 A=1.0,
                 B=1.0)

    # copy the input file to the output file then mosaic the
    # furrow area as needed.
    logger.info(f"Copy {in_cub} to {out_cube}.")
    shutil.copyfile(in_cub, out_cube)
    isis.handmos(
        alg_cub,
        mosaic=out_cube,
        outsample=1,
        outline=1,
        outband=1,
        insample=1,
        inline=1,
        inband=1,
        create="NO",
    )

    if not keep:
        to_del.unlink()

    return
Esempio n. 7
0
def per_band(cubes,
             out_p,
             temp_token,
             color_code,
             furrow_flag,
             unfiltered,
             keep=False) -> float:
    to_del = isis.PathSet()

    # Generate the handmos of both the ratio and the croped ratio files
    if len(cubes) == 2:
        maxlines = max(c.lines for c in cubes)
        maxsamps = sum(c.samps for c in cubes)

        # Generate the mosaic of the ratio image
        mos_p = to_del.add(
            out_p.with_suffix(f".{temp_token}.{color_code}.mos.cub"))
        make_LR_mosaic(
            cubes[0].mask_path[color_code],
            cubes[1].mask_path[color_code],
            cubes[0].samps,
            mos_p,
            maxlines,
            maxsamps,
        )

        # Generate the mosaic of the crop ratio image
        maxlines = max(c.crop_lines for c in cubes)
        crpmos_p = to_del.add(
            out_p.with_suffix(f".{temp_token}.{color_code}.moscrop.cub"))
        make_LR_mosaic(
            cubes[0].crop_path[color_code],
            cubes[1].crop_path[color_code],
            cubes[0].samps,
            crpmos_p,
            maxlines,
            maxsamps,
        )
    else:
        mos_p = cubes[0].mask_path[color_code]
        crpmos_p = cubes[0].crop_path[color_code]

    mosnrm_p = to_del.add(
        out_p.with_suffix(f".{temp_token}.{color_code}.mosnorm.cub"))
    ratio_stddev = cubenorm_stats(crpmos_p, mos_p, mosnrm_p, keep=keep)

    # from the handmos cubes, pull out the individual CCDs with crop
    if len(cubes) == 2:
        samp = 1
        for i, c in enumerate(cubes):
            cubes[i].nrm_path[color_code] = c.path.with_suffix(
                f".{temp_token}.{color_code}.norm.cub")
            isis.crop(
                mosnrm_p,
                to=cubes[i].nrm_path[color_code],
                sample=samp,
                nsamples=c.samps,
            )
            samp += c.samps
    else:
        # If there was only one file then all we need to do is rename files
        cubes[0].nrm_path[color_code] = mosnrm_p

    if unfiltered:
        # Create the unfiltered color cubes, if needed
        for c in cubes:
            make_unfiltered(
                c.path,
                c.nrm_path[color_code],
                temp_token,
                color_code,
                c.band[color_code],
                keep=keep,
            )

    # low pass filter the files
    for c in cubes:
        # If $lpfz=1 then we're only interpolating null pixels caused by
        # noise or furrow removal

        lowpass_args = dict(
            minopt="PERCENT",
            minimum=25,
            low=0.00,
            high=2.0,
            null=True,
            hrs=True,
            lis=True,
            lrs=True,
        )

        # As the comment below states, I *think* that the OP had a copy
        # and paste error here, because even though it kept track of both
        # the IR and BG boxcar dimensions, they were always identical.
        logger.warning("The original Perl calculates the boxcar size for "
                       "both the IR and BG based only on the ratio of the "
                       "IR to the RED.")
        if c.get_boxcar_size(c.ir_bin) == 1:
            lowpass_args["lines"] = 3
            lowpass_args["samples"] = 3
            lowpass_args["filter"] = "OUTSIDE"
        else:
            lowpass_args["lines"] = 1
            lowpass_args["samples"] = 1

        lpf_path = to_del.add(
            c.path.with_suffix(f".{temp_token}.{color_code}.lpf.cub"))
        isis.lowpass(c.nrm_path[color_code], to=lpf_path, **lowpass_args)

        # Perform lpfz filters to interpolate null pixels due to furrows or
        #   bad pixels
        if furrow_flag:
            lpfz_path = c.path.with_suffix(
                f".{temp_token}.{color_code}.lpfz.cub")
            lpfz_triplefilter(lpf_path, lpfz_path, temp_token, keep=keep)
        else:
            lpfz_path = lpf_path

        # run ISIS algebra program to created (normalized-IR/RED)*RED files
        alg_path = to_del.add(
            c.path.with_suffix(f".{temp_token}.{color_code}.algebra.cub"))
        isis.algebra(lpfz_path,
                     from2=f"{c.path}+2",
                     to=alg_path,
                     operator="MULTIPLY")

        # Update the output file with the normalized IR and BG bands
        isis.handmos(
            alg_path,
            mosaic=c.final_path,
            outsample=1,
            outline=1,
            outband=c.band[color_code],
            matchbandbin=False,
        )

    if not keep:
        to_del.unlink()

    return ratio_stddev
Esempio n. 8
0
def match_red(cubes: list, base_cube, flat_path, elargement_ratio=1.0006):
    """Prepare cubs for hijitreg by matching size and binning to center red
    ccds.
    """
    # Where does the 1.0006 value for OPTICAL_ENLARGEMENT_RATIO come from?
    # Not sure.

    red4 = list(filter(lambda x: int(x.ccdnumber) == 4, cubes))[0]
    red5 = list(filter(lambda x: int(x.ccdnumber) == 5, cubes))[0]

    if red4.bin != red5.bin:
        raise ValueError("RED4 and RED5 binning not equal.")

    for c in cubes:
        bin_ratio = c.bin / base_cube.bin

        # Differences in field of view between color and red are corrected
        # for by multiplying bin ratio by pre-determined constant for BG and
        # dividing bin ratio by that constant for IR

        mag = bin_ratio
        if c.ccdname == "BG":
            mag = bin_ratio * elargement_ratio
        elif c.ccdname == "IR":
            mag = bin_ratio / elargement_ratio

        # scale cubes as needed
        if mag > 1:
            isis.enlarge(
                c.path,
                to=c.next_path,
                sscale=mag,
                lscale=bin_ratio,
                interp="BILINEAR",
            )
        elif mag < 1:
            isis.reduce(
                c.path,
                to=c.next_path,
                sscale=1 / mag,
                lscale=bin_ratio,
                mode="SCALE",
            )
        else:
            shutil.copy(c.path, c.next_path)

        if c.ccdname != "RED":
            offset = int(
                (200 * (c.bin - base_cube.bin) + c.tdi - base_cube.tdi)
                / base_cube.bin
            )
            mos_path = c.next_path.with_suffix(".mosaiced.cub")
            isis.handmos(
                c.next_path,
                mosaic=mos_path,
                create="Y",
                nlines=base_cube.lines,
                nsamples=base_cube.samps,
                nbands=1,
                outline=offset,
                outsamp=1,
                outband=1,
            )
            shutil.move(mos_path, c.next_path)

        if bin_ratio != 1:
            isis.editlab(
                c.next_path,
                options="MODKEY",
                grpname="INSTRUMENT",
                KEYWORD="SUMMING",
                value=base_cube.bin,
            )

    # This section creates flat.tabs for RED4-RED5 pair only
    rows = int(red5.lines / 50)
    isis.hijitreg(
        red4.next_path, match=red5.next_path, row=rows, flat=flat_path
    )

    return
Esempio n. 9
0
def HiBeautify(cube_paths: list,
               conf: dict,
               out_irb="_IRB.cub",
               out_rgb="_RGB.cub",
               keep=False):
    logger.info(f"HiBeautify start: {', '.join(map(str, cube_paths))}")

    # GetConfigurationParameters()
    cubes = list(map(hcn.ColorCube, cube_paths))
    cubes.sort()

    irb_out_p = hcn.set_outpath(out_irb, cubes)
    rgb_out_p = hcn.set_outpath(out_rgb, cubes)

    temp_token = datetime.now().strftime("HiBeautify-%y%m%d%H%M%S")
    to_del = isis.PathSet()

    # Create an IRB mosaic from the HiColorNorm halves.

    # If a half is missing, we create a mosaic with the proper width and place
    # the half in it at the proper location.
    # Logic ofr image_midpoint and total_width come from original HiColorInit
    # irbmerged_p = to_del.add(out_p.with_suffix(f'.{temp_token}_IRB.cub'))
    image_midpoint = int((2000 / cubes[0].red_bin) + 1)
    outsample = image_midpoint
    if cubes[0].ccdnumber == "4":
        outsample = 1
    total_width = int(2 * cubes[0].samps - (48 / cubes[0].red_bin))

    isis.handmos(
        cubes[0].path,
        mosaic=irb_out_p,
        outline=1,
        outsample=outsample,
        outband=1,
        create="Y",
        nlines=cubes[0].lines,
        nsamp=total_width,
        nbands=3,
    )

    if len(cubes) == 1:
        logger.info("Warning, missing one half!")
    else:
        logger.info("Using both halves")
        isis.handmos(
            cubes[1].path,
            mosaic=irb_out_p,
            outline=1,
            outsample=image_midpoint,
            outband=1,
        )

    # Nothing is actually done to the pixels here regarding the FrostStats, so
    # I'm just going to skip them here.
    #
    # # Determine if Frost/ICE may be present using FrostStats module.
    # frost = None
    # if args.frost:
    #     frost = True
    #     logging.info('Frost override: disabling auto-detection and using '
    #                  'the frost/ice color stretch')
    # if args.nofrost:
    #     frost = False
    #     logging.info('Frost override: disable auto-detection and not using '
    #                  'the frost/ice color stretch')
    # if frost is None:
    #     pass
    #     # get frost stats

    # Subtract the unaltered RED band from the high pass filtered BG for
    # synthetic blue.
    logger.info("Creating synthetic B, subtracting RED from BG")
    rgbsynthb_p = to_del.add(irb_out_p.with_suffix(f".{temp_token}_B.cub"))
    isis.algebra(
        f"{irb_out_p}+3",
        from2=f"{irb_out_p}+2",
        op="subtract",
        to=rgbsynthb_p,
        A=conf["Beautify"]["Synthetic_A_Coefficient"],
        B=conf["Beautify"]["Synthetic_B_Coefficient"],
    )

    # Adjust the BandBin group
    isis.editlab(rgbsynthb_p,
                 grpname="BandBin",
                 keyword="Name",
                 value="Synthetic Blue")
    isis.editlab(rgbsynthb_p, grpname="BandBin", keyword="Center", value="0")
    isis.editlab(rgbsynthb_p, grpname="BandBin", keyword="Width", value="0")

    # HiBeautify gathers and writes a bunch of statistics to PVL that is
    # important to the HiRISE GDS, but not relevant to just producing pixels
    # so I'm omitting it.
    #
    # # Determine the min and max DN values of each band (RED, IR, BG, B) we're
    # # working with.
    # (upper, lower) = conf['Beautify']['Stretch_Exclude_Lines']
    # if upper == 0 and lower == 0:
    #     synthbcrp_p = rgbsynthb_p
    #     irbmrgcrp_p = irbmerged_p
    # else:
    #     synthbcrp_p = to_del.add(
    #           out_p.with_suffix(f'.{temp_token}_Bx.cub'))
    #     irbmrgcrp_p = to_del.add(
    #           out_p.with_suffix(f'.{temp_token}_IRBx.cub'))
    #
    #     for (f, t) in ((rgbsynthb_p, synthbcrp_p),
    #                    (irbmerged_p, irbmrgcrp_p)):
    #         logging.info(isis.crop(f, to=t, propspice=False,
    #                                line=(1 + upper),
    #                                nlines=(
    #                                   cubes[0].lines - lower + upper)).args)
    #
    # stats = dict()
    # stats['B'] = Get_MinMax(synthbcrp_p,
    #                         conf['Beautify']['Stretch_Reduction_Factor'],
    #                         temp_token, keep=keep)
    #
    # for band in cubes[0].band.keys():
    #     stats[band] = Get_MinMax('{}+{}'.format(str(irbmrgcrp_p),
    #                                             cubes[0].band[band]),
    #                              conf['Beautify']['Stretch_Reduction_Factor'],
    #                              temp_token, keep=keep)

    # Create an RGB cube using the RED from the IRB mosaic,
    # the BG from the IRB mosaic and the synthetic B that we just made.
    isis.cubeit_k([f"{irb_out_p}+2", f"{irb_out_p}+3", rgbsynthb_p],
                  to=rgb_out_p)

    if not keep:
        to_del.unlink()

    return
Esempio n. 10
0
def process_set(
    red: HiColorCube,
    ir: HiColorCube,
    bg: HiColorCube,
    outsuffix: str,
    keep=False,
):
    """Do all of the scaling and cropping for a RED/IR/BG set."""

    if (len(
            set(
                map(
                    lambda c: c.get_obsid(),
                    filter(lambda x: x is not None, [red, ir, bg]),
                ))) != 1):
        raise ValueError("These cube files don't all have the same "
                         f"Observation ID: {red}, {ir}, {bg}")

    temp_token = datetime.now().strftime("HiColorInit-%y%m%d%H%M%S")

    # These two values are calculated but only written to a PVL file,
    # which I think we can skip.
    # # in bin1 there are 48 pixels of overlap
    # total_width = 2 * red.samps - (48 / red.bin)
    #
    # # in bin1, the right half starts at pixel 2001
    # image_midpoint = 2000 / red.bin + 1

    for c in filter(lambda x: x is not None, [ir, bg]):
        # Calculate delta offset in lines between red and color ccd
        offset = int((200 * (c.bin - red.bin) + c.tdi - red.tdi) / red.bin)

        bin_ratio = c.bin / red.bin
        # tdi_ratio = c.tdi / red.tdi
        mag_ratio = bin_ratio / 1.0006
        # ratio of color to red for enlargement, correction of optical
        # distortion from OPTICAL_ENLARGEMENT_RATIO constant in original
        # HiColor.pm

        # Rescale the color by the bin ratio and mag ratio, to match the red.
        # These will be the BG and IR "pre-color" cubes.
        rescaled = c.path.with_suffix(f".{temp_token}.rescaled" + outsuffix)

        if mag_ratio < 1:
            s = 1 / mag_ratio
            isis.reduce(
                c.path,
                to=rescaled,
                sscale=s,
                lscale=bin_ratio,
                validper=1,
                algorithm="nearest",
                vper_replace="nearest",
            )
        else:
            isis.enlarge(
                c.path,
                to=rescaled,
                sscale=mag_ratio,
                lscale=bin_ratio,
                interp="bilinear",
            )

        # The original Perl had an additional step to divide c.bin by the
        # bin_ratio, and provide that to value= below, but that's
        # mathematically just red.bin, so we'll skip a calculation:
        isis.editlab(
            rescaled,
            options="modkey",
            grpname="Instrument",
            keyword="Summing",
            value=red.bin,
        )

        # trim by placing in a new image
        isis.handmos(
            rescaled,
            mosaic=c.path.with_suffix(outsuffix),
            create="Y",
            nlines=red.lines,
            nsamp=red.samps,
            nband=1,
            outline=offset,
            outsamp=1,
            outband=1,
        )

        if not keep:
            rescaled.unlink()

        logger.info(f"Created {c.path.with_suffix(outsuffix)}")
    return