Example #1
0
def load_pvl(input_pvl, decoder=None):
    if isinstance(input_pvl, str):
        try:
            label = pvl.load(input_pvl, decoder=decoder)
        except:
            # Some labels are poorly formatted or include characters that
            # cannot be parsed with the PVL library.  This finds those
            # characters and replaces them so that we can properly parse
            # the PVL.
            with open(input_pvl, 'r') as f:
                filedata = f.read()

            filedata = filedata.replace(';', '-').replace('&', '-')
            filedata = re.sub(r'\-\s+', r'', filedata, flags=re.M)

            with open(input_pvl, 'w') as f:
                f.write(filedata)

            label = pvl.load(input_pvl)

        label = lower_keys(label)

    elif isinstance(input_pvl, pvl.PVLModule):
        label = lower_keys(input_pvl)

    return label
Example #2
0
def test_dump_stream():
    for filename in PDS_LABELS:
        label = pvl.load(filename)
        stream = io.BytesIO()
        pvl.dump(label, stream)
        stream.seek(0)
        assert label == pvl.load(stream)
Example #3
0
def test_dump_stream():
    for filename in PDS_LABELS:
        label = pvl.load(filename)
        stream = io.BytesIO()
        pvl.dump(label, stream)
        stream.seek(0)
        assert label == pvl.load(stream)
Example #4
0
def parse_label(filename, full=False):
    """ Wraps forking paths for attached and detached PDS3 labels.
    """
    if filename.endswith('.fmt'):
        return pvl.load(filename)
    if not has_attached_label(filename):
        if os.path.exists(filename[:filename.rfind(".")] + ".LBL"):
            label = pvl.load(filename[:filename.rfind(".")] + ".LBL")
        elif os.path.exists(filename[:filename.rfind(".")] + ".lbl"):
            label = pvl.load(filename[:filename.rfind(".")] + ".lbl")
        elif os.path.exists(filename[:filename.rfind(".")] + ".xml"):
            # TODO: Make label data format consistent between PDS3 & 4
            label = pds4_tools.read(filename[:filename.rfind(".")] + ".xml",
                                    quiet=True).label.to_dict()
        else:
            print("*** Unable to locate file label. ***")
            return None
    else:
        label = parse_attached_label(filename)
    # TODO: This ugly conditional exists entirely to deal with Cassini data
    # which all seem to be returning zero-value images, so maybe it's wrong!
    if (not full) and ("UNCOMPRESSED_FILE" in label.keys()):
        if "COMPRESSED_FILE" in label.keys():
            if "ENCODING_TYPE" in label["COMPRESSED_FILE"].keys():
                if label["COMPRESSED_FILE"][
                        "ENCODING_TYPE"] == "MSLMMM-COMPRESSED":
                    return label
        return label["UNCOMPRESSED_FILE"]
    return label
Example #5
0
class TestPancam(object):

    pancam1 = Pancam(pvl.load(FILE_2))
    pancam2 = Pancam(pvl.load(FILE_3))

    def test_camera(self):
        assert self.pancam1.camera == 'PANCAM_RIGHT'
        assert self.pancam2.camera == 'PANCAM_LEFT'

    def test_is_left(self):
        assert not self.pancam1.is_left
        assert self.pancam2.is_left

    def test_is_right(self):
        assert self.pancam1.is_right
        assert not self.pancam2.is_right

    def test_filter_num(self):
        assert self.pancam1.filter_num == 8
        assert self.pancam2.filter_num == 8

    @pytest.mark.parametrize('unit, wavelength1, wavelength2',
                             [('nm', 880, 440), ('um', 0.880, 0.440),
                              ('AA', 8800, 4400)])
    def test_get_wavelength(self, unit, wavelength1, wavelength2):
        assert self.pancam1.get_wavelength(unit) == wavelength1
        assert self.pancam2.get_wavelength(unit) == wavelength2
Example #6
0
def parse_attached_label(filename):
    """ Parse an attached label of a IMG file.
    """
    # First grab the entries from the label that define how to read the label
    with open(filename, "rb") as f:
        for line_ in f:
            line = line_.decode("utf-8").strip()  # hacks through a rare error
            if "PDS_VERSION_ID" in line:
                PDS_VERSION_ID = line.strip().split("=")[1]
            if "RECORD_BYTES" in line:
                RECORD_BYTES = int(line.strip().split("=")[1])
            if "LABEL_RECORDS" in line:
                if "<BYTES>" in line:
                    # Convert pointer value to bytes like everything else
                    LABEL_RECORDS = line.strip().split("=")[1].split()[0] * 8
                else:
                    LABEL_RECORDS = int(line.strip().split("=")[1])
                break
    # Read the label and then parse it with PVL
    try:
        with open(filename, "rb") as f:
            return pvl.load(f.read(RECORD_BYTES * (LABEL_RECORDS)))
    except UnboundLocalError:
        print("*** RECORD_BYTES not set??? ***")
        return None
    except:
        with open(filename, "rb") as f:
            return pvl.load(f.read(RECORD_BYTES * (LABEL_RECORDS)),
                            strict=False)
Example #7
0
def main():
    args = Args()
    args.parse_args()
    a = {}

    if args.textfile is not None:
        filePath = open(args.textfile, 'r')
        lines = filePath.readlines()
        length = len(lines)

        for n in range(length):
            if 'https' in lines[n] or 'http' in lines[n] or 'ftp' in lines[n]:
                voldesc = urllib.request.urlopen(lines[n])
                voldescPvl = pvl.load(voldesc)
            else:
                voldescPvl = load_pvl(lines[n].rstrip())
            a.update(ds_count(voldescPvl))
    else:
        if 'https' in args.local or 'http' in args.local or 'ftp' in args.local:
            voldesc = urllib.request.urlopen(args.local)
            voldescPvl = pvl.load(voldesc)
        else:
            filePath = open(str(args.local), 'r')
            voldescPvl = load_pvl(str(args.local))
        a.update(ds_count(voldescPvl))

    if args.output is not None:
        f = open(args.output, 'w')
        f.write(str(json.dumps(a)))
    else:
        print(json.dumps(a))
Example #8
0
    def __init__(self, path: os.PathLike):
        # First try it as an ISIS cube:
        try:
            cam_to = Path(path).with_suffix(".caminfo")
            sh.caminfo(f'from={path}', f'to={cam_to}', 'polygon=True')
            caminfo = pvl.load(str(cam_to))
        except subprocess.CalledProcessError:
            # Maybe it is the PVL output of caminfo?
            caminfo = pvl.load(str(path))

        camgeo = caminfo["Caminfo"]["Geometry"]

        self.path = Path(path)

        self.incidence_angle = float(camgeo["IncidenceAngle"])
        self.emission_angle = float(camgeo["EmissionAngle"])
        self.phase_angle = float(camgeo["PhaseAngle"])
        self.sc_azimuth = float(camgeo["SubSpacecraftGroundAzimuth"])
        self.solar_azimuth = float(camgeo["SubSolarGroundAzimuth"])
        self.gsd = float(camgeo["ObliquePixelResolution"])

        try:
            from shapely import wkt
            self.geometry = wkt.loads(
                caminfo["Caminfo"]["Polygon"]["GisFootprint"])
        except ImportError:
            self.geometry = None
Example #9
0
def test_dump_to_file():
    tmpdir = tempfile.mkdtemp()

    try:
        for filename in PDS_LABELS:
            label = pvl.load(filename)
            tmpfile = os.path.join(tmpdir, os.path.basename(filename))
            pvl.dump(label, tmpfile)
            assert label == pvl.load(tmpfile)
    finally:
        shutil.rmtree(tmpdir)
Example #10
0
def test_dump_to_file():
    tmpdir = tempfile.mkdtemp()

    try:
        for filename in PDS_COMPLIANT:
            label = pvl.load(filename)
            tmpfile = os.path.join(tmpdir, os.path.basename(filename))
            pvl.dump(label, tmpfile)
            assert label == pvl.load(tmpfile)
    finally:
        shutil.rmtree(tmpdir)
Example #11
0
def test_broken_labels(label, expected, expected_errors):
    with open(os.path.join(BROKEN_DIR, label), 'rb') as stream:
        module = pvl.load(stream, strict=False)
    expected = pvl.PVLModule(expected)

    assert module == expected
    assert module.errors == expected_errors
    assert not module.valid

    with open(os.path.join(BROKEN_DIR, label), 'rb') as stream:
        with pytest.raises(pvl.decoder.ParseError):
            pvl.load(stream, strict=True)
