Skip to content

Commit

Permalink
Merge pull request #60 from soapy/conjugatesDMs
Browse files Browse the repository at this point in the history
Conjugates DMs
  • Loading branch information
matthewtownson committed May 18, 2016
2 parents f3caf9a + 0720894 commit 211cbdb
Show file tree
Hide file tree
Showing 8 changed files with 267 additions and 104 deletions.
90 changes: 90 additions & 0 deletions conf/sh_8x8_mcao.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
simName: sh_8x8
pupilSize: 64
nGS: 3
nDM: 2
nSci: 1
nIters: 5000
loopTime: 0.0025
reconstructor: "MVM"

verbosity: 2

saveCMat: False
saveSlopes: True
saveDmCommands: False
saveLgsPsf: False
saveSciPsf: True


Atmosphere:
scrnNo: 2
scrnHeights: [0, 10000]
scrnStrengths: [0.5, 0.5]
windDirs: [0, 90]
windSpeeds: [10, 10]
wholeScrnSize: 2048
r0: 0.16


Telescope:
telDiam: 4.2
obsDiam: 1.
mask: circle

# WFSs in equalateral triange, with asterism radius 25"
WFS:
0:
type: ShackHartmann
GSPosition: [0, 25]
GSHeight: 0
GSMag: 8
nxSubaps: 8
pxlsPerSubap: 10
subapFOV: 2.5
wavelength: 600e-9

1:
type: ShackHartmann
GSPosition: [-21.5, -12.5]
GSHeight: 0
GSMag: 8
nxSubaps: 8
pxlsPerSubap: 10
subapFOV: 2.5
wavelength: 600e-9
2:
type: ShackHartmann
GSPosition: [21.5, -12.5]
GSHeight: 0
GSMag: 8
nxSubaps: 8
pxlsPerSubap: 10
subapFOV: 2.5
wavelength: 600e-9

DM:
0:
type: Piezo
closed: True
nxActuators: 9
svdConditioning: 0.05
iMatValue: 500
gain: 0.7

1:
type: Piezo
closed: True
nxActuators: 9
svdConditioning: 0.05
gain: 0.7
iMatValue: 500
altitude: 10000
diameter: 10


Science:
0:
position: [0, 0]
FOV: 2.0
wavelength: 1.65e-6
pxls: 128
67 changes: 42 additions & 25 deletions soapy/DM.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
==============
New DMs are easy to add into the simulation. At its simplest, the :py:class:`DM`
class is inherited by the new DM class. Only a ``makeIMatShapes` method need be provided, which creates the independent influence function the DM can make. The
class is inherited by the new DM class. Only a ``makeIMatShapes` method need be provided,
which creates the independent influence function the DM can make. The
base class deals with the rest, including making interaction matrices and loop
operation.
"""
Expand All @@ -58,7 +59,8 @@ class DM(object):
The base DM class
This class is intended to be inherited by other DM classes which describe
real DMs. It provides methods to create DM shapes and then interaction matrices, given a specific WFS or WFSs.
real DMs. It provides methods to create DM shapes and then interaction matrices,
given a specific WFS or WFSs.
Parameters:
soapyConfig (ConfigObj): The soapy configuration object
Expand All @@ -68,7 +70,8 @@ class DM(object):
"""

def __init__ (self, soapyConfig, nDm=0, wfss=None, mask=None):


self.soapyConfig = soapyConfig
self.simConfig = soapyConfig.sim
self.dmConfig = soapyConfig.dms[nDm]
self.wfss = wfss
Expand Down Expand Up @@ -137,7 +140,7 @@ def makeIMat(self, callback=None):
if self.dmConfig.rotation:
self.iMatShapes = rotate(
self.iMatShapes, self.dmConfig.rotation,
order=self.dmConfig.interpOrder, axes=(-2,-1)
order=self.dmConfig.interpOrder, axes=(-2, -1)
)
rotShape = self.iMatShapes.shape
self.iMatShapes = self.iMatShapes[:,
Expand All @@ -148,10 +151,13 @@ def makeIMat(self, callback=None):
]

iMat = numpy.zeros(
(self.acts, self.totalWfsMeasurements) )
(self.acts, self.totalWfsMeasurements))

# A vector of DM commands to use when making the iMat
actCommands = numpy.zeros(self.acts)

# Blank phase to use whilst making iMat
phs = numpy.zeros((self.simConfig.simSize, self.simConfig.simSize))
for i in xrange(self.acts):
subap = 0

Expand All @@ -166,11 +172,10 @@ def makeIMat(self, callback=None):

# Send the DM shape off to the relavent WFS. put result in iMat
iMat[i, subap: subap + (2*self.wfss[nWfs].activeSubaps)] = (
self.wfss[nWfs].frame(
self.dmShape, iMatFrame=True
))/self.dmConfig.iMatValue
-1*self.wfss[nWfs].frame(
None, correction=self.dmShape, iMatFrame=True))/self.dmConfig.iMatValue

if callback!=None:
if callback != None:
callback()

