Beispiel #1
0
    def __init__(self,
                 satellite_configuration,
                 groundstation_configuration,
                 channel_configuration,
                 monte_carlo=False,
                 warn=True):

        # store the parameters internally
        self.satellite_configuration = satellite_configuration
        self.groundstation_configuration = groundstation_configuration
        self.channel_configuration = channel_configuration
        self.monte_carlo = monte_carlo
        self.warn = warn

        # if we're doing Monte-Carlo we need to choose an elevation to use
        if self.monte_carlo:

            distribution = channel_configuration['statistical']['geometry'][
                'elevation']

            assert distribution[0] == 'Uniform'

            minimum_elevation = float(distribution[1][0])
            maximum_elevation = float(distribution[1][1])

            self.elevation = (maximum_elevation - minimum_elevation
                              ) * random.random() + minimum_elevation

        else:
            self.elevation = channel_configuration['nominal']['geometry'][
                'elevation']

        # set the components
        self.satellite_init()
        self.groundstation_init()
        self.channel_init()

        # defaults to DVB-S2X
        self.modulation = pylink.Modulation()

        # form the downlink signal chain
        self.downlink = pylink.DAGModel([
            self.geometry, self.gs_rx_antenna, self.sat_transmitter,
            self.sat_tx_antenna, self.gs_receiver, self.downlink_channel,
            self.rx_interconnect, self.tx_interconnect, self.modulation,
            pylink.LinkBudget(name='Downlink', is_downlink=True)
        ])

        # form the downlink signal chain
        self.uplink = pylink.DAGModel([
            self.geometry, self.sat_rx_antenna, self.sat_receiver,
            self.gs_transmitter, self.gs_tx_antenna, self.uplink_channel,
            pylink.LinkBudget(name='Uplink', is_downlink=False)
        ])
Beispiel #2
0
    def test_loop_induction(self):
        """Ensures that a loop-inducing calculation can be made

        A -> B -> C -> D -> B

        C is a member of set {1, 2, 3}
        """
        def f_A(m):
            return m.B

        def f_B(m):
            return m.C

        def f_C(m):
            e = m.enum

            retval = -1

            for v in m.C_opt:
                m.override(e.C, v)
                b = m.cached_calculate(e.B, clear_stack=True)
                m.revert(e.C)
                retval = max(retval, b)

            return retval

        def f_D(m):
            return m.B

        def f_C_opt(m):
            return [1, 2, 3]

        m = pylink.DAGModel(A=f_A, B=f_B, C=f_C, D=f_D, C_opt=f_C_opt)

        assert m.A == 3
Beispiel #3
0
    def test_loop_detection(self):
        def __a(model):
            return model.b

        def __b(model):
            return model.c

        def __c(model):
            return model.d

        def __d(model):
            return model.e

        def __e(model):
            return model.b

        # a -> b -> c -> d -> e
        #      ^              |
        #      |              |
        #      +--------------+

        m = pylink.DAGModel(a=__a, b=__b, c=__c, d=__d, e=__e)

        with pytest.raises(pylink.LoopException):
            m.a
Beispiel #4
0
    def test_basic_override(self):

        m = pylink.DAGModel(A=42)
        e = m.enum

        assert m.A == 42
        m.override(e.A, 41)
        assert m.A == 41
Beispiel #5
0
    def test_basic_tribute(self):
        a = TributeA()
        b = TributeB()
        m = pylink.DAGModel([a, b])

        assert 1 == m.a1
        assert 2 == m.a2
        assert 1 == m.b1
        assert 2 == m.b2
Beispiel #6
0
    def test_basic_value(self):
        def __a(model):
            return model.b

        def __b(model):
            return 42

        m = pylink.DAGModel(a=__a, b=__b)
        assert 42 == m.a
Beispiel #7
0
def model():
    return pylink.DAGModel([pylink.Geometry(),
                            pylink.Antenna(is_rx=True),
                            pylink.Interconnect(is_rx=True),
                            pylink.Receiver(),
                            pylink.Transmitter(),
                            pylink.Interconnect(is_rx=False),
                            pylink.Antenna(is_rx=False),
                            pylink.Channel(),
                            pylink.Modulation(name='QPSK', perf=perf),
                            pylink.LinkBudget()])
