Exemple #1
0
    def analyze(self, paths, filename_only=False):
        inpath = paths[0]
        name_attrs = self.parse_filename(inpath)

        properties = Struct()

        core = properties.core = Struct()
        core.product_name = os.path.splitext(os.path.basename(inpath))[0]
        core.creation_date = datetime.strptime(name_attrs['creation_date'],
                                               "%Y%m%dT%H%M%S")
        if name_attrs['validity_start'] == "00000000T000000":
            core.validity_start = datetime.min
        else:
            core.validity_start = datetime.strptime(
                name_attrs['validity_start'], "%Y%m%dT%H%M%S")
        if name_attrs['validity_stop'] == "99999999T999999":
            core.validity_stop = datetime.max
        else:
            core.validity_stop = datetime.strptime(name_attrs['validity_stop'],
                                                   "%Y%m%dT%H%M%S")

        s5p = properties.s5p = Struct()
        s5p.file_class = name_attrs['file_class']
        s5p.file_type = name_attrs['file_type']

        return properties
Exemple #2
0
    def analyze(self, paths, filename_only=False):
        inpath = paths[0]
        name_attrs = self.parse_filename(inpath)

        properties = Struct()

        core = properties.core = Struct()
        core.product_name = os.path.splitext(os.path.basename(inpath))[0]
        core.creation_date = datetime.strptime(name_attrs['creation_date'],
                                               "%Y%m%dT%H%M%S")
        core.validity_start = datetime.strptime(name_attrs['validity_start'],
                                                "%Y%m%dT%H%M%S")
        core.validity_stop = datetime.strptime(name_attrs['validity_stop'],
                                               "%Y%m%dT%H%M%S")
        if not filename_only:
            core.footprint = get_footprint(inpath)

        s5p = properties.s5p = Struct()
        s5p.file_class = name_attrs['file_class']
        s5p.file_type = name_attrs['file_type']
        s5p.orbit = int(name_attrs['orbit'])
        s5p.collection = int(name_attrs['collection'])
        s5p.processor_version = int(name_attrs['processor_version'])

        return properties
Exemple #3
0
 def _unpack_namespace_properties(self, namespace, description, values):
     unpacked_properties = Struct()
     schema = self._namespace_schema(namespace)
     for property, value in zip(description, values):
         if value is not None or not schema.is_optional(property):
             unpacked_properties[property] = value
     return unpacked_properties
Exemple #4
0
    def _unpack_product_properties(self, description, values):
        unpacked_properties, start = Struct(), 0
        for ns_name, ns_description in description:
            end = start + len(ns_description)

            # A value of None for the uuid field of namespaces other than the core namespace indicates the namespace is
            # not defined for the product under consideration. In this case, the entire namespace will be skipped.
            # Otherwise, only the uuid field is skipped, as it is an implementation detail (foreign key) and it is not
            # part of the namespace itself.
            #
            if ns_name != "core":
                assert (ns_description[0] == "uuid")
                if values[start] is None:
                    # Skip the entire namespace.
                    start = end
                    continue

                # Skip the uuid field.
                start += 1
                ns_description = ns_description[1:]

            unpacked_ns_properties = self._unpack_namespace_properties(
                ns_name, ns_description, values[start:end])
            self._validate_namespace_properties(ns_name,
                                                unpacked_ns_properties)
            unpacked_properties[ns_name] = unpacked_ns_properties
            start = end

        return unpacked_properties
Exemple #5
0
    def analyze(self, paths, filename_only=False):
        inpath = paths[0]
        name_attrs = self.parse_filename(inpath)

        properties = Struct()

        core = properties.core = Struct()
        core.product_name = os.path.splitext(os.path.basename(inpath))[0]
        core.validity_start = datetime.strptime(name_attrs['validity_start'],
                                                "%Y%m%d")
        core.validity_stop = core.validity_start + timedelta(days=1)
        core.creation_date = core.validity_start

        s5p = properties.s5p = Struct()
        s5p.file_class = "OPER"
        s5p.file_type = "AUX_NISE__"

        return properties
Exemple #6
0
 def _unpack_namespace_properties(self, namespace, description, values):
     unpacked_properties = Struct()
     schema = self._namespace_schema(namespace)
     for identifier, value in zip(description, values):
         if value is not None or not schema.is_optional(identifier):
             if issubclass(schema[identifier], JSON):
                 value = json.loads(value)
             unpacked_properties[identifier] = value
     return unpacked_properties
