Skip to content

Adds ability to forward noises from sub-budgets into higher level budget

Kevin Kuns requested to merge kevin.kuns/pygwinc:forward-noises into master

This adds the ability to extract noises and calibrations from a list of sub-budgets and forward them to an upper level budget, as was done in !128 (closed). However, @christopher.wipf suggested a different implementation. That suggestion was not general enough though (it only worked for a single sub-budget and not a list of sub-budgets). Here I loop through his suggestion and further generalize it to work with dicts as well as lists. We'll need this by hook or by crook for the new quantum calculations.

Examples of this forwarding are given in the unit test test_forward_noises in test/budgets/test_budgets.py They use the budgets H1NoRefsForwardNoises and H1dictNoRefsForwardNoises defined in the H1 intereferometer in that directory.

As a simple example using the exact same API as in !128 (closed) and used in all of the new quantum code,

class Quantum(nb.Budget):
    noises = [
        (Shot, Sensing),
        RadiationPressure,
    ]

class MainBudget(nb.Budget):
    noises = [
        Thermal,
    ]
    noises_forward = [
        Quantum,
    ]

Defined like this the main budget will have shot noise, radiation pressure, and thermal noise even though the two quantum noises are grouped in their own sub-budget. If MainBudget had been defined with Quantum in the list of noises with Thermal instead, the main budget would only have the total quantum and thermal noises, and the quantum noise would be further broken up into a quantum sub-budget with shot noise and radiation pressure noise.

An alternative approach, which would need to be modified to support dicts directly and which I don't like as much, was implemented in the commit 15ac555e and is almost exactly Chris' suggestion. Instead of the above which very slightly modifies the nb.Budget init, the same behavior is produced without modifying nb.Budget with

def forward_noises(subbudgets):
    noises_frwd = []
    for budget in subbudgets:
        if not isinstance(budget, (tuple, list)):
            budget = (budget,)
        b = budget[0]
        cals = tuple(budget[1:])
        cals += tuple(b.calibrations)
        noises_frwd.extend([
            n + cals if isinstance(n, (tuple, list))
            else (n,) + cals for n in b.noises
        ])
    return noises_frwd

class MainBudget(Budget):
    noises = [
        Thermal,
    ]
    noises += forward_noises([
        Quantum,
    ])

Merge request reports