Beispiel #8
0
    def test_static_revert_error(self):
        """Ensure a revert of a static node throws an error.
        """

        m = pylink.DAGModel(A=42)
        e = m.enum

        assert m.A == 42
        m.override(e.A, 41)
        assert m.A == 41
        with pytest.raises(AttributeError):
            m.revert(e.A)
Beispiel #9
0
    def test_basic_cache(self):
        self._state_a = 0

        f_A = self._wrap_func(self._assert_on_second,
                              state_var='_state_a',
                              retval='A')

        m = pylink.DAGModel(A=f_A)
        e = m.enum

        m.A
        assert 1 == self._state_a, "A was not calculated"

        m.A
        assert 1 == self._state_a, "A was recalculated"
Beispiel #10
0
def model():
    fed_married_joint = {
        0: 0.1,
        19750: 0.12,
        80250: 0.22,
        171050: 0.24,
        326600: 0.32,
        414700: 0.35,
        622050: 0.37
    }

    ca_married = {
        0: 0.01,
        17618: 0.02,
        41766: 0.04,
        65920: 0.06,
        91506: 0.08,
        115648: 0.093,
        590746: 0.103,
        708890: 0.113,
        1181484: 0.123,
        1999999: 0.133
    }

    return pylink.DAGModel(
        [
            deathAnd.Taxes(),
            anAwkward.Position([]),
            myMeager.Income(),
        ], **{
            'palantir_401k_usd': 0,
            'fed_tax_table': fed_married_joint,
            'state_tax_table': ca_married,
            'amt_exemption_rolloff_threshhold_usd': 1036800,
            'amt_exemption_base_usd': 113400,
            'palantir_fsa_usd': 0,
            'palantir_drca_usd': 0,
            'iso_exercise_income_usd': 0,
            'ext_amt_income_usd': 0,
            'reg_income_usd': 0,
            'ipo_price_usd': 1,
            'fed_std_deduction_usd': 1,
            'state_std_deduction_usd': 1,
            'query_date': '1/10/10',
        })
Beispiel #11
0
    def update_gs_rx_antenna_gain(self, gain):

        # create new antenna
        self.gs_rx_antenna = pylink.Antenna(
            gain=gain,
            pattern=self.sampler(self.groundstation_configuration,
                                 ['rx', 'antenna', 'pattern']),
            polarization=self.groundstation_configuration['nominal']['rx']
            ['antenna']['polarization'],
            is_rx=True,
            tracking=self.groundstation_configuration['nominal']['rx']
            ['antenna']['tracking'],
            pointing_loss_db=self.sampler(self.groundstation_configuration,
                                          ['rx', 'antenna', 'pointing_loss']),
            rx_noise_temp_k=self.sampler(self.groundstation_configuration,
                                         ['rx', 'antenna', 'noise_temp']))

        # form the downlink signal chain
        self.downlink = pylink.DAGModel([
            self.geometry, self.gs_rx_antenna, self.sat_transmitter,
            self.sat_tx_antenna, self.gs_receiver, self.downlink_channel,
            self.rx_interconnect, self.tx_interconnect, self.modulation,
            pylink.LinkBudget(name='Downlink', is_downlink=True)
        ])
Beispiel #12
0
    # that income as it counts towards amti.  This is done in
    # investigator.py where it determines the number of ISOs you can
    # exercise before hitting AMT.
    'iso_exercise_income_usd': 0,

    # pre-tax contributions
    'palantir_401k_usd': 0,
    'palantir_fsa_usd': 0,
    'palantir_drca_usd': 0,

    # Regular income
    'reg_income_usd': 150000,

    # If you have any other income that does not count as regular
    # income, but does affect amti (such as any ISOs you've exercised
    # this year), it should be included here.
    'ext_amt_income_usd': 0,

    # Check your paystub and estimate how much has been withheld for
    # taxes by the end of the year.  This one is needed to approximate
    # how much remaining tax burden will exist.
    'fed_withheld_usd': 20000,
    'state_withheld_usd': 15000,
}