Exemple #7
0
    def _unpack_namespace_properties(self, namespace, description, values):
        unpacked_properties = Struct()
        schema = self._namespace_schema(namespace)
        for identifier, value in zip(description, values):
            # We may get unicode from the (psycopg2) connection
            # if, possibly by a third party, the UNICODE adapter is loaded.
            # Muninn assumes strs
            if is_python2_unicode(value):
                value = value.encode(self._connection.encoding)

            if value is not None or not schema.is_optional(identifier):
                unpacked_properties[identifier] = value
        return unpacked_properties
def get_core_properties(product_type, ecmwfmars, levtype_options=None):
    date = datetime.datetime.strptime(ecmwfmars.date.replace('-', ''),
                                      "%Y%m%d")
    time = ecmwfmars.time.replace(':', '')
    if len(time) >= 2:
        if len(time) >= 4:
            date += datetime.timedelta(hours=int(time[0:2]),
                                       minutes=int(time[2:4]))
        else:
            date += datetime.timedelta(hours=int(time[0:2]))
    core = Struct()
    core.uuid = Archive.generate_uuid()
    core.active = True
    core.product_type = product_type
    core.product_name = "%s_%s_%s_%s_%s_%s" % (
        product_type, ecmwfmars.marsclass, ecmwfmars.stream, ecmwfmars.expver,
        ecmwfmars.type, date.strftime("%Y%m%dT%H%M%S"))
    if 'step' in ecmwfmars:
        core.product_name += "_%03d" % (ecmwfmars.step, )
    core.physical_name = "%s.grib" % (core.product_name, )
    core.validity_start = date
    if 'step' in ecmwfmars:
        core.validity_start += datetime.timedelta(hours=ecmwfmars.step)
    core.validity_stop = core.validity_start
    # the creation date is set to the base time of the model
    core.creation_date = date
    if levtype_options:
        core.remote_url = get_remote_url(core.physical_name, ecmwfmars,
                                         levtype_options)
    return core