Example #12
0
def test_broken_labels(label, expected, expected_errors):
    with open(os.path.join(BROKEN_DIR, label), 'rb') as stream:
        module = pvl.load(stream, strict=False)
    expected = pvl.PVLModule(expected)

    assert module == expected
    assert module.errors == expected_errors
    assert not module.valid

    with open(os.path.join(BROKEN_DIR, label), 'rb') as stream:
        with pytest.raises(pvl.decoder.ParseError):
            pvl.load(stream, strict=True)
Example #13
0
def test_dump_to_file_insert_before():
    tmpdir = tempfile.mkdtemp()

    try:
        for filename in PDS_COMPLIANT:
            label = pvl.load(filename)
            if os.path.basename(filename) != 'empty.lbl':
                label.insert_before('PDS_VERSION_ID', [('new', 'item')])
            tmpfile = os.path.join(tmpdir, os.path.basename(filename))
            pvl.dump(label, tmpfile, encoder=pvl.encoder.PVLEncoder())
            assert label == pvl.load(tmpfile)
    finally:
        shutil.rmtree(tmpdir)
Example #14
0
def test_dump_to_file_insert_after():
    tmpdir = tempfile.mkdtemp()

    try:
        for filename in PDS_LABELS:
            label = pvl.load(filename)
            if os.path.basename(filename) != 'empty.lbl':
                label.insert_after('PDS_VERSION_ID', [('new', 'item')])
            tmpfile = os.path.join(tmpdir, os.path.basename(filename))
            pvl.dump(label, tmpfile)
            assert label == pvl.load(tmpfile)
    finally:
        shutil.rmtree(tmpdir)
Example #15
0
def test_dump_to_file_insert_after():
    tmpdir = tempfile.mkdtemp()

    try:
        for filename in PDS_LABELS:
            label = pvl.load(filename)
            if os.path.basename(filename) != 'empty.lbl':
                label.insert_after('PDS_VERSION_ID', [('new', 'item')])
            tmpfile = os.path.join(tmpdir, os.path.basename(filename))
            pvl.dump(label, tmpfile)
            assert label == pvl.load(tmpfile)
    finally:
        shutil.rmtree(tmpdir)
Example #16
0
def test_dump_to_file_insert_after():
    tmpdir = tempfile.mkdtemp()

    try:
        for filename in PDS_COMPLIANT:
            label = pvl.load(filename)
            if os.path.basename(filename) != "empty.lbl":
                label.insert_after("PDS_VERSION_ID", [("new", "item")])
            tmpfile = os.path.join(tmpdir, os.path.basename(filename))
            pvl.dump(label, tmpfile, encoder=pvl.encoder.PVLEncoder())
            assert label == pvl.load(tmpfile)
    finally:
        shutil.rmtree(tmpdir)
Example #17
0
    def __init__(
            self,
            # `uvis_id` can be either the PDS product_id 'FUV2005_172_03_35' or the long form
            # used within the UVIS product.
            # The attribute `pid` will carry the shortenend PDS identifier,
            # attribute `uvis_id` will just store what the user came in with.
            uvis_id: str,
            skip_download: bool = False):
        self.uvis_id = uvis_id
        self.product_id = self.pid = uvis_id[:17]
        self.path = get_data_path(self.pid, skip_download)
        if self.path is None:
            raise FileNotFoundError("No valid data path found.")
        self.pds = PDSReader(self.path)
        self.datalabel = self.pds.label
        self.cal_data = None

        # Try to load the calibration Matrix file.  If not present, set to None.
        if self.cal_label_path.exists() and self.cal_data_path.exists():
            self.cal_data = PDSReader(self.cal_data_path)
            self.cal_matrix = self.cal_data.data
            self.caliblabel = dict2obj(pvl.load(str(self.cal_label_path)))
            self.set_cal_wavelengths()
        else:
            self.set_default_wavelengths()
Example #18
0
    def filterCNetPVL(self, path=None):
        """Filters the CNET file and adds Ignored point information."""

        if len(self.IgnoredPoints) == 0:
            return

        if path is None:
            path = self.cnet_path

        p = pvl.load(str(path))

        cn = pvl.PVLModule()

        badness = 0
        for (k, v) in p["ControlNetwork"].items():
            if k == "ControlPoint":
                if (v["PointId"] in self.IgnoredPoints
                        and "Ignore" not in v.keys()):
                    v.append("Ignore", True)
                    badness += 1
                    logger.info("Ignoring point {}".format(v["PointId"]))
            cn.append(k, v)

        logger.info(f"{badness} point(s) ignored.")

        new_pvl = pvl.PVLModule(ControlNetwork=cn)

        with open(path, "w") as stream:
            pvl.dump(new_pvl, stream, encoder=pvl.encoder.ISISEncoder())
Example #19
0
def extract_img(image_file: str) -> Image:
    """Extracts and returns embedded image from PDS3 IMG files as PIL Image.

    Args:
        image_file (str): path to .IMG file.

    Returns:
        PIL.Image
    """

    # Parsing label
    label = pvl.load(image_file)  # load label from .IMG file
    image_data = label['IMAGE']  # getting image object info

    h_img, w_img = image_data[0][-1], image_data[1][-1]  # real image sizes
    pref, suff = image_data[6][-1], image_data[7][-1]  # buffer pixels margins
    w_total = w_img + pref + suff  # width with margins

    offset = label['^IMAGE'].value  # pointer where image is located
    size = label['^GAP_TABLE'].value - label[
        '^IMAGE'].value  # image size (in bytes)

    # Now getting back to file
    with open(image_file, "rb") as f:
        container = ContainerIO.ContainerIO(f, offset - 1, size)
        data = container.read()  # reading image bytes
        img = Image.frombytes('L', (w_total, h_img), data, "raw")  # decoding
        img = img.crop((pref, 0, w_img + pref, h_img))  # cropping margins

    return img
Example #20
0
def object_asarray(file_path: os.PathLike, name: str) -> np.ndarray:
    """Return the data object of *name* from *file_path* as a numpy array.

    Data objects are found by having both a a pointer parameter (like ^*name*)
    and an object in the label with *name*.

    Doesn't work for objects that have columns.  Since such objects don't
    have SAMPLE_BITS and SAMPLE_TYPE fields, this will result in a KeyError.
    """
    label = pvl.load(str(file_path))
    width, b_order, b_signed = byte_info(name, label)

    lut = LUT_Table(
        label["INSTRUMENT_SETTING_PARAMETERS"]["MRO:LOOKUP_CONVERSION_TABLE"])

    table = list()
    with open(file_path, mode="rb") as f:
        # Since The first byte is location 1 (not 0) in PDS-counting.
        f.seek(int(label[f"^{name}"].value) - 1)
        for line in range(label[name]["LINES"]):
            row = list()
            # Skip over the prefix bytes.
            f.seek(label[name]["LINE_PREFIX_BYTES"], os.SEEK_CUR)
            for samp in range(label[name]["LINE_SAMPLES"]):
                dn = lut.unlut(
                    int.from_bytes(f.read(width),
                                   byteorder=b_order,
                                   signed=b_signed))
                row.append(dn)
            table.append(row)
            # Skip over the suffix bytes.
            f.seek(label[name]["LINE_SUFFIX_BYTES"], os.SEEK_CUR)

    return np.array(table)
Example #21
0
def overwrite_object(file_path: os.PathLike, name: str, arr: np.ndarray):
    """The file at *file_path* will have its *name* object overwritten
    with the data in *array*.

    Doesn't work for objects that have columns.  Since such objects don't
    have SAMPLE_BITS and SAMPLE_TYPE fields, this will result in a KeyError.
    """
    label = pvl.load(str(file_path))
    width, b_order, b_signed = byte_info(name, label)

    if arr.shape != (label[name]["LINES"], label[name]["LINE_SAMPLES"]):
        raise ValueError(f"The object {name} has different dimensions "
                         f"({label[name]['LINES']}, "
                         f"{label[name]['LINE_SAMPLES']})than "
                         f"the array ({arr.shape}).")

    lut = LUT_Table(
        label["INSTRUMENT_SETTING_PARAMETERS"]["MRO:LOOKUP_CONVERSION_TABLE"])

    with open(file_path, mode="r+b") as f:
        # Since The first byte is location 1 (not 0) in PDS-counting.
        f.seek(int(label[f"^{name}"].value) - 1)
        for line in range(arr.shape[0]):
            # Skip over the prefix bytes.
            f.seek(label[name]["LINE_PREFIX_BYTES"], os.SEEK_CUR)
            for samp in range(arr.shape[1]):
                f.write(
                    lut.lookup(arr[line][samp]).to_bytes(width,
                                                         byteorder=b_order,
                                                         signed=b_signed))
            # Skip over the suffix bytes.
            f.seek(label[name]["LINE_SUFFIX_BYTES"], os.SEEK_CUR)
    return