logger.statusMessage(i, self.acts,
Expand Down Expand Up @@ -208,22 +213,27 @@ def dmFrame(self, dmCommands, closed=False):

else:
self.actCoeffs = (self.dmConfig.gain * self.newActCoeffs)\
+ ( (1.-self.dmConfig.gain) * self.actCoeffs)
+ ( (1. - self.dmConfig.gain) * self.actCoeffs)

self.dmShape = self.makeDMFrame(self.actCoeffs)
# Remove any piston term from DM
self.dmShape -= self.dmShape.mean()

return self.dmShape

# except AttributeError:
# raise AttributeError("DM Missing influence functions. Have you made an interaction matrix?")


def makeDMFrame(self, actCoeffs):

dmShape = (self.iMatShapes.T*actCoeffs.T).T.sum(0)
return dmShape
dmShape = (self.iMatShapes.T*actCoeffs.T).T.sum(0)

# If DM not telescope diameter, must adjust pixel scale
if self.dmConfig.diameter != self.soapyConfig.tel.telDiam:
scaledDMSize = (dmShape.shape[0]
* float(self.dmConfig.diameter)/self.soapyConfig.tel.telDiam)
dmShape = aoSimLib.zoom(dmShape, scaledDMSize, order=1)

# Turn into phase pbject with altitude
dmShape = Phase(dmShape, altitude=self.dmConfig.altitude)

return dmShape

class Zernike(DM):
"""
Expand All @@ -237,12 +247,12 @@ def makeIMatShapes(self):
'''

shapes = aoSimLib.zernikeArray(
int(self.acts+1),int(self.simConfig.pupilSize))[1:]
int(self.acts + 1), int(self.simConfig.pupilSize))[1:]


pad = self.simConfig.simPad
self.iMatShapes = numpy.pad(
shapes, ((0,0), (pad,pad), (pad,pad)), mode="constant"
shapes, ((0, 0), (pad, pad), (pad, pad)), mode="constant"
).astype("float32")

class Piezo(DM):
Expand Down Expand Up @@ -296,7 +306,7 @@ def makeIMatShapes(self):

#Create a "dmSize" - the pupilSize but with 1 extra actuator on each
#side
dmSize = self.simConfig.pupilSize + 2*numpy.round(self.spcing)
dmSize = self.simConfig.pupilSize + 2 * numpy.round(self.spcing)

shapes = numpy.zeros((self.acts, dmSize, dmSize), dtype="float32")

Expand Down Expand Up @@ -337,8 +347,6 @@ class GaussStack(Piezo):
not realistic, it provides a known influence function which can be useful
for some analysis.
"""


def makeIMatShapes(self):
"""
Generates the influence functions for the GaussStack DM.
Expand All @@ -365,8 +373,6 @@ def makeIMatShapes(self):
self.iMatShapes, ((0,0), (pad,pad), (pad,pad)), mode="constant"
)



class TT(DM):
"""
A class representing a tip-tilt mirror.
Expand Down Expand Up @@ -436,3 +442,14 @@ def makeDMFrame(self, actCoeffs):
).astype("float32")

return self.dmShape

class Phase(numpy.ndarray):
def __new__(cls, input_array, altitude=0):
obj = numpy.asarray(input_array).view(cls)
obj.altitude = altitude
return obj

def __array_finalize__(self, obj):
if obj is None: return
self.info = getattr(obj, 'info', None)

1 change: 0 additions & 1 deletion soapy/SCI.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@ def frame(self, scrns, correction=None):
Returns:
ndarray: Resulting science PSF
"""

self.los.frame(scrns, correction=correction)

self.calcFocalPlane()
Expand Down
17 changes: 15 additions & 2 deletions soapy/confParse.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,18 +220,24 @@ def calcParams(self):
logger.info("Pixel Scale: {0:.2f} pxls/m".format(self.sim.pxlScale))
logger.info("subScreenSize: {:d} simulation pixels".format(int(self.sim.scrnSize)))

# If outer scale is None, set all to 100m
# If outer scale is None, set all to really big number. Will introduce bugs when we make
# telescopes with diameter >1000000s of kilometres
if self.atmos.L0 is None:
self.atmos.L0 = []
for scrn in range(self.atmos.scrnNo):
self.atmos.L0.append(100.)
self.atmos.L0.append(10e9)

# Check if SH WFS with 1 subap. Feild stop must be FOV
for wfs in self.wfss:
if wfs.nxSubaps==1 and wfs.subapFieldStop==False:
logger.warning("Setting WFS:{} to have field stop at sub-ap FOV as it only has 1 sub-aperture".format(wfs))
wfs.subapFieldStop = True

# If dm diameter is None, set to telescope diameter
for dm in self.dms:
if dm.diameter is None:
dm.diameter = self.tel.telDiam


def __iter__(self):
objs = {'Sim': dict(self.sim),
Expand Down Expand Up @@ -912,6 +918,11 @@ class in the ``DM`` module.
``gaussWidth`` float: Width of Guass DM actuator
as a fraction of the
inter-actuator spacing. ``0.5``
``altitude`` float: Altitude to which DM is
optically conjugated. ``0``
``diameter`` float: Diameter covered by DM in
metres. If ``None`` if telescope
diameter. ``None``
==================== ================================= ===========
"""

Expand All @@ -930,6 +941,8 @@ class in the ``DM`` module.
("rotation", 0),
("interpOrder", 2),
("gaussWidth", 0.5),
("altitude", 0.),
("diameter", None)
]

calculatedParams = [
Expand Down
Loading

0 comments on commit 211cbdb

Please sign in to comment.