# Now we create the DAG Model.  We'll use this model for everything else.
MODEL = pylink.DAGModel(
    [deathAnd.Taxes(),
     myMeager.Income(),
     anAwkward.Position(GRANTS)], **__constants)
Beispiel #13
0
"""Illustrations of the override functionality.

This example illustrates how node values can be overridden.
"""


def _the_calculated_answer(model):
    return 42


def _the_answer_plus_two(model):
    return model.the_answer + 2


m = pylink.DAGModel(the_answer=42,
                    the_calculated_answer=_the_calculated_answer,
                    the_answer_plus_two=_the_answer_plus_two)
e = m.enum

print('The original answer:', m.the_answer)
print('Overriding the Answer to 24')
m.override(e.the_answer, 24)
print('The new answer:', m.the_answer)
print('The override value:', m.override_value(e.the_answer))

print('')

print('"Reverting" the override is illegal, since it is a static value')
try:
    m.revert(e.the_answer)
except AttributeError as err:
Beispiel #14
0
#!/usr/bin/python

import pylink
"""Illustrations of the precedence order for node definitions.

Nodes are added to the DAG in the order in which they are received.
So you can, if you wish, override a standard definition.
"""

# Vanilla link budget
m = pylink.DAGModel([
    pylink.Geometry(),
    pylink.Transmitter(tx_power_at_pa_dbw=2),
    pylink.Interconnect(is_rx=False),
    pylink.Antenna(is_rx=False),
    pylink.Receiver(),
    pylink.Antenna(is_rx=True),
    pylink.Interconnect(is_rx=True),
    pylink.Channel(),
    pylink.Modulation('DVB-S2X'),
    pylink.LinkBudget()
])
e = m.enum

print 'Link margin in vanilla example: %s' % m.link_margin_db


# let's override the link_margin_db node in the kwargs
def _evil_margin_db(model):
    return -3.0

Beispiel #15
0
    parser.add_argument('--ground-irradiance-index', '-G',
                        metavar='GROUND_IRRADIANCE_INDEX',
                        action='store',
                        dest='ground_index',
                        required=False,
                        type=int,
                        default=3,
                        help='Index into the CSV for the ground irradiance',)

    args = parser.parse_args()

    atmo_irradiance = _load_irradiance(args.atmo_path, args.atmo_index)
    ground_irradiance = _load_irradiance(args.ground_path, args.ground_index)

    budget = pylink.HyperSpectralSNRBudget(atmo_irradiance, ground_irradiance)

    geometry = pylink.Geometry(apoapsis_altitude_km=500,
                               periapsis_altitude_km=500,
                               min_elevation_deg=90)

    m = pylink.DAGModel([budget, geometry])
    e = m.enum

    output_dir = os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        'export')
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    path = os.path.join(output_dir, 'snr-vnir.png')
    plot_snr(m, start_nm=400,  end_nm=1400,  path=path)