Example #22
0
    def readLBL(self):
        '''Read VIMS LBL header'''
        self.lbl = pvl.load(self.imgID + '.LBL')

        for ii, axis in enumerate(self.lbl['QUBE']['AXIS_NAME']):
            if axis == 'SAMPLE':
                self.NS = int(self.lbl['QUBE']['CORE_ITEMS'][ii])
            elif axis == 'LINE':
                self.NL = int(self.lbl['QUBE']['CORE_ITEMS'][ii])
            elif axis == 'BAND':
                self.NB = int(self.lbl['QUBE']['CORE_ITEMS'][ii])

        self.obs = self.lbl['INSTRUMENT_HOST_NAME']
        self.inst = self.lbl['INSTRUMENT_ID']
        self.target = self.lbl['TARGET_NAME']
        self.expo = self.lbl['FRAME_PARAMETER'][0]
        #self.mode = self.lbl['QUBE']['SAMPLING_MODE_ID'][0]
        #self.seq    = self.lbl['QUBE']['SEQUENCE_ID']
        #self.seq_title = self.lbl['QUBE']['SEQUENCE_TITLE']
        self.start = self.lbl['START_TIME']
        self.stop = self.lbl['STOP_TIME']
        self.dtime = (self.stop - self.start) / 2 + self.start
        self.time = self.dtime.strftime('%Y-%m-%dT%H:%M:%S.%f')
        self.year = self.dtime.year
        self.doy = int(self.dtime.strftime('%j'))
        self.year_d = self.year + (
            self.doy - 1
        ) / 365.  # Decimal year [ISSUE: does not apply take into account bissextile years]
        self.date = self.dtime.strftime('%Y/%m/%d')

        self.wvlns = np.array(self.lbl['QUBE']['BAND_BIN']['BAND_BIN_CENTER'])
        self.bands = np.array(
            self.lbl['QUBE']['BAND_BIN']['BAND_BIN_ORIGINAL_BAND'])
        return
Example #23
0
def main():
    args = arg_parser().parse_args()

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

    if len(args.img) > 1 and not args.output.startswith("."):
        logger.critical(
            "With more than one input IMG file, the --output must start with "
            f"a period, and it does not: {args.output}"
        )
        sys.exit()

    gainsinfo = pvl.load(args.gains)

    for i in args.img:
        out_p = util.path_w_suffix(args.output, i)

        with util.main_exceptions(args.verbose):
            histats = EDR_Stats(
                i, out_p, gainsinfo, args.histmin, args.histmax, keep=args.keep
            )

        # DB stuff
        # for k, v in histats.items():
        #     print(f'{k}: {v}')
        db_path = util.path_w_suffix(args.db, i)

        with open(db_path, "w") as f:
            json.dump(histats, f, indent=0, sort_keys=True)

        logger.info(f"Wrote {db_path}")
    return
Example #24
0
    def readLBL(self):
        '''Read VIMS LBL header'''
        self.lbl = pvl.load(self.fname)

        for ii, axis in enumerate(self.lbl['SPECTRAL_QUBE']['AXIS_NAME']):
            if axis == 'SAMPLE':
                self.NS = int(self.lbl['SPECTRAL_QUBE']['CORE_ITEMS'][ii])
            elif axis == 'LINE':
                self.NL = int(self.lbl['SPECTRAL_QUBE']['CORE_ITEMS'][ii])
            elif axis == 'BAND':
                self.NB = int(self.lbl['SPECTRAL_QUBE']['CORE_ITEMS'][ii])

        self.obs    = self.lbl['INSTRUMENT_HOST_NAME']
        self.inst   = self.lbl['INSTRUMENT_ID']
        self.target = self.lbl['TARGET_NAME']
        self.expo = {'IR': self.lbl['EXPOSURE_DURATION'][0], 'VIS': self.lbl['EXPOSURE_DURATION'][1]}
        self.mode = {'IR': self.lbl['SAMPLING_MODE_ID'][0], 'VIS': self.lbl['SAMPLING_MODE_ID'][1]}
        self.seq    = self.lbl['SEQUENCE_ID']
        self.seq_title = self.lbl['SEQUENCE_TITLE']
        self.start  = self.lbl['START_TIME']
        self.stop   = self.lbl['STOP_TIME']
        self.dtime  = (self.stop - self.start)/2 + self.start
        self.time   = self.dtime.strftime('%Y-%m-%dT%H:%M:%S.%f')
        self.year   = self.dtime.year
        self.doy    = int(self.dtime.strftime('%j'))
        self.year_d = self.year + (self.doy-1)/365. # Decimal year [ISSUE: doest not apply take into account bissextile years]
        self.date   = self.dtime.strftime('%Y/%m/%d')

        self.wvlns = None
        self.bands = None
        return
Example #25
0
def parse_label(label, grammar=pvl.grammar.PVLGrammar):
    """
    Attempt to parse a PVL label.

    Parameters
    ----------
    label
        The label as a pvl string or pvl file.

    grammar
        The pvl grammar with which to parse the label. If None, default to PVLGrammar


    Returns
    -------
    pvl.collections.PVLModule
        The PVL label deserialized to a Python object

    See Also
    --------
    load
    loads
    """
    try:
        parsed_label = pvl.loads(label, grammar=grammar)
    except Exception:
        parsed_label = pvl.load(label, grammar=grammar)
    except:
        raise ValueError("{} is not a valid label for grammar {}".format(label, grammar.__name__))

    return parsed_label
Example #26
0
def extract_band(job, image, band_num):
    """
    Extract the temperature data from the processed ISIS cube.

    Parameters
    ----------
    job : dict
               Job specification dictionary

    image : str
               PATH to an ISIS cube to extract bands from

    band_num : int
               Band number that needs to be extracted

    Returns
    ----------
    : ndarray
               Array representation of the extracted band
    """
    header = pvl.load(job['images'])
    bands = find_in_dict(header, 'BAND_BIN_BAND_NUMBER')

    for i, band in enumerate(bands):
        if band_num == band:
            geo_image = io_gdal.GeoDataset(image)
            return geo_image.read_array(band=i + 1)
Example #27
0
    def label(self):
        """
        Loads a PVL from from the _file attribute and
        parses the binary table data.

        Returns
        -------
        PVLModule :
            Dict-like object with PVL keys
        """
        class PvlDecoder(pvl.decoder.PVLDecoder):
            def unescape_next_char(self, stream):
                esc = stream.read(1)
                string = '\{}'.format(esc.decode('utf-8')).encode('utf-8')
                return string

        if not hasattr(self, "_label"):
            if isinstance(self._file, pvl.PVLModule):
                self._label = self._file
            try:
                self._label = pvl.loads(self._file, PvlDecoder)
            except Exception:

                # PvlDecoder class to ignore all escape sequences when getting
                # the label
                self._label = pvl.load(self._file, PvlDecoder)
            except:
                raise ValueError("{} is not a valid label".format(self._file))
        return self._label
Example #28
0
 def metadata(self):
     if not hasattr(self, '_metadata'):
         try:
             self._metadata = pvl.load(self.file_name)
         except:
             self._metadata = self.dataset.GetMetadata()
     return self._metadata
Example #29
0
def main():
    # The original Perl needed the specific output of cubenorm from a
    # particular step in the HiCal pipeline before here.  However, rather
    # than keep track of those files, open them, and read them again, we
    # can (and did) perform the relevant check in HiCal.py, and then save
    # that in the db that we can check now.

    args = arg_parser().parse_args()

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

    with util.main_exceptions(args.verbose):
        (db, outcub_path) = HiStitch(
            args.cube0,
            args.cube1,
            get_db(util.pid_path_w_suffix(args.db, args.cube0)),
            get_db(util.pid_path_w_suffix(args.db2, args.cube1)),
            args.output,
            pvl.load(args.conf),
            keep=args.keep,
        )

    db_path = set_outpath(args.dbout, hirise.get_CCDID_fromfile(outcub_path),
                          outcub_path.parent)

    with open(db_path, "w") as f:
        json.dump(db, f, indent=0, sort_keys=True)

    logger.info(f"Wrote {db_path}")
    return
Example #30
0
def main():
    args = arg_parser(formats).parse_args()

    some_pvl = pvl.load(args.infile)

    formats[args.output_format].dump(some_pvl, args.outfile)
    return
Example #31
0
 def metadata(self):
     if not hasattr(self, '_metadata'):
         try:
             self._metadata = pvl.load(self.file_name)
         except:
             self._metadata = self.dataset.GetMetadata()
     return self._metadata