def extract_grib_metadata(gribfile):
    """
      this will return a tuple containing:
        - ecmwfmars properties struct
        - levtype_options struct (see set_remote_url())
    """
    import coda

    @contextlib.contextmanager
    def coda_open(filename):
        coda_handle = coda.open(filename)
        try:
            yield coda_handle
        finally:
            coda.close(coda_handle)

    ecmwfmars = Struct()
    levtype_options = {}  # TODO: add extraction of levtype_options

    with coda_open(gribfile) as coda_handle:
        cursor = coda.Cursor()
        coda.cursor_set_product(cursor, coda_handle)
        num_messages = coda.cursor_get_num_elements(cursor)
        coda.cursor_goto_first_array_element(cursor)
        for i in range(num_messages):
            index = coda.cursor_get_available_union_field_index(cursor)
            coda.cursor_goto_record_field_by_index(cursor, index)
            step = 0
            if index == 0:
                # grib1
                centuryOfReferenceTimeOfData = coda.fetch(
                    cursor, "centuryOfReferenceTimeOfData")
                yearOfCentury = coda.fetch(cursor, "yearOfCentury")
                month = coda.fetch(cursor, "month")
                day = coda.fetch(cursor, "day")
                date = "%02d%02d-%02d-%02d" % (centuryOfReferenceTimeOfData -
                                               1, yearOfCentury, month, day)
                hour = coda.fetch(cursor, "hour")
                minute = coda.fetch(cursor, "minute")
                time = "%02d:%02d:00" % (hour, minute)
                unitOfTimeRange = coda.fetch(cursor, "unitOfTimeRange")
                if unitOfTimeRange != 0:
                    P1 = coda.fetch(cursor, "P1")
                    if unitOfTimeRange == 1:
                        step = P1
                    elif unitOfTimeRange == 2:
                        step = 24 * P1
                    elif unitOfTimeRange == 10:
                        step = 3 * P1
                    elif unitOfTimeRange == 11:
                        step = 6 * P1
                    elif unitOfTimeRange == 13:
                        step = 12 * P1
                    else:
                        raise Error("unsupported unitOfTimeRange: %d" %
                                    (unitOfTimeRange, ))
                local = coda.fetch(cursor, "local")
                try:
                    local = local[1:9].tobytes()
                except AttributeError:
                    # workaround for older numpy versions
                    local = local[1:9].tostring()
                marsclass, marstype, stream, expver = struct.unpack(
                    '>BBH4s', local)
            else:
                # grib2
                year = coda.fetch(cursor, "year")
                month = coda.fetch(cursor, "month")
                day = coda.fetch(cursor, "day")
                date = "%04d-%02d-%02d" % (year, month, day)
                hour = coda.fetch(cursor, "hour")
                minute = coda.fetch(cursor, "minute")
                second = coda.fetch(cursor, "second")
                time = "%02d:%02d:%02d" % (hour, minute, second)
                significanceOfReferenceTime = coda.fetch(
                    cursor, "significanceOfReferenceTime")
                local = coda.fetch(cursor, "local[0]")
                try:
                    local = local[2:12].tobytes()
                except AttributeError:
                    # workaround for older numpy versions
                    local = local[2:12].tostring()
                marsclass, marstype, stream, expver = struct.unpack(
                    '>HHH4s', local)
                coda.cursor_goto_record_field_by_name(cursor, "data")
                num_data = coda.cursor_get_num_elements(cursor)
                coda.cursor_goto_first_array_element(cursor)
                prev_step = None
                for j in range(num_data):
                    forecastTime = coda.fetch(cursor, "forecastTime")
                    if forecastTime != 0:
                        indicatorOfUnitOfTimeRange = coda.fetch(
                            cursor, "indicatorOfUnitOfTimeRange")
                        if indicatorOfUnitOfTimeRange == 0:
                            # minutes
                            step = 60 * forecastTime
                        elif indicatorOfUnitOfTimeRange == 1:
                            # hours
                            step = 60 * 60 * forecastTime
                        elif indicatorOfUnitOfTimeRange == 2:
                            # days
                            step = 24 * 60 * 60 * forecastTime
                        elif indicatorOfUnitOfTimeRange == 10:
                            # 3 hours
                            step = 3 * 60 * 60 * forecastTime
                        elif indicatorOfUnitOfTimeRange == 11:
                            # 6 hours
                            step = 6 * 60 * 60 * forecastTime
                        elif indicatorOfUnitOfTimeRange == 12:
                            # 12 hours
                            step = 12 * 60 * 60 * forecastTime
                        elif indicatorOfUnitOfTimeRange == 13:
                            # seconds
                            step = forecastTime
                        step = int(step / 3600.)  # convert seconds to hours
                        if prev_step is None:
                            prev_step = step
                        elif step != prev_step:
                            raise Error(
                                "not all data has the same 'step' time (%d) (%d)"
                                % (step, prev_step))
                    if j < num_data - 1:
                        coda.cursor_goto_next_array_element(cursor)
                coda.cursor_goto_parent(cursor)
                coda.cursor_goto_parent(cursor)
            if marsclass not in MARSCLASSES:
                raise Error("unsupported MARS class (%d)" % (marsclass, ))
            marsclass = MARSCLASSES[marsclass]
            if marstype not in MARSTYPES:
                raise Error("unsupported MARS type (%d)" % (marstype, ))
            marstype = MARSTYPES[marstype]
            if stream not in MARSSTREAMS:
                raise Error("unsupported MARS stream (%d)" % (stream, ))
            stream = MARSSTREAMS[stream]
            if 'date' in ecmwfmars:
                if date != ecmwfmars.date:
                    raise Error("not all data is for the same date (%s) (%s)" %
                                (date, ecmwfmars.date))
                if time != ecmwfmars.time:
                    raise Error("not all data is for the same time (%s) (%s)" %
                                (time, ecmwfmars.time))
                if step != 0:
                    if 'step' in ecmwfmars:
                        if step != ecmwfmars.step:
                            raise Error(
                                "not all data has the same 'step' time (%d) (%d)"
                                % (step, ecmwfmars.step))
                    else:
                        raise Error("not all data has the same 'step' time")
                else:
                    if 'step' in ecmwfmars and ecmwfmars.step != 0:
                        raise Error("not all data has the same 'step' time")
                if marsclass != ecmwfmars.marsclass:
                    raise Error(
                        "not all data has the same MARS class (%s) (%s)" %
                        (marsclass, ecmwfmars.marsclass))
                if marstype != ecmwfmars.type:
                    raise Error(
                        "not all data has the same MARS type (%s) (%s)" %
                        (marstype, ecmwfmars.type))
                if stream != ecmwfmars.stream:
                    raise Error(
                        "not all data has the same MARS stream (%s) (%s)" %
                        (stream, ecmwfmars.stream))
                if expver != ecmwfmars.expver:
                    raise Error(
                        "not all data has the same MARS experiment version (%s) (%s)"
                        % (expver, ecmwfmars.expver))
            else:
                ecmwfmars.date = date
                ecmwfmars.time = time
                if step != 0:
                    ecmwfmars.step = step
                ecmwfmars.marsclass = marsclass
                ecmwfmars.type = marstype
                ecmwfmars.stream = stream
                ecmwfmars.expver = expver
                if (marsclass, stream, expver, marstype) in PUBLIC_DATASETS:
                    ecmwfmars.dataset = PUBLIC_DATASETS[(marsclass, stream,
                                                         expver, marstype)]
            coda.cursor_goto_parent(cursor)
            if i < num_messages - 1:
                coda.cursor_goto_next_array_element(cursor)

    return ecmwfmars, levtype_options