Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion falco/config/ModelParameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from falco.config.yaml_loader import object_constructor, load_from_str
from falco.util import _spec_arg
from falco.config import Probe, ProbeSchedule, Object
import astropy


class ModelParameters(Object):
Expand Down Expand Up @@ -251,7 +252,7 @@ def from_yaml(text, context=None):

data = load_from_str(
text,
{'np': numpy, 'falco': falco, 'math': math},
{'np': numpy, 'falco': falco, 'math': math, 'astropy': astropy},
context,
{
"!Probe": object_constructor(Probe),
Expand Down
9 changes: 9 additions & 0 deletions falco/config/TestbedInterface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from abc import ABC, abstractmethod

class TestbedInterface(ABC):
'''A general purpose interface for all testbeds to implement.'''

@abstractmethod
def get_sbp_image(self, subband_index):
pass

14 changes: 7 additions & 7 deletions falco/ctrl.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import falco


def wrapper(mp, cvar, jacStruct):
def wrapper(mp, cvar, jacStruct, tb=None):
"""
Outermost wrapper function for all the controller functions.

Expand Down Expand Up @@ -98,7 +98,7 @@ def wrapper(mp, cvar, jacStruct):
print('Control beginning ...')
# Established, conventional controllers
if mp.controller.lower() == 'plannedefc':
dDM = _planned_efc(mp, cvar)
dDM = _planned_efc(mp, cvar, tb=tb)
elif mp.controller.lower() == 'gridsearchefc':
dDM = _grid_search_efc(mp, cvar)

Expand Down Expand Up @@ -556,7 +556,7 @@ def _planned_ad_efc(mp, cvar):
return dDM


def _planned_efc(mp, cvar):
def _planned_efc(mp, cvar, tb=None):
"""
Perform a scheduled/planned set of EFC iterations.

Expand Down Expand Up @@ -627,7 +627,7 @@ def _planned_efc(mp, cvar):

for ni in range(Nvals):

[InormVec[ni], dDM_temp] = _efc(ni, vals_list, mp, cvar)
[InormVec[ni], dDM_temp] = _efc(ni, vals_list, mp, cvar, tb=tb)
ImCube[ni, :, :] = dDM_temp.Itotal

# delta voltage commands
Expand Down Expand Up @@ -703,7 +703,7 @@ def _planned_efc(mp, cvar):
vals_list = [(x, y) for y in np.array([cvar.latestBestDMfac])
for x in np.array([log10regSchedOut])]

[cvar.cMin, dDM] = _efc(ni, vals_list, mp, cvar)
[cvar.cMin, dDM] = _efc(ni, vals_list, mp, cvar, tb=tb)
cvar.Im = np.squeeze(dDM.Itotal)
if mp.ctrl.flagUseModel:
print(('Model expects scheduled log10(reg) = %.1f\t to give ' +
Expand Down Expand Up @@ -800,7 +800,7 @@ def efc_schedule_generator(scheduleMatrix):
return Nitr, relinItrVec, gridSearchItrVec, log10regSched, dm_ind_sched


def _efc(ni, vals_list, mp, cvar):
def _efc(ni, vals_list, mp, cvar, tb=None):
"""
Compute the main EFC equation. Called by a wrapper controller function.

Expand Down Expand Up @@ -856,7 +856,7 @@ def _efc(ni, vals_list, mp, cvar):
Itotal = falco.imaging.get_expected_summed_image(mp, cvar, dDM)
InormAvg = np.mean(Itotal[mp.Fend.corr.maskBool])
else: # Get actual image from full model or testbed
Itotal = falco.imaging.get_summed_image(mp)
Itotal = falco.imaging.get_summed_image(mp, tb=tb)
InormAvg = np.mean(Itotal[mp.Fend.corr.maskBool])
dDM.Itotal = Itotal

Expand Down
20 changes: 12 additions & 8 deletions falco/est.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from . import check


def wrapper(mp, ev, jacStruct):
def wrapper(mp, ev, jacStruct, tb = None):
"""
Select and run the chosen estimator.

Expand All @@ -23,6 +23,8 @@ def wrapper(mp, ev, jacStruct):
Structure containing estimation variables.
jacStruct : ModelParameters
Structure containing control Jacobians for each specified DM.
tb : falco.config.TestbedInterface or None
(Optional) Control interface for a physical testbed.

Returns
-------
Expand All @@ -33,15 +35,15 @@ def wrapper(mp, ev, jacStruct):

falco.est.perfect(mp, ev)
with falco.util.TicToc('Getting updated summed image'):
ev.Im = falco.imaging.get_summed_image(mp)
ev.Im = falco.imaging.get_summed_image(mp, tb)

elif mp.estimator in ['pairwise', 'pairwise-square', 'pairwise-rect',
'pwp-bp-square', 'pwp-bp', 'pwp-kf']:

if mp.est.flagUseJac: # Send in the Jacobian if true
falco.est.pairwise_probing(mp, ev, jacStruct=jacStruct)
falco.est.pairwise_probing(mp, ev, jacStruct=jacStruct, tb=tb)
else: # Otherwise don't pass the Jacobian
falco.est.pairwise_probing(mp, ev)
falco.est.pairwise_probing(mp, ev, tb=tb)

return None

Expand Down Expand Up @@ -219,7 +221,7 @@ def _est_perfect_Efield_with_Zernikes_in_parallel(mp, ilist, inds_list):
return E2D


def pairwise_probing(mp, ev, jacStruct=np.array([])):
def pairwise_probing(mp, ev, jacStruct=np.array([]), tb = None):
"""
Estimate the dark hole E-field with pair-wise probing.

Expand All @@ -230,6 +232,8 @@ def pairwise_probing(mp, ev, jacStruct=np.array([])):
ev : falco.config.Object()
jacStruct : array_like, optional
Array containing the control Jacobian. Default is an empty array.
tb : falco.config.TestbedInterface or None
(Optional) Control interface for a physical testbed.

Returns
-------
Expand Down Expand Up @@ -394,7 +398,7 @@ def pairwise_probing(mp, ev, jacStruct=np.array([])):

# Take initial, unprobed image (for unprobed DM settings).
whichImage = 0
I0 = falco.imaging.get_sbp_image(mp, iSubband)
I0 = falco.imaging.get_sbp_image(mp, iSubband, tb)
I0vec = I0[mp.Fend.corr.maskBool] # Vectorize the dark hole

# Image already includes all stars, so don't sum over star loop
Expand Down Expand Up @@ -460,7 +464,7 @@ def pairwise_probing(mp, ev, jacStruct=np.array([])):
mp.dm2.V = DM2Vnom + dDM2Vprobe

# Take probed image
Im = falco.imaging.get_sbp_image(mp, iSubband)
Im = falco.imaging.get_sbp_image(mp, iSubband, tb)

# ImNonneg = Im
# ImNonneg[Im < 0] = 0
Expand Down Expand Up @@ -875,4 +879,4 @@ def gen_pairwise_probe(mp, InormDes, phaseShift, starIndex, rotation):
probeCmd = falco.dm.fit_surf_to_act(dm, probeHeight)
probeCmd = mp.est.probe.gainFudge[starIndex] * probeCmd # Scale the probe amplitude empirically if needed

return probeCmd
return probeCmd
13 changes: 9 additions & 4 deletions falco/imaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ def _model_full_norm_wrapper(mp, ilist, inds_list):
return np.max(np.abs(Etemp)**2)


def get_summed_image(mp):
def get_summed_image(mp, tb = None):
"""
Get the broadband image over the entire bandpass.

Expand All @@ -257,6 +257,8 @@ def get_summed_image(mp):
----------
mp: falco.config.ModelParameters
Structure of model parameters
tb: falco.config.TestbedInterface
(Optional) control interface for a physical testbed

Returns
-------
Expand All @@ -270,7 +272,7 @@ def get_summed_image(mp):
if not (mp.flagParallel and mp.flagSim):
summedImage = 0
for si in range(mp.Nsbp):
summedImage += mp.sbp_weights[si] * get_sbp_image(mp, si)
summedImage += mp.sbp_weights[si] * get_sbp_image(mp, si, tb)

else: # Compute simulated images in parallel

Expand Down Expand Up @@ -360,7 +362,7 @@ def _get_single_sim_full_image(mp, ilist, vals_list):
return np.abs(Estar)**2 # Apply spectral weighting outside this function


def get_sbp_image(mp, si):
def get_sbp_image(mp, si, tb = None):
"""
Get an image in the specified sub-bandpass.

Expand All @@ -373,6 +375,8 @@ def get_sbp_image(mp, si):
Structure of model parameters
si: int
Index of sub-bandpass for which to take the image
tb: falco.config.TestbedInterface or None
(Optional) Control interface for a physical testbed

Returns
-------
Expand All @@ -387,7 +391,8 @@ def get_sbp_image(mp, si):
if mp.flagSim:
Isbp = get_sim_sbp_image(mp, si)
else:
Isbp = get_testbed_sbp_image(mp, si)
tb.dm.apply(mp.dm1.V)
Isbp = tb.get_sbp_image(si)

return Isbp

Expand Down
8 changes: 5 additions & 3 deletions falco/wfsc.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import falco


def loop(mp, out):
def loop(mp, out, tb = None):
"""
Loop over the estimator and controller for WFSC.

Expand All @@ -19,6 +19,8 @@ def loop(mp, out):
Structure of model parameters
out : falco.config.Object
Output variables
tb : falco.config.TestbedInterface or None
(Optional) Control interface for a physical testbed.

Returns
-------
Expand Down Expand Up @@ -90,7 +92,7 @@ def loop(mp, out):
if Itr > 0:
EestPrev = ev.Eest # save previous estimate for Delta E plot

falco.est.wrapper(mp, ev, jacStruct)
falco.est.wrapper(mp, ev, jacStruct, tb)

store_intensities(mp, out, ev, Itr)

Expand Down Expand Up @@ -122,7 +124,7 @@ def loop(mp, out):

# Send a copy of jacStruct so that spatial weights don't show up
# outside the controller or get applied multiple times.
falco.ctrl.wrapper(mp, cvar, copy(jacStruct))
falco.ctrl.wrapper(mp, cvar, copy(jacStruct), tb=tb)

# Store key data in out object
out.log10regHist[Itr] = cvar.log10regUsed
Expand Down