Example #32
0
    def __init__(self, fname):
        self.path = Path(fname)
        # file management
        self.file_id = self.path.stem
        self.label_fname = self.path.with_suffix(".LBL")
        self.data_fname = self.path.with_suffix(".DAT")

        # read the data
        self.data1D = (np.fromfile(str(self.data_fname), ">H")).astype(np.uint16)

        # label stuff
        self.label = pvl.load(str(self.label_fname))
        self.cubelabel = self.label["QUBE"]
        self.LINE_BIN = self.cubelabel["LINE_BIN"]
        self.BAND_BIN = self.cubelabel["BAND_BIN"]
        self.shape = tuple(self.cubelabel["CORE_ITEMS"])
        self.line_range = (
            self.cubelabel["UL_CORNER_LINE"],
            self.cubelabel["LR_CORNER_LINE"] + 1,  # for numpy slicing + 1
        )
        self.band_range = (
            self.cubelabel["UL_CORNER_BAND"],
            self.cubelabel["LR_CORNER_BAND"] + 1,  # for numpy slicing + 1
        )

        # reshape the data with infos from label
        self.data = self.data1D.reshape(self.shape, order="F")[
            slice(*self.band_range), slice(*self.line_range), :
        ]
    def read(self):
        """
        Given an ISIS store, read the underlying ISIS3 compatible control network and
        return an IsisControlNetwork dataframe.
        """
        pvl_header = pvl.load(self._path)
        header_start_byte = find_in_dict(pvl_header, 'HeaderStartByte')
        header_bytes = find_in_dict(pvl_header, 'HeaderBytes')
        point_start_byte = find_in_dict(pvl_header, 'PointsStartByte')
        version = find_in_dict(pvl_header, 'Version')

        if version == 2:
            self.point_attrs = [i for i in cnf._CONTROLPOINTFILEENTRYV0002.fields_by_name if i != 'measures']
            self.measure_attrs = [i for i in cnf._CONTROLPOINTFILEENTRYV0002_MEASURE.fields_by_name]

            cp = cnf.ControlPointFileEntryV0002()
            self._handle.seek(header_start_byte)
            pbuf_header = cnf.ControlNetFileHeaderV0002()
            pbuf_header.ParseFromString(self._handle.read(header_bytes))

            self._handle.seek(point_start_byte)
            cp = cnf.ControlPointFileEntryV0002()
            pts = []
            for s in pbuf_header.pointMessageSizes:
                cp.ParseFromString(self._handle.read(s))
                pt = [getattr(cp, i) for i in self.point_attrs if i != 'measures']

                for measure in cp.measures:
                    meas = pt + [getattr(measure, j) for j in self.measure_attrs]
                    pts.append(meas)

        elif version == 5:
            self.point_attrs = [i for i in cnp5._CONTROLPOINTFILEENTRYV0005.fields_by_name if i != 'measures']
            self.measure_attrs = [i for i in cnp5._CONTROLPOINTFILEENTRYV0005_MEASURE.fields_by_name]

            cp = cnp5.ControlPointFileEntryV0005()
            self._handle.seek(header_start_byte)
            pbuf_header = cnh5.ControlNetFileHeaderV0005()
            pbuf_header.ParseFromString(self._handle.read(header_bytes))

            self._handle.seek(point_start_byte)
            cp = cnp5.ControlPointFileEntryV0005()
            pts = []
            byte_count = 0;
            while byte_count < find_in_dict(pvl_header, 'PointsBytes'):
                message_size = struct.unpack('I', self._handle.read(4))[0]
                cp.ParseFromString(self._handle.read(message_size))
                pt = [getattr(cp, i) for i in self.point_attrs if i != 'measures']

                for measure in cp.measures:
                    meas = pt + [getattr(measure, j) for j in self.measure_attrs]
                    pts.append(meas)

                byte_count += 4 + message_size

        cols = self.point_attrs + self.measure_attrs
        df = IsisControlNetwork(pts, columns=cols)
        df.header = pvl_header
        return df
Example #34
0
def read_label(filename):
    try:
        label = pvl.load(filename, strict=False)
        if not len(label):
            raise ValueError("Cannot find attached label data.")
        label.append("attached_label_filename", filename)
        return label
    except:  # look for a detached label
        if os.path.exists(filename[:filename.rfind(".")] + ".LBL"):
            return pvl.load(filename[:filename.rfind(".")] + ".LBL",
                            strict=False)
        elif os.path.exists(filename[:filename.rfind(".")] + ".lbl"):
            return pvl.load(filename[:filename.rfind(".")] + ".lbl",
                            strict=False)
        else:
            print(" *** Cannot find label data. *** ")
            raise
Example #35
0
def test_load_all_sample_labels():
    files = glob.glob(os.path.join(PDS_DATA_DIR, "*.lbl"))
    for infile in files:
        try:
            label = pvl.load(infile)
        except:
            raise
        assert isinstance(label, Label)
Example #36
0
def get_campt_label(frompath, sample, line):
    try:
        group = pvl.load(campt(from_=str(frompath), sample=sample,
                               line=line)).get('GroundPoint')
    except ProcessError as e:
        print(e.stdout)
        print(e.stderr)
        raise e
    else:
        return group
Example #37
0
def get_rdr_index_names():
    lblfile = hirise_dropbox() / 'RDRCUMINDEX.LBL'
    label = pvl.load(lblfile)
    table = label['RDR_INDEX_TABLE']
    names = []
    for item in table:
        second = item[1]
        if isinstance(second, pvl.PVLObject):
            names.append(second['NAME'])
    return names
Example #38
0
def read_image_header(filename):  # ^IMAGE_HEADER
    label = parse_label(filename)
    try:
        with open(filename, "rb") as f:
            f.seek(data_start_byte(label, "^IMAGE_HEADER"))
            image_header = pvl.load(f.read(label["IMAGE_HEADER"]["BYTES"]))
        return image_header
    except:
        print("*** Unable to parse image header. ***")
        return
Example #39
0
def get_rdr_index_names():
    lblfile = hirise_dropbox() / 'RDRCUMINDEX.LBL'
    label = pvl.load(str(lblfile))
    table = label['RDR_INDEX_TABLE']
    names = []
    for item in table:
        second = item[1]
        if isinstance(second, pvl.PVLObject):
            names.append(second['NAME'])
    return names
Example #40
0
def get_campt_label(frompath, sample, line):
    try:
        group = pvl.load(campt(from_=str(frompath),
                               sample=sample,
                               line=line)).get('GroundPoint')
    except ProcessError as e:
        print(e.stdout)
        print(e.stderr)
        raise e
    else:
        return group
Example #41
0
def test_parse_error():
    with pytest.raises(pvl.decoder.ParseError):
        pvl.loads(b'foo=')

    with pytest.raises(pvl.decoder.ParseError):
        pvl.loads(b'=')

    with pytest.raises(pvl.decoder.ParseError):
        pvl.loads(b'(}')

    with pytest.raises(pvl.decoder.ParseError):
        pvl.loads(b'foo=')

    with pytest.raises(pvl.decoder.ParseError):
        pvl.loads(b'foo=!')

    with pytest.raises(pvl.decoder.ParseError):
        pvl.loads(b'foo')

    with pytest.raises(pvl.decoder.ParseError):
        pvl.load(io.BytesIO(b'foo'))
Example #42
0
    def test_create_pvl_header(self):
        pvl_header = pvl.load("test.net")

        npoints = find_in_dict(pvl_header, "NumberOfPoints")
        self.assertEqual(2, npoints)

        mpoints = find_in_dict(pvl_header, "NumberOfMeasures")
        self.assertEqual(5, mpoints)

        points_bytes = find_in_dict(pvl_header, "PointsBytes")
        self.assertEqual(334, points_bytes)

        points_start_byte = find_in_dict(pvl_header, "PointsStartByte")
        self.assertEqual(65621, points_start_byte)
    def test_create_pvl_header(self):
        pvl_header = pvl.load('test.net')

        npoints = find_in_dict(pvl_header, 'NumberOfPoints')
        self.assertEqual(2, npoints)

        mpoints = find_in_dict(pvl_header, 'NumberOfMeasures')
        self.assertEqual(5, mpoints)

        points_bytes = find_in_dict(pvl_header, 'PointsBytes')
        self.assertEqual(330, points_bytes)

        points_start_byte = find_in_dict(pvl_header, 'PointsStartByte')
        self.assertEqual(65621, points_start_byte)
