# Module `ammosreader.PDW`

I store the information of a single PDW block.

Expand source code

    """I store the information of a single PDW block."""

    import struct
    import math
    import numpy as np

    class PDW():
        """
        I store information from a single ppdw data block.

        .. automethod:: __init__
        """

        @classmethod
        def from_bytes(cls, byte_string):
            """
            I create an instance of class PDW from data body (8 * 32 bits).

            :param byte_string: a byte string containing a single data body read from a ppdw file
            :type byte_string: byte string

            :return: an instance of class PDW with attributes set according to the data of a data body
            :rtype: PDW
            """
            assert(len(byte_string) == 32)

            parts = struct.unpack('<Q4s4s4s4s4s4s', byte_string)
            nanoseconds = (parts[0])
            time_of_arrival = np.datetime64(nanoseconds, 'ns')

            third_entry = bin(int.from_bytes(parts[1], byteorder='little'))
            padding = 32-len(str(third_entry)[2:])
            third_entry_bit_string = "0" * padding + str(third_entry)[2:]
            pdw_format_identifier = int(third_entry_bit_string[0:6], 2)
            center_frequency = int(third_entry_bit_string[5:32], 2)

            fourth_entry = bin(int.from_bytes(parts[2], byteorder='little'))
            padding = 32-len(str(fourth_entry)[2:])
            fourth_entry_bit_string = "0" * padding + str(fourth_entry)[2:]
            is_valid = bool(int(fourth_entry_bit_string[0]))
            is_pulse = bool(int(fourth_entry_bit_string[1]))
            level_unit = int(fourth_entry_bit_string[2])
            signal_start_missing = bool(int(fourth_entry_bit_string[3]))
            signal_end_missing = bool(int(fourth_entry_bit_string[4]))
            pulse_width = int(fourth_entry_bit_string[7:33], 2)

            fifth_entry = bin(int.from_bytes(parts[3], byteorder='little'))
            padding = 32-len(str(fifth_entry)[2:])
            fifth_entry_bit_string = "0" * padding + str(fifth_entry)[2:]
            frequency_shift_or_bandwidth = int(fifth_entry_bit_string[0:20], 2)
            # FIXME: You have to scale me to the range from -200.0 to 200.0 in 0.1 steps
            pulse_level_or_pulse_field_strength = math.ceil(int(fifth_entry_bit_string[20:32], 2)) / 10

            sixth_entry = bin(int.from_bytes(parts[4], byteorder='little'))
            padding = 32-len(str(sixth_entry)[2:])
            sixth_entry_bit_string = "0" * padding + str(sixth_entry)[2:]
            region_of_interest = bool(int(sixth_entry_bit_string[0]))
            # FIXME: You have to scale me to a range from 0.0 to 6.2 in steps of 0.1 - 6.3 means unknown
            azimuth_confidence = math.ceil(int(sixth_entry_bit_string[1:7], 2)) / 10
            modulations = {0: 'Unknown', 1: 'Unmodulated', 2: 'FM', 3: 'LFM', 4: 'PSK-2', 5: 'PSK-3', 6: 'PSK-4',
                           7: 'PSK-m', 8: 'NLFM', 9: 'SFM', 10: 'TFM', 11: 'Pulse too short'}
            modulation = modulations[int(sixth_entry_bit_string[7:12], 2)]
            sector = int(sixth_entry_bit_string[28:32], 2)

            seventh_entry = bin(int.from_bytes(parts[5], byteorder='little'))
            padding = 32-len(str(seventh_entry)[2:])
            seventh_entry_bit_string = "0" * padding + str(seventh_entry)[2:]
            polarities = {0: 'Horizontal/Unknown', 1: 'Vertical', 2: 'Counter clockwise', 3: 'Clockwise'}
            polarity = polarities[int(seventh_entry_bit_string[0:2], 2)]
            df_quality = int(seventh_entry_bit_string[2:9], 2)
            # FIXME: You have to scale me from -90 to 90 in 0.1 degree steps
            elevation = int(seventh_entry_bit_string[9:20], 2)
            # FIXME: You have to check me for a range from 0.0 to 359.9 in steps of 0.1
            azimuth = 0.1 * (int(seventh_entry_bit_string[20:32], 2))

            eighth_entry = bin(int.from_bytes(parts[5], byteorder='little'))
            padding = 32-len(str(eighth_entry)[2:])
            eighth_entry_bit_string = "0" * padding + str(eighth_entry)[2:]
            channel = int(eighth_entry_bit_string[0:4], 2)

            return PDW(time_of_arrival, pdw_format_identifier, center_frequency, is_valid, is_pulse, level_unit,
                       signal_start_missing, signal_end_missing, pulse_width, frequency_shift_or_bandwidth,
                       pulse_level_or_pulse_field_strength, region_of_interest, azimuth_confidence, modulation,
                       sector, polarity, df_quality, elevation, azimuth, channel)

        def __init__(self, time_of_arrival, pdw_format_identifier, center_frequency, is_valid, is_pulse,
                     level_unit, signal_start_missing, signal_end_missing, pulse_width, frequency_shift_or_bandwidth,
                     pulse_level_or_pulse_field_strength, region_of_interest, azimuth_confidence, modulation,
                     sector, polarity, df_quality, elevation, azimuth, channel):
            r"""
            I return an instance of an Pulse Data word.

            :param time_of_arrival: nanoseconds since 1970-01-01 00:00:00
            :type time_of_arrival: Integer
            :param pdw_format: format code
            :type pdw_format: Integer
            :param center_frequency: center frequency in KHz
            :type center_frequency: Integer
            :param is_valid: flag to mark if pdw data body is valid
            :type is_valid: Boolean
            :param is_pulse: flag to mark if pdw data body contains a pulse or a continuous wave signal
            :type is_pulse: Boolean
            :param level_unit: 0 means dBµV - 1 means dBµV/m
            :type level_unit: Integer
            :param signal_start_missing: signal started before time of arrival
            :type signal_start_missing: Boolean
            :param signal_end_missing: signal stops after time of arrival
            :type signal_end_missing: Boolean
            :param pulse_width: pulse width in nanoseconds - Zero if no valid pulse detected
            :type pulse_width: Integer
            :param frequency_shift_or_bandwidth: Value in KHz - Value set to 1048575 means Unknown
            :type frequency_shift_or_bandwidth: Integer
            :param pulse_level_or_pulse_field_strength: Pulse level or Pulse Field Strength depending on level_unit \
             (-200.0...200.0) in 0.1 steps / minus 204.8 means no valid level detected
            :type pulse_level_or_pulse_field_strength: Float
            :param region_of_interest: Marks if signal is from region of interest
            :type region_of_interest: Boolean
            :param azimuth_confidence: degree in steps of 0.1 (0.0-6.2) / 6.3 means confidence unknown
            :type azimuth_confidence: Float
            :param modulation: type of modulation (e.g. PSK-2, PSK-4, FM etc.)
            :type modulation: String
            :param sector: reference antenna sector (0-15)
            :type sector: Integer
            :param polarity: Horizontal, Vertical, Clockwise, Counter clockwise
            :type polarity: String
            :param df_quality: Direction finding quality in percent (0-100) - Zero means unknown
            :type df_quality: Integer
            :param elevation: elevation of incoming signal (from -90 to 90 degree) in steps of 0.1 degree \
            minus 102.4 means unknown
            :type elevation: Float
            :param azimuth: azimuth of incoming signal (from 0 to 359.9 degree) in steps of 0.1 degree \
            plus 409.5 means unknown
            :type azimuth: Float
            :param channel: detecting channel (0-16) - Zero means unknown
            :type channel: Integer
            :return: An instance of class PDW with attributes set according to the data of a data body
            :rtype: PDW
            """
            self.time_of_arrival = time_of_arrival #
            self.pdw_format_identifier = pdw_format_identifier
            self.center_frequency = center_frequency #
            self.__is_valid = is_valid #
            self.is_pulse = is_pulse #
            self.level_unit = level_unit #
            self.signal_start_missing = signal_start_missing
            self.signal_end_missing = signal_end_missing
            self.pulse_width = pulse_width #
            self.frequency_shift_or_bandwidth = frequency_shift_or_bandwidth #
            self.pulse_level_or_pulse_field_strength = pulse_level_or_pulse_field_strength #
            self.region_of_interest = region_of_interest
            self.azimuth_confidence = azimuth_confidence
            self.modulation = modulation #
            self.sector = sector
            self.polarity = polarity
            self.df_quality = df_quality #
            self.elevation = elevation #
            self.azimuth = azimuth
            self.channel = channel #

        def __str__(self):
            """
            I return the string representation of myself.

            :rtype: str
            """
            output = ("Time of arrival: " + str(self.time_of_arrival) + "\n" +
                      "PDW Format identifier: " + str(self.pdw_format_identifier) + "\n" +
                      "Center frequency: " + str(self.center_frequency) + " KHz\n")

            if self.__is_valid:
                output += "Signal: Valid\n"
            else:
                output += "Signal: Invalid\n"

            if self.is_pulse:
                output += "Signal type: Pulse\n"
            else:
                output += "Signal type: Continuous wave\n"

            if self.level_unit == 1:
                output += "Pulse level: " + str(self.pulse_level_or_pulse_field_strength) + " dbµV\n"
            else:
                output += "Pulse field strength: " + str(self.pulse_level_or_pulse_field_strength) + " dbµV/meter\n"

            output += ("Pulse width: " + str(self.pulse_width) + " nanoseconds\n" +
                       "Frequency shift or bandwidth: " + str(self.frequency_shift_or_bandwidth) + " KHz\n")

            if self.region_of_interest:
                output += "Region of interest: Yes\n"
            else:
                output += "Region of interest: No\n"

            if self.azimuth_confidence == 6.3:
                output += "Azimuth confidence: Invalid\n"
            else:
                output += "Azimuth confidence: " + str(self.azimuth_confidence) + " degree\n"

            output += "Modulation: " + str(self.modulation) + "\n"

            if self.sector == 0:
                output += "Sector: Unknown\n"
            else:
                output += "Sector:" + str(self.sector) + "\n"

            output += "Polarity: " + str(self.polarity) + "\n"

            output += "DF quality: " + str(self.df_quality) + " %\n"

            if self.elevation == 1024:
                output += "Elevation: Unknown\n"
            else:
                output += "Elevation: " + str(self.elevation) + " degree\n"

            if self.azimuth == 409.5:
                output += "Azimuth: Unknown\n"
            else:
                output += "Azimuth: " + str(self.azimuth) + " degree\n"

            output += "Channel: " + str(self.channel) + "\n"

            return output

        def is_valid(self):
            return self.__is_valid

        def to_json(self):
            return {'time of arrival': self.time_of_arrival,
                    'FORMATIDENTIFIER': self.pdw_format_identifier,
                    'center frequency': self.center_frequency,
                    'VALID': self.__is_valid,
                    'PULSE': self.is_pulse,
                    'PULSELEVEL': self.pulse_level_or_pulse_field_strength,
                    'PULSEWIDTH': self.pulse_width,
                    'BANDWIDTH': self.frequency_shift_or_bandwidth,
                    'REGIONOFINTEREST': self.region_of_interest,
                    'AZIMUTHCONFIDENCE': self.azimuth_confidence,
                    'MODULATION': self.modulation,
                    'SECTOR': self.sector,
                    'POLARITY': self.polarity,
                    'DFQUALITY': self.df_quality,
                    'ELEVATION': self.elevation,
                    'AZIMUTH': self.azimuth,
                    'CHANNEL': self.channel
                    }

    if __name__ == '__main__':
        pass