Beispiel #16
0
    def test_solve_for(self, model):
        m = model
        e = m.enum

        # Basic operation - make sure it doesn't die
        tmp = m.solve_for(e.rx_antenna_noise_temp_k,
                          e.link_margin_db,
                          0.125,
                          300,
                          5000,
                          10,
                          rounds=1)

        # Basic operation - make sure it doesn't die on 10 rounds
        tmp = m.solve_for(e.rx_antenna_noise_temp_k,
                          e.link_margin_db,
                          0.125,
                          300,
                          5000,
                          10,
                          rounds=10)

        # Should error-out on invalid input: same input and output
        with pytest.raises(AttributeError):
            tmp = m.solve_for(e.link_margin_db,
                              e.link_margin_db,
                              0.125,
                              300,
                              5000,
                              10,
                              rounds=10)

        # Should error-out on invalid input: static output variable
        with pytest.raises(AttributeError):
            tmp = m.solve_for(e.link_margin_db,
                              e.rx_antenna_noise_temp_k,
                              0.125,
                              300,
                              5000,
                              10,
                              rounds=10)

        # Should error-out on invalid input: 0 step size
        with pytest.raises(AttributeError):
            tmp = m.solve_for(e.link_margin_db,
                              e.rx_antenna_noise_temp_k,
                              0.125,
                              300,
                              5000,
                              0,
                              rounds=10)

        # Should error-out on invalid input: negative rounds
        with pytest.raises(AttributeError):
            tmp = m.solve_for(e.link_margin_db,
                              e.rx_antenna_noise_temp_k,
                              0.125,
                              300,
                              5000,
                              0,
                              rounds=-1)

        # Should error-out on invalid input: non-integer rounds
        with pytest.raises(AttributeError):
            tmp = m.solve_for(e.link_margin_db,
                              e.rx_antenna_noise_temp_k,
                              0.125,
                              300,
                              5000,
                              0,
                              rounds=1.0)

        # Basic operation: proper value
        def __round(ans, order):
            return round(ans * 10**order) / 10**order

        model.override(e.rx_ebn0_db, 10.0)
        model.override(e.required_ebn0_db, 2.0)
        target = 0.1257354
        ans = 2.0 + target

        for i in range(10):
            tmp = m.solve_for(e.rx_ebn0_db,
                              e.link_margin_db,
                              target,
                              0.0,
                              10.0,
                              1.0,
                              rounds=i + 1)
            assert abs(__round(ans, i) - tmp) < 1e-6

        def __a(m):
            return m.b

        m = pylink.DAGModel([], a=__a, b=10)
        e = m.enum

        b = m.solve_for(e.b, e.a, 20, 0.0, 10.0, 1.0, rounds=4)
        assert abs(b - 10.0) < 1e-4

        d = 1e-5
        b = m.solve_for(e.b, e.a, 20, 0.0, 10.0 + d, 1.0, rounds=4)
        assert abs(b - 10.0) < 1e-4

        b = m.solve_for(e.b, e.a, 20, 0.0, 10.0 - d, 1.0, rounds=4)
        assert abs(b - 10.0) < 1e-4

        b = m.solve_for(e.b, e.a, 20, 10.0, 0.0, -1.0, rounds=4)
        assert abs(b - 10.0) < 1e-4
Beispiel #17
0
                           center_freq_mhz=8200,
                           atmospheric_loss_db=1,
                           ionospheric_loss_db=1,
                           rain_loss_db=2,
                           multipath_fading_db=0,
                           polarization_mismatch_loss_db=3)

s_channel = pylink.Channel(bitrate_hz=500e3,
                           allocation_hz=5e6,
                           center_freq_mhz=2022.5,
                           atmospheric_loss_db=.5,
                           ionospheric_loss_db=.5,
                           rain_loss_db=1,
                           multipath_fading_db=0,
                           polarization_mismatch_loss_db=3)

# defaults to DVB-S2X
modulation = pylink.Modulation()

DOWNLINK = pylink.DAGModel([
    geometry, gs_rx_antenna, sat_transmitter, sat_tx_antenna, gs_receiver,
    x_channel, rx_interconnect, tx_interconnect, modulation,
    pylink.LinkBudget(name='Example XBand Downlink', is_downlink=True)
])

UPLINK = pylink.DAGModel([
    geometry, sat_rx_antenna, sat_receiver, gs_transmitter, gs_tx_antenna,
    s_channel,
    pylink.LinkBudget(name='Example SBand Uplink', is_downlink=False)
])
Beispiel #18
0
    def test_selective_cache_clear(self):
        """Ensures that a non-dependent cached-item is not re-calculated.

        A: Tracking calculator
        B: Tracking calculator
        C: Assert second time

        Dependent pathway:
        A <-- B

        Independent pathway:
        C

        Calculate B
        Calculate C

        Ensure:
         * A was calculated
         * B was calculated
         * C was calculated

        Override A
        Calculate B

        Ensure:
         * A was served from the override value and was NOT recalculated
         * B was recalculated
         * C was NOT recalculated
        """

        self._state_a = 0
        self._state_b = 0
        self._state_c = 0

        f_A = self._wrap_func(self._tracking_calculator,
                              state_var='_state_a',
                              retval='A')
        f_B = self._wrap_func(self._tracking_calculator,
                              state_var='_state_b',
                              retval='B',
                              deps=['A'])
        f_C = self._wrap_func(self._assert_on_second,
                              state_var='_state_c',
                              retval='C')

        m = pylink.DAGModel(A=f_A, B=f_B, C=f_C)
        e = m.enum

        m.B
        assert 1 == self._state_a, "A was not calculated"
        assert 1 == self._state_b, "B was not calculated"

        m.C
        assert 1 == self._state_c, "C was not calculated"

        m.override(e.A, "A'")

        m.B
        assert 1 == self._state_a, "A was recalculated"
        assert 2 == self._state_b, "B was not recalculated"

        m.C
        assert 1 == self._state_c, "C was recalculated"