def generate_serial_number(label):
    """
    Generate an ISIS compatible serial number using the ISIS
    team's translation files

    Parameters
    ----------
    label : dict or str
            A PVLModule object (dict) or string PATH
            to a file containing a PVL header

    Returns
    -------
     : str
       The ISIS compatible serial number
    """
    if not isinstance(label, PVLModule):
        label = pvl.load(label, cls=SerialNumberDecoder)
    # Get the translation information
    translation = get_isis_translation(label)

    if not translation:
        warnings.warn('Unable to load an appropriate image translation.')
        return

    serial_number = []

    # Sort the keys to ensure proper iteration order
    keys = sorted(translation.keys())

    for k in keys:
        try:
            group = translation[k]
            search_key = group['InputKey']
            search_position = group['InputPosition']
            search_translation = {group['Translation'][1]:group['Translation'][0]}
            sub_group = find_nested_in_dict(label, search_position)
            serial_entry = sub_group[search_key]

            if serial_entry in search_translation.keys():
                serial_entry = search_translation[serial_entry]
            elif '*' in search_translation.keys() and search_translation['*'] != '*':
                serial_entry = search_translation['*']
            serial_number.append(serial_entry)
        except:
            pass
    return '/'.join(serial_number)
Example #45
0
def extract_keywords(header, *args):
    """
    For a given header, find all of the keys and return an unnested dict.
    """
    try:
        header = pvl.load(header)
    except:
        header = pvl.loads(header)

    res = {}
    # Iterate through all of the requested keys
    for a in args:
        try:
            res[a] = find_in_dict(a)
        except:
            res[a] = None
    return res
Example #46
0
def get_isis_translation(label):
    """
    Compute the ISIS serial number for a given image using
    the input cube or the label extracted from the cube.

    Parameters
    ----------
    label : dict or str
            A PVL dict object or file name to extract
            the PVL object from

    Returns
    -------
    translation : dict
                  A PVLModule object containing the extracted
                  translation file
    """
    # Instantiate a DB session if not already instantiated
    if not hasattr(plio, 'data_session'):
        print(get_data('data.db'))
        plio.data_session = setup_db_session(get_data('data.db'))

    # Grab the label is not already read
    if not isinstance(label, PVLModule):
        label = pvl.load(label)

    # Grab the spacecraft name and run it through the ISIS lookup
    spacecraft_name = find_in_dict(label, 'SpacecraftName')
    for row in plio.data_session.query(StringToMission).filter(StringToMission.key==spacecraft_name):
        spacecraft_name = row.value.lower()

    # Try and pull an instrument identifier
    try:
        instrumentid = find_in_dict(label, 'InstrumentId').capitalize()
    except:
        instrumentid = None

    translation = None
    # Grab the translation PVL object using the lookup
    for row in plio.data_session.query(Translations).filter(Translations.mission==spacecraft_name,
                                                            Translations.instrument==instrumentid):
        # Convert the JSON back to a PVL object
        translation = PVLModule(row.translation)

    return translation
Example #47
0
def test_pds3_sample_image():
    infile = os.path.join(PDS_DATA_DIR, "simple_image_1.lbl")
    label = pvl.load(infile)
    assert label['RECORD_TYPE'] == 'FIXED_LENGTH'
    assert label['RECORD_BYTES'] == 824
    assert label['LABEL_RECORDS'] == 1
    assert label['FILE_RECORDS'] == 601
    assert label['IMAGE']['LINES'] == 600
    assert label['IMAGE']['LINE_SAMPLES'] == 824
    image_group = label['IMAGE']
    assert image_group['SAMPLE_TYPE'] == 'MSB_INTEGER'
    assert image_group['SAMPLE_BITS'] == 8
    assert abs(image_group['MEAN'] - 51.6778539644) <= 0.00001
    assert image_group['MEDIAN'] == 50.0
    assert image_group['MINIMUM'] == 0
    assert image_group['MAXIMUM'] == 255
    assert image_group['STANDARD_DEVIATION'] == 16.97019
    assert image_group['CHECKSUM'] == 25549531
Example #48
0
def test_cube_label():
    with open(os.path.join(DATA_DIR, 'pattern.cub'), 'rb') as fp:
        label = pvl.load(fp)

    assert isinstance(label['Label'], dict)
    assert label['Label']['Bytes'] == 65536

    assert isinstance(label['IsisCube'], dict)
    assert isinstance(label['IsisCube']['Core'], dict)
    assert label['IsisCube']['Core']['StartByte'] == 65537
    assert label['IsisCube']['Core']['Format'] == 'Tile'
    assert label['IsisCube']['Core']['TileSamples'] == 128
    assert label['IsisCube']['Core']['TileLines'] == 128

    assert isinstance(label['IsisCube']['Core']['Dimensions'], dict)
    assert label['IsisCube']['Core']['Dimensions']['Samples'] == 90
    assert label['IsisCube']['Core']['Dimensions']['Lines'] == 90
    assert label['IsisCube']['Core']['Dimensions']['Bands'] == 1

    assert isinstance(label['IsisCube']['Core']['Pixels'], dict)
    assert label['IsisCube']['Core']['Pixels']['Type'] == 'Real'
    assert label['IsisCube']['Core']['Pixels']['ByteOrder'] == 'Lsb'
    assert label['IsisCube']['Core']['Pixels']['Base'] == 0.0
    assert label['IsisCube']['Core']['Pixels']['Multiplier'] == 1.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'

    #load ISIS3 label using PVL library
    isis3lbl = pvl.load(inputlbl)

    #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 = (isis3lbl['IsisCube']['Mapping']['TargetName']).upper()
        theLine = '-co VAR_TARGET={}\n'.format(target)
        fileConfig.write(theLine)
    except KeyError:
        print('No Target in ISIS3 Label')

    try:
        mission = (isis3lbl['IsisCube']['Archive']['InstrumentHostName']).upper()
        theLine = '-co VAR_INVESTIGATION_AREA_NAME="{}"\n'.format(mission)
        fileConfig.write(theLine)
    except KeyError:
        print('No InstrumentHostName in ISIS3 Label')

    try:
        dataSetID = isis3lbl['IsisCube']['Archive']['DataSetId']
        theLine = '-co VAR_LOGICAL_IDENTIFIER={}\n'.format(dataSetID)
        fileConfig.write(theLine)
    except KeyError:
        print('No DataSetId in ISIS3 Label')

    try:
        observeID = isis3lbl['IsisCube']['Archive']['InstrumentId']
        theLine = '-co VAR_OBSERVING_SYSTEM_NAME={}\n'.format(observeID)
        fileConfig.write(theLine)
    except KeyError:
        print('No InstrumentId in ISIS3 Label')

    try:
        fileName = isis3lbl['IsisCube']['Archive']['ProductId']
        theLine = '-co VAR_TITLE={}\n'.format(fileName)
        fileConfig.write(theLine)
    except KeyError:
        print('No ProductId in ISIS3 Label')

    #try:
        #producerName = isis3lbl['IsisCube']['Archive']['ProducerFullName']
    #except KeyError:
        #print('No ProducerFullName in ISIS3 Label')

    #try:
        #proInstName = isis3lbl['IsisCube']['Archive']['ProducerInstitutionName']
    #except KeyError:
        #print('No ProducerInstitutionName 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)
Example #50
0
def test_default_encoder():
    for filename in PDS_LABELS:
        label = pvl.load(filename)
        assert label == pvl.loads(pvl.dumps(label))
Example #51
0
def test_pds_encoder():
    for filename in PDS_LABELS:
        label = pvl.load(filename)
        encoder = pvl.encoder.PDSLabelEncoder
        assert label == pvl.loads(pvl.dumps(label, cls=encoder))