## Classes

`class PDW (time_of_arrival, pdw_format_identifier, center_frequency, is_valid, is_pulse, level_unit, signal_start_missing, signal_end_missing, pulse_width, frequency_shift_or_bandwidth, pulse_level_or_pulse_field_strength, region_of_interest, azimuth_confidence, modulation, sector, polarity, df_quality, elevation, azimuth, channel)`

  I store information from a single ppdw data block.

  Automethod:init

  I return an instance of an Pulse Data word.

  :param time_of_arrival: nanoseconds since 1970-01-01 00:00:00 :type time_of_arrival: Integer :param pdw_format: format code :type pdw_format: Integer :param center_frequency: center frequency in KHz :type center_frequency: Integer :param is_valid: flag to mark if pdw data body is valid :type is_valid: Boolean :param is_pulse: flag to mark if pdw data body contains a pulse or a continuous wave signal :type is_pulse: Boolean :param level_unit: 0 means dBµV - 1 means dBµV/m :type level_unit: Integer :param signal_start_missing: signal started before time of arrival :type signal_start_missing: Boolean :param signal_end_missing: signal stops after time of arrival :type signal_end_missing: Boolean :param pulse_width: pulse width in nanoseconds - Zero if no valid pulse detected :type pulse_width: Integer :param frequency_shift_or_bandwidth: Value in KHz - Value set to 1048575 means Unknown :type frequency_shift_or_bandwidth: Integer :param pulse_level_or_pulse_field_strength: Pulse level or Pulse Field Strength depending on level_unit \ (-200.0…200.0) in 0.1 steps / minus 204.8 means no valid level detected :type pulse_level_or_pulse_field_strength: Float :param region_of_interest: Marks if signal is from region of interest :type region_of_interest: Boolean :param azimuth_confidence: degree in steps of 0.1 (0.0-6.2) / 6.3 means confidence unknown :type azimuth_confidence: Float :param modulation: type of modulation (e.g. PSK-2, PSK-4, FM etc.) :type modulation: String :param sector: reference antenna sector (0-15) :type sector: Integer :param polarity: Horizontal, Vertical, Clockwise, Counter clockwise :type polarity: String :param df_quality: Direction finding quality in percent (0-100) - Zero means unknown :type df_quality: Integer :param elevation: elevation of incoming signal (from -90 to 90 degree) in steps of 0.1 degree \ minus 102.4 means unknown :type elevation: Float :param azimuth: azimuth of incoming signal (from 0 to 359.9 degree) in steps of 0.1 degree \ plus 409.5 means unknown :type azimuth: Float :param channel: detecting channel (0-16) - Zero means unknown :type channel: Integer :return: An instance of class PDW with attributes set according to the data of a data body :rtype: PDW

  Expand source code

      class PDW():
          """
          I store information from a single ppdw data block.

          .. automethod:: __init__
          """

          @classmethod
          def from_bytes(cls, byte_string):
              """
              I create an instance of class PDW from data body (8 * 32 bits).

              :param byte_string: a byte string containing a single data body read from a ppdw file
              :type byte_string: byte string

              :return: an instance of class PDW with attributes set according to the data of a data body
              :rtype: PDW
              """
              assert(len(byte_string) == 32)

              parts = struct.unpack('<Q4s4s4s4s4s4s', byte_string)
              nanoseconds = (parts[0])
              time_of_arrival = np.datetime64(nanoseconds, 'ns')

              third_entry = bin(int.from_bytes(parts[1], byteorder='little'))
              padding = 32-len(str(third_entry)[2:])
              third_entry_bit_string = "0" * padding + str(third_entry)[2:]
              pdw_format_identifier = int(third_entry_bit_string[0:6], 2)
              center_frequency = int(third_entry_bit_string[5:32], 2)

              fourth_entry = bin(int.from_bytes(parts[2], byteorder='little'))
              padding = 32-len(str(fourth_entry)[2:])
              fourth_entry_bit_string = "0" * padding + str(fourth_entry)[2:]
              is_valid = bool(int(fourth_entry_bit_string[0]))
              is_pulse = bool(int(fourth_entry_bit_string[1]))
              level_unit = int(fourth_entry_bit_string[2])
              signal_start_missing = bool(int(fourth_entry_bit_string[3]))
              signal_end_missing = bool(int(fourth_entry_bit_string[4]))
              pulse_width = int(fourth_entry_bit_string[7:33], 2)

              fifth_entry = bin(int.from_bytes(parts[3], byteorder='little'))
              padding = 32-len(str(fifth_entry)[2:])
              fifth_entry_bit_string = "0" * padding + str(fifth_entry)[2:]
              frequency_shift_or_bandwidth = int(fifth_entry_bit_string[0:20], 2)
              # FIXME: You have to scale me to the range from -200.0 to 200.0 in 0.1 steps
              pulse_level_or_pulse_field_strength = math.ceil(int(fifth_entry_bit_string[20:32], 2)) / 10

              sixth_entry = bin(int.from_bytes(parts[4], byteorder='little'))
              padding = 32-len(str(sixth_entry)[2:])
              sixth_entry_bit_string = "0" * padding + str(sixth_entry)[2:]
              region_of_interest = bool(int(sixth_entry_bit_string[0]))
              # FIXME: You have to scale me to a range from 0.0 to 6.2 in steps of 0.1 - 6.3 means unknown
              azimuth_confidence = math.ceil(int(sixth_entry_bit_string[1:7], 2)) / 10
              modulations = {0: 'Unknown', 1: 'Unmodulated', 2: 'FM', 3: 'LFM', 4: 'PSK-2', 5: 'PSK-3', 6: 'PSK-4',
                             7: 'PSK-m', 8: 'NLFM', 9: 'SFM', 10: 'TFM', 11: 'Pulse too short'}
              modulation = modulations[int(sixth_entry_bit_string[7:12], 2)]
              sector = int(sixth_entry_bit_string[28:32], 2)

              seventh_entry = bin(int.from_bytes(parts[5], byteorder='little'))
              padding = 32-len(str(seventh_entry)[2:])
              seventh_entry_bit_string = "0" * padding + str(seventh_entry)[2:]
              polarities = {0: 'Horizontal/Unknown', 1: 'Vertical', 2: 'Counter clockwise', 3: 'Clockwise'}
              polarity = polarities[int(seventh_entry_bit_string[0:2], 2)]
              df_quality = int(seventh_entry_bit_string[2:9], 2)
              # FIXME: You have to scale me from -90 to 90 in 0.1 degree steps
              elevation = int(seventh_entry_bit_string[9:20], 2)
              # FIXME: You have to check me for a range from 0.0 to 359.9 in steps of 0.1
              azimuth = 0.1 * (int(seventh_entry_bit_string[20:32], 2))

              eighth_entry = bin(int.from_bytes(parts[5], byteorder='little'))
              padding = 32-len(str(eighth_entry)[2:])
              eighth_entry_bit_string = "0" * padding + str(eighth_entry)[2:]
              channel = int(eighth_entry_bit_string[0:4], 2)

              return PDW(time_of_arrival, pdw_format_identifier, center_frequency, is_valid, is_pulse, level_unit,
                         signal_start_missing, signal_end_missing, pulse_width, frequency_shift_or_bandwidth,
                         pulse_level_or_pulse_field_strength, region_of_interest, azimuth_confidence, modulation,
                         sector, polarity, df_quality, elevation, azimuth, channel)

          def __init__(self, time_of_arrival, pdw_format_identifier, center_frequency, is_valid, is_pulse,
                       level_unit, signal_start_missing, signal_end_missing, pulse_width, frequency_shift_or_bandwidth,
                       pulse_level_or_pulse_field_strength, region_of_interest, azimuth_confidence, modulation,
                       sector, polarity, df_quality, elevation, azimuth, channel):
              r"""
              I return an instance of an Pulse Data word.

              :param time_of_arrival: nanoseconds since 1970-01-01 00:00:00
              :type time_of_arrival: Integer
              :param pdw_format: format code
              :type pdw_format: Integer
              :param center_frequency: center frequency in KHz
              :type center_frequency: Integer
              :param is_valid: flag to mark if pdw data body is valid
              :type is_valid: Boolean
              :param is_pulse: flag to mark if pdw data body contains a pulse or a continuous wave signal
              :type is_pulse: Boolean
              :param level_unit: 0 means dBµV - 1 means dBµV/m
              :type level_unit: Integer
              :param signal_start_missing: signal started before time of arrival
              :type signal_start_missing: Boolean
              :param signal_end_missing: signal stops after time of arrival
              :type signal_end_missing: Boolean
              :param pulse_width: pulse width in nanoseconds - Zero if no valid pulse detected
              :type pulse_width: Integer
              :param frequency_shift_or_bandwidth: Value in KHz - Value set to 1048575 means Unknown
              :type frequency_shift_or_bandwidth: Integer
              :param pulse_level_or_pulse_field_strength: Pulse level or Pulse Field Strength depending on level_unit \
               (-200.0...200.0) in 0.1 steps / minus 204.8 means no valid level detected
              :type pulse_level_or_pulse_field_strength: Float
              :param region_of_interest: Marks if signal is from region of interest
              :type region_of_interest: Boolean
              :param azimuth_confidence: degree in steps of 0.1 (0.0-6.2) / 6.3 means confidence unknown
              :type azimuth_confidence: Float
              :param modulation: type of modulation (e.g. PSK-2, PSK-4, FM etc.)
              :type modulation: String
              :param sector: reference antenna sector (0-15)
              :type sector: Integer
              :param polarity: Horizontal, Vertical, Clockwise, Counter clockwise
              :type polarity: String
              :param df_quality: Direction finding quality in percent (0-100) - Zero means unknown
              :type df_quality: Integer
              :param elevation: elevation of incoming signal (from -90 to 90 degree) in steps of 0.1 degree \
              minus 102.4 means unknown
              :type elevation: Float
              :param azimuth: azimuth of incoming signal (from 0 to 359.9 degree) in steps of 0.1 degree \
              plus 409.5 means unknown
              :type azimuth: Float
              :param channel: detecting channel (0-16) - Zero means unknown
              :type channel: Integer
              :return: An instance of class PDW with attributes set according to the data of a data body
              :rtype: PDW
              """
              self.time_of_arrival = time_of_arrival #
              self.pdw_format_identifier = pdw_format_identifier
              self.center_frequency = center_frequency #
              self.__is_valid = is_valid #
              self.is_pulse = is_pulse #
              self.level_unit = level_unit #
              self.signal_start_missing = signal_start_missing
              self.signal_end_missing = signal_end_missing
              self.pulse_width = pulse_width #
              self.frequency_shift_or_bandwidth = frequency_shift_or_bandwidth #
              self.pulse_level_or_pulse_field_strength = pulse_level_or_pulse_field_strength #
              self.region_of_interest = region_of_interest
              self.azimuth_confidence = azimuth_confidence
              self.modulation = modulation #
              self.sector = sector
              self.polarity = polarity
              self.df_quality = df_quality #
              self.elevation = elevation #
              self.azimuth = azimuth
              self.channel = channel #

          def __str__(self):
              """
              I return the string representation of myself.

              :rtype: str
              """
              output = ("Time of arrival: " + str(self.time_of_arrival) + "\n" +
                        "PDW Format identifier: " + str(self.pdw_format_identifier) + "\n" +
                        "Center frequency: " + str(self.center_frequency) + " KHz\n")

              if self.__is_valid:
                  output += "Signal: Valid\n"
              else:
                  output += "Signal: Invalid\n"

              if self.is_pulse:
                  output += "Signal type: Pulse\n"
              else:
                  output += "Signal type: Continuous wave\n"

              if self.level_unit == 1:
                  output += "Pulse level: " + str(self.pulse_level_or_pulse_field_strength) + " dbµV\n"
              else:
                  output += "Pulse field strength: " + str(self.pulse_level_or_pulse_field_strength) + " dbµV/meter\n"

              output += ("Pulse width: " + str(self.pulse_width) + " nanoseconds\n" +
                         "Frequency shift or bandwidth: " + str(self.frequency_shift_or_bandwidth) + " KHz\n")

              if self.region_of_interest:
                  output += "Region of interest: Yes\n"
              else:
                  output += "Region of interest: No\n"

              if self.azimuth_confidence == 6.3:
                  output += "Azimuth confidence: Invalid\n"
              else:
                  output += "Azimuth confidence: " + str(self.azimuth_confidence) + " degree\n"

              output += "Modulation: " + str(self.modulation) + "\n"

              if self.sector == 0:
                  output += "Sector: Unknown\n"
              else:
                  output += "Sector:" + str(self.sector) + "\n"

              output += "Polarity: " + str(self.polarity) + "\n"

              output += "DF quality: " + str(self.df_quality) + " %\n"

              if self.elevation == 1024:
                  output += "Elevation: Unknown\n"
              else:
                  output += "Elevation: " + str(self.elevation) + " degree\n"

              if self.azimuth == 409.5:
                  output += "Azimuth: Unknown\n"
              else:
                  output += "Azimuth: " + str(self.azimuth) + " degree\n"

              output += "Channel: " + str(self.channel) + "\n"

              return output

          def is_valid(self):
              return self.__is_valid

          def to_json(self):
              return {'time of arrival': self.time_of_arrival,
                      'FORMATIDENTIFIER': self.pdw_format_identifier,
                      'center frequency': self.center_frequency,
                      'VALID': self.__is_valid,
                      'PULSE': self.is_pulse,
                      'PULSELEVEL': self.pulse_level_or_pulse_field_strength,
                      'PULSEWIDTH': self.pulse_width,
                      'BANDWIDTH': self.frequency_shift_or_bandwidth,
                      'REGIONOFINTEREST': self.region_of_interest,
                      'AZIMUTHCONFIDENCE': self.azimuth_confidence,
                      'MODULATION': self.modulation,
                      'SECTOR': self.sector,
                      'POLARITY': self.polarity,
                      'DFQUALITY': self.df_quality,
                      'ELEVATION': self.elevation,
                      'AZIMUTH': self.azimuth,
                      'CHANNEL': self.channel
                      }

  ### Static methods

  `def from_bytes(byte_string)`

    I create an instance of class PDW from data body (8 * 32 bits).

    :param byte_string: a byte string containing a single data body read from a ppdw file :type byte_string: byte string

    :return: an instance of class PDW with attributes set according to the data of a data body :rtype: PDW

    Expand source code

        @classmethod
        def from_bytes(cls, byte_string):
            """
            I create an instance of class PDW from data body (8 * 32 bits).

            :param byte_string: a byte string containing a single data body read from a ppdw file
            :type byte_string: byte string

            :return: an instance of class PDW with attributes set according to the data of a data body
            :rtype: PDW
            """
            assert(len(byte_string) == 32)

            parts = struct.unpack('<Q4s4s4s4s4s4s', byte_string)
            nanoseconds = (parts[0])
            time_of_arrival = np.datetime64(nanoseconds, 'ns')

            third_entry = bin(int.from_bytes(parts[1], byteorder='little'))
            padding = 32-len(str(third_entry)[2:])
            third_entry_bit_string = "0" * padding + str(third_entry)[2:]
            pdw_format_identifier = int(third_entry_bit_string[0:6], 2)
            center_frequency = int(third_entry_bit_string[5:32], 2)

            fourth_entry = bin(int.from_bytes(parts[2], byteorder='little'))
            padding = 32-len(str(fourth_entry)[2:])
            fourth_entry_bit_string = "0" * padding + str(fourth_entry)[2:]
            is_valid = bool(int(fourth_entry_bit_string[0]))
            is_pulse = bool(int(fourth_entry_bit_string[1]))
            level_unit = int(fourth_entry_bit_string[2])
            signal_start_missing = bool(int(fourth_entry_bit_string[3]))
            signal_end_missing = bool(int(fourth_entry_bit_string[4]))
            pulse_width = int(fourth_entry_bit_string[7:33], 2)

            fifth_entry = bin(int.from_bytes(parts[3], byteorder='little'))
            padding = 32-len(str(fifth_entry)[2:])
            fifth_entry_bit_string = "0" * padding + str(fifth_entry)[2:]
            frequency_shift_or_bandwidth = int(fifth_entry_bit_string[0:20], 2)
            # FIXME: You have to scale me to the range from -200.0 to 200.0 in 0.1 steps
            pulse_level_or_pulse_field_strength = math.ceil(int(fifth_entry_bit_string[20:32], 2)) / 10

            sixth_entry = bin(int.from_bytes(parts[4], byteorder='little'))
            padding = 32-len(str(sixth_entry)[2:])
            sixth_entry_bit_string = "0" * padding + str(sixth_entry)[2:]
            region_of_interest = bool(int(sixth_entry_bit_string[0]))
            # FIXME: You have to scale me to a range from 0.0 to 6.2 in steps of 0.1 - 6.3 means unknown
            azimuth_confidence = math.ceil(int(sixth_entry_bit_string[1:7], 2)) / 10
            modulations = {0: 'Unknown', 1: 'Unmodulated', 2: 'FM', 3: 'LFM', 4: 'PSK-2', 5: 'PSK-3', 6: 'PSK-4',
                           7: 'PSK-m', 8: 'NLFM', 9: 'SFM', 10: 'TFM', 11: 'Pulse too short'}
            modulation = modulations[int(sixth_entry_bit_string[7:12], 2)]
            sector = int(sixth_entry_bit_string[28:32], 2)

            seventh_entry = bin(int.from_bytes(parts[5], byteorder='little'))
            padding = 32-len(str(seventh_entry)[2:])
            seventh_entry_bit_string = "0" * padding + str(seventh_entry)[2:]
            polarities = {0: 'Horizontal/Unknown', 1: 'Vertical', 2: 'Counter clockwise', 3: 'Clockwise'}
            polarity = polarities[int(seventh_entry_bit_string[0:2], 2)]
            df_quality = int(seventh_entry_bit_string[2:9], 2)
            # FIXME: You have to scale me from -90 to 90 in 0.1 degree steps
            elevation = int(seventh_entry_bit_string[9:20], 2)
            # FIXME: You have to check me for a range from 0.0 to 359.9 in steps of 0.1
            azimuth = 0.1 * (int(seventh_entry_bit_string[20:32], 2))

            eighth_entry = bin(int.from_bytes(parts[5], byteorder='little'))
            padding = 32-len(str(eighth_entry)[2:])
            eighth_entry_bit_string = "0" * padding + str(eighth_entry)[2:]
            channel = int(eighth_entry_bit_string[0:4], 2)

            return PDW(time_of_arrival, pdw_format_identifier, center_frequency, is_valid, is_pulse, level_unit,
                       signal_start_missing, signal_end_missing, pulse_width, frequency_shift_or_bandwidth,
                       pulse_level_or_pulse_field_strength, region_of_interest, azimuth_confidence, modulation,
                       sector, polarity, df_quality, elevation, azimuth, channel)

  ### Methods

  `def is_valid(self)`
    Expand source code

        def is_valid(self):
            return self.__is_valid

  `def to_json(self)`
    Expand source code

        def to_json(self):
            return {'time of arrival': self.time_of_arrival,
                    'FORMATIDENTIFIER': self.pdw_format_identifier,
                    'center frequency': self.center_frequency,
                    'VALID': self.__is_valid,
                    'PULSE': self.is_pulse,
                    'PULSELEVEL': self.pulse_level_or_pulse_field_strength,
                    'PULSEWIDTH': self.pulse_width,
                    'BANDWIDTH': self.frequency_shift_or_bandwidth,
                    'REGIONOFINTEREST': self.region_of_interest,
                    'AZIMUTHCONFIDENCE': self.azimuth_confidence,
                    'MODULATION': self.modulation,
                    'SECTOR': self.sector,
                    'POLARITY': self.polarity,
                    'DFQUALITY': self.df_quality,
                    'ELEVATION': self.elevation,
                    'AZIMUTH': self.azimuth,
                    'CHANNEL': self.channel
                    }