Beispiel #19
0
    'whimsy_coefficient': TA(42,
                             datasheet="hitchhiker's guide to the galaxy",
                             author="Douglas Adams"),
    'wacky_computation': __do_it_do_it_now
    }

tx_power = TA(2,
              part_number='234x',
              test_report='http://reports.co/234x')

m = pylink.DAGModel([pylink.Geometry(),
                     pylink.Transmitter(tx_power_at_pa_dbw=tx_power),
                     pylink.Interconnect(is_rx=False),
                     pylink.Antenna(is_rx=False),
                     pylink.Receiver(),
                     pylink.Antenna(is_rx=True),
                     pylink.Interconnect(is_rx=True),
                     pylink.Channel(),
                     pylink.Modulation('DVB-S2X'),
                     pylink.LinkBudget()],
                    **ex)
e = m.enum

print('slant range (km):        %3g' % m.slant_range_km)
print('antenna angle (deg):     %3g' % m.satellite_antenna_angle_deg)
print('total rx noise temp (K): %3g' % m.rx_noise_temp_k)
print('receiver noise temp (K): %3g' % m.rx_system_noise_temp_k)
print('noise factor:            %3g' % m.rx_system_noise_factor)
print('noise figure (dB):       %3g' % m.rx_system_noise_figure)
print('transmit power (dBW):    %3g' % m.tx_power_at_antenna_dbw)
print('transmit eirp (dBW):     %3g' % m.tx_eirp_dbw)
Beispiel #20
0
#!/usr/bin/python

import pylink


def _raises_exception(model):
    """Return a value that doesn't exist.

    Calling this node will result in an AttributeError because the
    'does_not_exist' node, well, doesn't exist.
    """
    return model.does_not_exist


extras = {'raises_exception': _raises_exception}
m = pylink.DAGModel([], **extras)

print "="*80
print 'AttributeError will be raised'
print "We're asking for a node that doesn't exist"
print "="*80
print m.raises_exception
Beispiel #21
0
def model():
    return pylink.DAGModel([
        anAwkward.Position(GRANTS),
        ],
                           query_date='11/1/20')
Beispiel #22
0
            # calculators
            'net_salary_usd_per_month': _net_salary_usd_per_month,
            'expenses_usd_per_month': _expenses_usd_per_month,
            'savings_usd_per_month': _savings_usd_per_month,

            # constants
            'gross_salary_usd_per_month': gross_salary_usd_per_month,
            'tax_rate': tax_rate,
            'rent_usd_per_month': rent_usd_per_month,
            'food_usd_per_month': food_usd_per_month,
            'other_expenses_usd_per_month': other_expenses_usd_per_month,
        }


def _months_to_pay_for_car(model):
    return float(model.midlife_crisis_car_usd) / model.savings_usd_per_month


extras = {
    'midlife_crisis_car_usd': TA(110e3, model='Tesla P100d'),
    'months_to_pay_for_car': _months_to_pay_for_car,
}
m = pylink.DAGModel([GenericFinancialModel()], **extras)
e = m.enum

print 'Savings Rate ($/mo):        %3g' % m.savings_usd_per_month
print 'Cost of Midlife Crisis ($): %3g' % m.midlife_crisis_car_usd
print 'Car Model:                  %s' % m.get_meta(
    e.midlife_crisis_car_usd)['model']
print 'Months to Pay for Crisis:   %d' % round(m.months_to_pay_for_car, 0)