Example #52
0
    def __init__(self, input_data, cleaned=True, qa_threshold=2000):
        """
        Read the .spc file, parse the label, and extract the spectra

        Parameters
        ----------

        input_data : string
                     The PATH to the input .spc file

        cleaned : boolean
                  If True, mask the data based on the QA array.
        """

        label_dtype_map = {'IEEE_REAL':'f',
                        'MSB_INTEGER':'i',
                        'MSB_UNSIGNED_INTEGER':'u'}

        label = pvl.load(input_data)
        self._label = label 
        with open(input_data, 'rb') as indata:

            # Get the offsets
            ancillary_data_offset = find_in_dict(label, 
                                    "^ANCILLARY_AND_SUPPLEMENT_DATA").value
            wavelength_offset = find_in_dict(label, "^SP_SPECTRUM_WAV").value
            raw_offset = find_in_dict(label, "^SP_SPECTRUM_RAW").value
            ref2_offset = find_in_dict(label, "^SP_SPECTRUM_REF2").value
            radiance_offset = find_in_dict(label, "^SP_SPECTRUM_RAD").value
            ref1_offset = find_in_dict(label, "^SP_SPECTRUM_REF1").value
            qa_offset = find_in_dict(label, "^SP_SPECTRUM_QA").value
            l2d_offset = find_in_dict(label, "^L2D_RESULT_ARRAY").value

            ancillary_data = find_in_dict(label, "ANCILLARY_AND_SUPPLEMENT_DATA")
            nrows = ancillary_data['ROWS']
            ncols = ancillary_data['COLUMNS']
            rowbytes = ancillary_data['ROW_BYTES']

            columns = []
            bytelengths = []
            datatypes = []

            index = np.arange(nrows)

            indata.seek(ancillary_data_offset - 1)

            for i in ancillary_data.items():
                if i[0] == 'COLUMN':
                    entry = i[1]
                    columns.append(str(entry['NAME']))
                    datatypes.append(label_dtype_map[entry['DATA_TYPE']])
                    bytelengths.append(entry['BYTES'])
            strbytes = map(str, bytelengths)
            rowdtype = list(zip(columns, map(''.join, zip(['>'] * ncols, datatypes, strbytes))))
            d = np.fromstring(indata.read(rowbytes * nrows), dtype=rowdtype,
                              count=nrows)
            self.ancillary_data = pd.DataFrame(d, columns=columns,
                                               index=np.arange(nrows))

            """
            print len(columns)
            for i in range(nrows):
                d = np.fromstring(indata.read(rowbytes), dtype=rowdtype, count=1)
                self.ancillary_data.iloc[i] = d[0]
            """

            assert(ncols == len(columns))

            keys = ["SP_SPECTRUM_WAV","SP_SPECTRUM_RAW", "SP_SPECTRUM_REF1",
                    "SP_SPECTRUM_REF2", "SP_SPECTRUM_RAD", "SP_SPECTRUM_QA"]
            array_offsets = [wavelength_offset, raw_offset, ref1_offset,
                            ref2_offset, radiance_offset, qa_offset]
            offsets = dict(zip(keys, array_offsets))
            arrays = {}
            for k, offset in offsets.items():
                indata.seek(offset - 1)
                newk = k.split('_')[-1]
                
                d = find_in_dict(label, k)
                unit = d['UNIT']
                lines = d['LINES']
                scaling_factor = d['SCALING_FACTOR']
                
                arr = np.fromstring(indata.read(lines * 296*2), dtype='>H').astype(np.float64)
                arr = arr.reshape(lines, -1)
                
                if isinstance(scaling_factor, float):
                    arr *= scaling_factor
                arrays[newk] = arr

            self.wavelengths = pd.Series(arrays['WAV'][0])

            self.spectra = {}
            for i in range(nrows):
                self.spectra[i] = pd.DataFrame(index = self.wavelengths,
                                        columns = ["Raw", "Highlands",
                                                 "Mare", "Radiance", "QA"])
                 
                self.spectra[i]['Raw'] = arrays['RAW'][i]
                self.spectra[i]['Highlands'] = arrays['REF1'][i]
                self.spectra[i]['Mare'] = arrays['REF2'][i]
                self.spectra[i]['Radiance'] = arrays['RAD'][i]
                self.spectra[i]['QA'] = arrays['QA'][i]
                #self.spectra[i] = pd.concat([raw, high, self.mare, rad, qa], axis=1)
                #self.spectra[i] = pd.concat([raw, high, self.mare, rad, qa], axis=1)
           
                if cleaned:
                    self.spectra[i] = self.spectra[i][self.spectra[i]['QA'] < qa_threshold]
            
                self.spectra[i] = Spectra(self.spectra[i])
# * Author:   David P. Mayer, [email protected]
# *
# * License: Public Domain
# *
# ******************************************************************************


import sys
import re
import fileinput
import pvl
from pvl._collections import Units as PUnits

inputlbl = sys.argv[1]
print(inputlbl)
isis3lbl = pvl.load(inputlbl)

# ## Debug only ##
# # Load the ISIS3 input from a file. Can be either detached label, or a cube with attached label
# # isis3lbl = pvl.load('Mercury_MESSENGER_mosaic_global_250m_2013.lbl')
# # isis3lbl = pvl.load('Lunar_Kaguya_MIMap_MineralDeconv_AbundanceSMFe_50N50S.lbl')
# ################

# # TODO: Check that input contains some minimum required set of keywords before translating

