Extracts header part from TAF/METAR string and populates header dict

        Args:
            TAF/METAR report string

        Raises:
            MalformedTAF: An error parsing the report

        Returns:
            Header dictionary

def _init_header(self, string):
        """ Extracts header part from TAF/METAR string and populates header dict

        Args:
            TAF/METAR report string

        Raises:
            MalformedTAF: An error parsing the report

        Returns:
            Header dictionary
        """

        taf_header_pattern = """
            ^
            (TAF)?    # TAF header (at times missing or duplicate)
            \s*
            (?P<type> (COR|AMD|AMD\sCOR|COR\sAMD|RTD)){0,1}

            \s* # There may or may not be space as COR/AMD/RTD is optional
            (?P<icao_code> [A-Z]{4}) # Station ICAO code

            \s* # at some aerodromes does not appear
            (?P<origin_date> \d{0,2}) # at some aerodromes does not appear
            (?P<origin_hours> \d{0,2}) # at some aerodromes does not appear
            (?P<origin_minutes> \d{0,2}) # at some aerodromes does not appear
            Z? # Zulu time (UTC, that is) # at some aerodromes does not appear

            \s*
            (?P<valid_from_date> \d{0,2})
            (?P<valid_from_hours> \d{0,2})
            /
            (?P<valid_till_date> \d{0,2})
            (?P<valid_till_hours> \d{0,2})
        """

        metar_header_pattern = """
            ^
            (METAR)?    # METAR header (at times missing or duplicate)
            \s*
            (?P<icao_code> [A-Z]{4}) # Station ICAO code

            \s* # at some aerodromes does not appear
            (?P<origin_date> \d{0,2}) # at some aerodromes does not appear
            (?P<origin_hours> \d{0,2}) # at some aerodromes does not appear
            (?P<origin_minutes> \d{0,2}) # at some aerodromes does not appear
            Z? # Zulu time (UTC, that is) # at some aerodromes does not appear
            \s+
            (?P<type> (COR){0,1}) # Corrected # TODO: Any other values possible?
        """

        header_taf = re.match(taf_header_pattern, string, re.VERBOSE)
        header_metar = re.match(metar_header_pattern, string, re.VERBOSE)

        # The difference between a METAR and TAF header isn't that big
        # so it's likely to get both regex to match. TAF is a bit more specific so if
        # both regex match then we're most likely dealing with a TAF string.
        if header_taf:
            header_dict = header_taf.groupdict()
            header_dict['form'] = 'taf'
        elif header_metar:
            header_dict = header_metar.groupdict()
            header_dict['form'] = 'metar'
        else:
            raise MalformedTAF("No valid TAF/METAR header found")

        return header_dict