# Some keyword value pairs that should always appear at the top of the PDS3 label
# The value of LABEL_REVISION_NOTE should be modified to suit the user's needs
pds3toplevel = """PDS_VERSION_ID = PDS3
DD_VERSION_ID = PDSCAT1R100
LABEL_REVISION_NOTE = \"2017-05-01, David P. Mayer (USGS), initial PDS3 label pointing to GeoTIFF;\"
RECORD_TYPE = FIXED_LENGTH
Example #54
0
    def __init__(self, input_data, cleaned=True, qa_threshold=2000):
        """
        Read the .spc file, parse the label, and extract the spectra

        Parameters
        ----------

        input_data : string
                     The PATH to the input .spc file

        cleaned : boolean
                  If True, mask the data based on the QA array.

        nspectra : int
                   The number of spectra in the given data file

        qa_threshold : int
                       The threshold value over which observations are masked as noise
                       if cleaned is True.
        """

        label_dtype_map = {'IEEE_REAL':'f',
                        'MSB_INTEGER':'i',
                        'MSB_UNSIGNED_INTEGER':'u'}


        label = pvl.load(input_data)
        self.label = label
        with open(input_data, 'rb') as indata:
            # Extract and handle the ancillary data
            ancillary_data = find_in_dict(label, "ANCILLARY_AND_SUPPLEMENT_DATA")
            self.nspectra = nrows = ancillary_data['ROWS']
            ncols = ancillary_data['COLUMNS']
            rowbytes = ancillary_data['ROW_BYTES']

            columns = []
            bytelengths = []
            datatypes = []
            ancillary_data_offset = find_in_dict(label, "^ANCILLARY_AND_SUPPLEMENT_DATA").value
            indata.seek(ancillary_data_offset - 1)
            for i in ancillary_data.items():
                if i[0] == 'COLUMN':
                    entry = i[1]
                    # Level 2B2 PVL has entries with 0 bytes, e.g. omitted.
                    if entry['BYTES'] > 0:
                        columns.append(str(entry['NAME']))
                        datatypes.append(label_dtype_map[entry['DATA_TYPE']])
                        bytelengths.append(entry['BYTES'])
                    else:
                        ncols -= 1
            strbytes = map(str, bytelengths)
            rowdtype = list(zip(columns, map(''.join, zip(['>'] * ncols, datatypes, strbytes))))
            d = np.fromstring(indata.read(rowbytes * nrows), dtype=rowdtype,
                              count=nrows)
            self.ancillary_data = pd.DataFrame(d, columns=columns,
                                               index=np.arange(nrows))

            assert(ncols == len(columns))

            keys = []
            array_offsets = []
            for d in ['WAV', 'RAW', 'REF', 'REF1', 'REF2', 'DAR', 'QA']:
                search_key = '^SP_SPECTRUM_{}'.format(d)
                result = find_in_dict(label, search_key)
                if result:
                    array_offsets.append(result.value)
                    keys.append('SP_SPECTRUM_{}'.format(d))

            offsets = dict(zip(keys, array_offsets))

            arrays = {}
            for k, offset in offsets.items():
                indata.seek(offset - 1)
                newk = k.split('_')[-1]

                d = find_in_dict(label, k)
                unit = d['UNIT']
                lines = d['LINES']
                scaling_factor = d['SCALING_FACTOR']

                arr = np.fromstring(indata.read(lines * 296*2), dtype='>H').astype(np.float64)
                arr = arr.reshape(lines, -1)

                # If the data is scaled, apply the scaling factor
                if isinstance(scaling_factor, float):
                    arr *= scaling_factor

                arrays[newk] = arr

            self.wavelengths = pd.Series(arrays['WAV'][0])

            self.spectra = {}
            for i in range(nrows):
                self.spectra[i] = pd.DataFrame(index=self.wavelengths)
                for k in keys:
                    k = k.split('_')[-1]
                    if k == 'WAV':
                        continue
                    self.spectra[i][k] = arrays[k][i]

                if cleaned:
                    self.spectra[i] = self.spectra[i][self.spectra[i]['QA'] < qa_threshold]

            self.spectra = pd.Panel(self.spectra)
    def __init__(self, input_data, label=None, cleaned=True, qa_threshold=2000):
        """
        Read the .spc file, parse the label, and extract the spectra

        Parameters
        ----------

        input_data : string
                     The PATH to the input .spc file

        label : string
                The PATH to an optional detached label associated with the .spc

        cleaned : boolean
                  If True, mask the data based on the QA array.

        nspectra : int
                   The number of spectra in the given data file

        qa_threshold : int
                       The threshold value over which observations are masked as noise
                       if cleaned is True.
        """

        label_dtype_map = {'IEEE_REAL':'f',
                        'MSB_INTEGER':'i',
                        'MSB_UNSIGNED_INTEGER':'u'}

        if label:
            label = pvl.load(label)
        else:
            label = pvl.load(input_data)
        self.label = label
        self.input_data = input_data
        with open(input_data, 'rb') as indata:
            # Extract and handle the ancillary data
            ancillary_data = find_in_dict(label, "ANCILLARY_AND_SUPPLEMENT_DATA")
            self.nspectra = nrows = ancillary_data['ROWS']
            ncols = ancillary_data['COLUMNS']
            rowbytes = ancillary_data['ROW_BYTES']

            columns = []
            bytelengths = []
            datatypes = []
            try:
                ancillary_data_offset = find_in_dict(self.label, "^ANCILLARY_AND_SUPPLEMENT_DATA").value
            except:
                ancillary_data_offset = find_in_dict(self.label, "^ANCILLARY_AND_SUPPLEMENT_DATA")[1].value
            indata.seek(ancillary_data_offset - 1)
            for i in ancillary_data.items():
                if i[0] == 'COLUMN':
                    entry = i[1]
                    # Level 2B2 PVL has entries with 0 bytes, e.g. omitted.
                    if entry['BYTES'] > 0:
                        columns.append(str(entry['NAME']))
                        datatypes.append(label_dtype_map[entry['DATA_TYPE']])
                        bytelengths.append(entry['BYTES'])
                    else:
                        ncols -= 1
            strbytes = map(str, bytelengths)
            rowdtype = list(zip(columns, map(''.join, zip(['>'] * ncols, datatypes, strbytes))))
            d = np.frombuffer(indata.read(rowbytes * nrows), dtype=rowdtype,
                              count=nrows)
            self.ancillary_data = pd.DataFrame(d, columns=columns,
                                               index=np.arange(nrows))
            keys = []
            vals = []
            for k, v in label.items():
                if k in ["ANCILLARY_AND_SUPPLEMENT_DATA", "L2D_RESULT_ARRAY",
                         "SP_SPECTRUM_QA", "SP_SPECTRUM_REF1", "SP_SPECTRUM_RAD",
                         "SP_SPECTRUM_REF2", "SP_SPECTRUM_RAW", "SP_SPECTRUM_WAV",
                         "^ANCILLARY_AND_SUPPLEMENT_DATA", "^SP_SPECTRUM_WAV",
                         "^SP_SPECTRUM_RAW", "^SP_SPECTRUM_REF2"," ^SP_SPECTRUM_RAD",
                         "^SP_SPECTRUM_REF1", "^SP_SPECTRUM_QA", "^L2D_RESULT_ARRAY",
                         "^SP_SPECTRUM_RAD"]:
                    continue
                if isinstance(v, pvl._collections.Units):
                    k = "{}_{}".format(k, v.units)
                    v = v.value
                keys.append(k)
                vals.append(v)
            
            vals = [vals] * len(self.ancillary_data)
            new_anc = pd.DataFrame(vals, index=self.ancillary_data.index, columns=keys)
            self.ancillary_data = self.ancillary_data.join(new_anc, how='inner')
            assert(ncols == len(columns))

            keys = []
            array_offsets = []
            for d in ['WAV', 'RAW', 'REF', 'REF1', 'REF2', 'DAR', 'QA', 'RAD']:
                search_key = '^SP_SPECTRUM_{}'.format(d)
                result = find_in_dict(label, search_key)
                if result:
                    try:
                        array_offsets.append(result.value)
                    except:
                        array_offsets.append(result[1].value) # 2C V3.0
                    keys.append('SP_SPECTRUM_{}'.format(d))

            offsets = dict(zip(keys, array_offsets))

            arrays = {}
            for k, offset in offsets.items():
                indata.seek(offset - 1)
                newk = k.split('_')[-1]

                d = find_in_dict(label, k)
                unit = d['UNIT']
                lines = d['LINES']
                scaling_factor = d['SCALING_FACTOR']

                arr = np.frombuffer(indata.read(lines * 296*2), dtype='>H').astype(np.float64)
                arr = arr.reshape(lines, -1)

                # If the data is scaled, apply the scaling factor
                if isinstance(scaling_factor, float):
                    arr *= scaling_factor

                arrays[newk] = arr

            self.wavelengths = pd.Series(arrays['WAV'][0])

            self.spectra = {}
            for i in range(nrows):
                self.spectra[i] = pd.DataFrame(index=self.wavelengths)
                for k in keys:
                    k = k.split('_')[-1]
                    if k == 'WAV':
                        continue
                    self.spectra[i][k] = arrays[k][i]

                if cleaned:
                    mask = self.spectra[i]['QA'] < qa_threshold
                    self.spectra[i] = self.spectra[i][mask]
            # If the spectra have been cleaned, the wavelength ids also need to be cleaned.
            if cleaned:
                self.wavelengths = self.wavelengths[mask.values].values

            dfs = [v for k, v in self.spectra.items()]
            self.spectra = pd.concat(dfs, axis=1, keys=range(nrows))
Example #56
0
 def _load_label(self, stream):
     return pvl.load(stream)
Example #57
0
def test_load_all_sample_labels():
    for filename in PDS_LABELS:
        label = pvl.load(filename)
        assert isinstance(label, Label)
Example #58
0
    def __init__(self, input_data, var_file = None, data_set=None):
        """
        Read the .spc file, parse the label, and extract the spectra

        Parameters
        ----------

        input_data : string
                     The PATH to the input .tab file

        """
        def expand_column(df, expand_column, columns): # pragma: no cover
            array = np.asarray([np.asarray(list(tup[0])) for tup in df[expand_column].as_matrix()], dtype=np.uint8)
            new_df = pd.concat([df, pd.DataFrame(array, columns=columns)], axis=1)
            del new_df[expand_column]
            return new_df

        def bolquality2arr(arr): # pragma: no cover
            bitarr = np.unpackbits(np.asarray(arr, dtype=np.uint8))
            lis = [(bitarr2int(bitarr[0:3]), bit2bool(bitarr[3:4]))]

            types = [('BOLOMETRIC_INERTIA_RATING', '>u1'), ('BOLOMETER_LAMP_ANOMALY', 'bool_')]
            arr = np.array(lis, dtype=types)
            return arr

        def obsquality2arr(arr): # pragma: no cover
            bitarr = np.unpackbits(np.asarray(arr, dtype=np.uint8))
            lis = [(bitarr2int(bitarr[0:2]), bitarr2int(bitarr[2:5]),
                    bitarr2int(bitarr[5:6]), bitarr2int(bitarr[6:7]),
                    bitarr2int(bitarr[7:8]), bitarr2int(bitarr[8:9]))]

            types = [('HGA_MOTION', '>u1'), ('SOLAR_PANEL_MOTION', '>u1'), ('ALGOR_PATCH', '>u1'),
                     ('IMC_PATCH', '>u1'), ('MOMENTUM_DESATURATION', '>u1'), ('EQUALIZATION_TABLE', '>u1')]
            arr = np.array(lis, dtype=types)
            return arr

        def obsclass2arr(arr): # pragma: no cover
            bitarr = np.unpackbits(np.asarray(arr, dtype=np.uint8))
            lis = [(bitarr2int(bitarr[0:3]), bitarr2int(bitarr[3:7]),
                    bitarr2int(bitarr[7:11]), bitarr2int(bitarr[11:13]),
                    bitarr2int(bitarr[13:14]), bitarr2int(bitarr[14:16]),
                    bitarr2int(bitarr[16:]))]

            types = [('MISSION_PHASE', '>u1'), ('INTENDED_TARGET', '>u1'), ('TES_SEQUENCE', '>u1'),
                     ('NEON_LAMP_STATUS', '>u1'), ('TIMING_ACCURACY', '>u1'), ('SPARE', '>u1'), ('CLASSIFICATION_VALUE', '>u2')]
            arr = np.array(lis, dtype=types)
            return arr

        def radquality2arr(arr): # pragma: no cover
            bitarr = np.unpackbits(np.asarray(arr, dtype=np.uint8))
            lis = [(bitarr2int(bitarr[0:1]), bitarr2int(bitarr[1:2]),
                    bitarr2int(bitarr[2:3]), bitarr2int(bitarr[3:5]),
                    bitarr2int(bitarr[5:7]), bitarr2int(bitarr[5:8]),
                    bitarr2int(bitarr[8:9]))]

            types = [('MAJOR_PHASE_INVERSION', '>u1'), ('ALGOR_RISK', '>u1'), ('CALIBRATION_FAILURE', '>u1'),
                     ('CALIBRATION_QUALITY', '>u1'), ('SPECTROMETER_NOISE', '>u1'), ('SPECTRAL_INERTIA_RATING', '>u1'),
                     ('DETECTOR_MASK_PROBLEM', '>u1')]
            arr = np.array(lis, dtype=types)
            return arr

        def atmquality2arr(arr): # pragma: no cover
            bitarr = np.unpackbits(np.asarray(arr, dtype=np.uint8))
            lis = [(bitarr2int(bitarr[0:2]), bitarr2int(bitarr[2:4]))]

            types = [('TEMPERATURE_PROFILE_RATING', '>u1'), ('ATMOSPHERIC_OPACITY_RATING', '>u1')]
            arr = np.array(lis, dtype=types)
            return arr

        def expand_column(df, expand_column, columns): # pragma: no cover
            array = np.asarray([np.asarray(list(tup[0])) for tup in df[expand_column].as_matrix()], dtype=np.uint8)
            new_df = pd.concat([df, pd.DataFrame(array, columns=columns)], axis=1)
            del new_df[expand_column]
            return new_df

        def bolquality2arr(arr): # pragma: no cover
            bitarr = np.unpackbits(np.asarray(arr, dtype=np.uint8))
            lis = [(bitarr2int(bitarr[0:3]), bit2bool(bitarr[3:4]))]

            types = [('BOLOMETRIC_INERTIA_RATING', '>u1'), ('BOLOMETER_LAMP_ANOMALY', 'bool_')]
            arr = np.array(lis, dtype=types)
            return arr

        def obsquality2arr(arr): # pragma: no cover
            bitarr = np.unpackbits(np.asarray(arr, dtype=np.uint8))
            lis = [(bitarr2int(bitarr[0:2]), bitarr2int(bitarr[2:5]),
                    bitarr2int(bitarr[5:6]), bitarr2int(bitarr[6:7]),
                    bitarr2int(bitarr[7:8]), bitarr2int(bitarr[8:9]))]

            types = [('HGA_MOTION', '>u1'), ('SOLAR_PANEL_MOTION', '>u1'), ('ALGOR_PATCH', '>u1'),
                     ('IMC_PATCH', '>u1'), ('MOMENTUM_DESATURATION', '>u1'), ('EQUALIZATION_TABLE', '>u1')]
            arr = np.array(lis, dtype=types)
            return arr

        def obsclass2arr(arr): # pragma: no cover
            bitarr = np.unpackbits(np.asarray(arr, dtype=np.uint8))
            lis = [(bitarr2int(bitarr[0:3]), bitarr2int(bitarr[3:7]),
                    bitarr2int(bitarr[7:11]), bitarr2int(bitarr[11:13]),
                    bitarr2int(bitarr[13:14]), bitarr2int(bitarr[14:16]),
                    bitarr2int(bitarr[16:]))]

            types = [('MISSION_PHASE', '>u1'), ('INTENDED_TARGET', '>u1'), ('TES_SEQUENCE', '>u1'),
                     ('NEON_LAMP_STATUS', '>u1'), ('TIMING_ACCURACY', '>u1'), ('SPARE', '>u1'), ('CLASSIFICATION_VALUE', '>u2')]
            arr = np.array(lis, dtype=types)
            return arr

        def radquality2arr(arr): # pragma: no cover
            bitarr = np.unpackbits(np.asarray(arr, dtype=np.uint8))
            lis = [(bitarr2int(bitarr[0:1]), bitarr2int(bitarr[1:2]),
                    bitarr2int(bitarr[2:3]), bitarr2int(bitarr[3:5]),
                    bitarr2int(bitarr[5:7]), bitarr2int(bitarr[5:8]),
                    bitarr2int(bitarr[8:9]))]

            types = [('MAJOR_PHASE_INVERSION', '>u1'), ('ALGOR_RISK', '>u1'), ('CALIBRATION_FAILURE', '>u1'),
                     ('CALIBRATION_QUALITY', '>u1'), ('SPECTROMETER_NOISE', '>u1'), ('SPECTRAL_INERTIA_RATING', '>u1'),
                     ('DETECTOR_MASK_PROBLEM', '>u1')]
            arr = np.array(lis, dtype=types)
            return arr

        def atmquality2arr(arr): # pragma: no cover
            bitarr = np.unpackbits(np.asarray(arr, dtype=np.uint8))
            lis = [(bitarr2int(bitarr[0:2]), bitarr2int(bitarr[2:4]))]

            types = [('TEMPERATURE_PROFILE_RATING', '>u1'), ('ATMOSPHERIC_OPACITY_RATING', '>u1')]
            arr = np.array(lis, dtype=types)
            return arr

        def bitarr2int(arr): # pragma: no cover
            arr = "".join(str(i) for i in arr)
            return np.uint8(int(arr,2))

        def bit2bool(bit): # pragma: no cover
            return np.bool_(bit)

        def expand_bitstrings(df, dataset): # pragma: no cover
            if dataset == 'BOL':
                quality_columns = ['ti_bol_rating', 'bol_ref_lamp']
                df['quality'] = df['quality'].apply(bolquality2arr)
                return expand_column(df, 'quality', quality_columns)

            elif dataset == 'OBS':
                quality_columns = ['hga_motion', 'pnl_motion', 'algor_patch', 'imc_patch',
                                   'momentum', 'equal_tab']
                class_columns = ['phase', 'type', 'sequence',
                                 'lamp_status', 'timing', 'spare', 'class_value']

                df['quality'] = df['quality'].apply(obsquality2arr)
                df['class'] = df['class'].apply(obsclass2arr)

                new_df = expand_column(df, 'quality', quality_columns)
                new_df = expand_column(new_df, 'class', class_columns)
                return new_df

            elif dataset == 'RAD':
                quality_columns = ['phase_inversion', 'algor_risk', 'calib_fail', 'calib_quality',
                                   'spect_noise', 'ti_spc_rating', 'det_mask_problem']

                df['quality'] = df['quality'].apply(radquality2arr)

                return expand_column(df, 'quality', quality_columns)

            elif dataset == 'ATM':
                quality_columns = ['atm_pt_rating', 'atm_opacity_rating']

                df['quality'] = df['quality'].apply(atmquality2arr)
                return expand_column(df, 'quality', quality_columns)

            else:
                return df

        if isinstance(input_data, pd.DataFrame):
            self.dataset = None
            if not data_set:
                for key in tes_columns.keys():
                    if len(set(tes_columns[key]).intersection(set(input_data.columns))) > 3 :
                        self.dataset = key
            else:
                self.dataset=data_set

            self.label = None
            self.data = input_data
            return

        self.label = pvl.load(input_data)
        nrecords = self.label['TABLE']['ROWS']
        nbytes_per_rec = self.label['RECORD_BYTES']
        data_start = self.label['LABEL_RECORDS'] * self.label['RECORD_BYTES']
        dataset = self.label['TABLE']['^STRUCTURE'].split('.')[0]
        self.dataset = dataset

        numpy_dtypes = tes_dtype_map
        columns = tes_columns
        scaling_factors = tes_scaling_factors

        with open(input_data, 'rb') as file:
            file.seek(data_start)
            buffer = file.read(nrecords*nbytes_per_rec)
            array = np.frombuffer(buffer, dtype=numpy_dtypes[dataset.upper()]).byteswap().newbyteorder()

        df = pd.DataFrame(data=array, columns=columns[dataset.upper()])

        # Read Radiance array if applicable
        if dataset.upper() == 'RAD': # pragma: no cover
            if not var_file:
                filename, file_extension = path.splitext(input_data)
                var_file = filename + ".var"

            with open(var_file, "rb") as var:
                buffer = var.read()
                def process_rad(index):
                    if index is -1:
                        return None

                    length = np.frombuffer(buffer[index:index+2], dtype='>u2')[0]
                    exp = np.frombuffer(buffer[index+2:index+4], dtype='>i2')[0]
                    scale = 2**(int(exp)-15)
                    radarr = np.frombuffer(buffer[index+4:index+4+length-2], dtype='>i2') * scale
                    if np.frombuffer(buffer[index+4+length-2:index+4+length], dtype='>u2')[0] != length:
                        warnings.warn("Last element did not match the length for file index {} in file {}".format(index, f))
                    return radarr

                df["raw_rad"] = df["raw_rad"].apply(process_rad)
                df["cal_rad"] = df["cal_rad"].apply(process_rad)

        # Apply scaling factors
        for column in scaling_factors[dataset]: # pragma: no cover
            def scale(x):
                 return np.multiply(x, scaling_factors[dataset][column])
            df[column] = df[column].apply(scale)

        df =  expand_bitstrings(df, dataset.upper())

        self.data =  df
Example #59
0
 def pvl_lbl(self):
     return pvl.load(str(self.path))
Example #60
0
 def _parse_label(self, stream):
     """Parses the label of an ISIS cube, returns a pvl module"""
     return pvl.load(stream)