Beispiel #1
0
 def checkArray(self,val,shape,dtype,raiseShape=0):
     if type(val)==type([]):
         val=numpy.array(val)
     elif type(val)==type(""):
         if os.path.exists(val):
             print "Loading %s"%val
             val=FITS.Read(val)[1]
         else:
             raise Exception("File not found %s"%val)
     if type(val)==numpy.ndarray:
         if dtype is not None:
             val=val.astype(dtype)
         if shape is not None:
             if type(shape)!=type(()):
                 shape=(shape,)
             if val.shape!=shape:
                 print "Warning - shape not quite right (expecting %s, got %s)?"%(str(shape),str(val.shape))
                 if raiseShape:
                     raise Exception("checkArray shape")
             try:
                 val.shape=shape
             except:
                 print val.shape,shape
                 raise
     else:
         raise Exception("checkArray")
     return val
Beispiel #2
0
 def DarcInit(self, data):
     """data can be a FITS filename, or the contents of the FITS file"""
     if os.path.exists(data):
         data = FITS.Read(data)[1]
     nbytes = data.size * data.itemsize
     self.sock.send(
         numpy.array(
             [0x55555555, DARCINIT, nbytes & 0xffffffff,
              nbytes >> 32]).astype(numpy.int32))
     self.sock.sendall(data)
     self.checkReply()
Beispiel #3
0
    def __init__(self, name):
        """For extracting data from a large FITS file."""
        self.bpdict = {
            8: numpy.uint8,
            16: numpy.int16,
            32: numpy.int32,
            -32: numpy.float32,
            -64: numpy.float64,
            -16: numpy.uint16
        }

        self.name = name
        self.fd = open(self.name, "r")
        self.HDUoffset = 0
        self.hdr = FITS.ReadHeader(self.fd)["parsed"]
        self.nd = int(self.hdr["NAXIS"])
        dims = []
        for i in range(self.nd):
            dims.append(int(self.hdr["NAXIS%d" % (i + 1)]))
        dims.reverse()
        self.dims = numpy.array(dims)
        self.bitpix = int(self.hdr["BITPIX"])
        self.dataOffset = self.fd.tell()
        dsize = self.getDataSize(self.hdr)
        #Now get the frame list - move to the frame list HDU
        self.fd.seek(dsize, 1)
        try:
            self.frameno = FITS.Read(self.fd, allHDU=0)[1]
        except:
            print "Unable to read frame numbers"
            traceback.print_exc()
        try:
            self.timestamp = FITS.Read(self.fd, allHDU=0)[1]
        except:
            print "Unable to read timestamps"
            traceback.print_exc()
        self.nextHDUoffset = self.fd.tell()
Beispiel #4
0
 def checkNoneOrArray(self,val,size,dtype):
     if type(val)==type([]):
         val=numpy.array(val)
     elif type(val)==type(""):
         if os.path.exists(val):
             print "Loading %s"%val
             val=FITS.Read(val)[1]
         else:
             print "File %s not found"%val
             raise Exception("File %s not found"%val)
     if val is None:
         pass
     elif type(val)==numpy.ndarray:
         val=val.astype(dtype)
         if size is not None:
             val.shape=size,
     else:
         raise Exception("checkNoneOrArray size requested %d"%size)
     return val
Beispiel #5
0
 def loadSineData(self,fname,stdThresh=0.25):
     """
     fname is the name of a file that has been created by e.g. doSinePokeGTC()
     stdThresh is the threshold above which slopes are ignored if their std is higher than the max std * thresh.  This allows us to automatically cut out slopes the don't have light."""
     sList=[]
     vList=[]
     data=FITS.Read(fname)
     for i in range(len(data)//12):
         s=data[1+i*12]#the slopes
         vmes=data[7+i*12]#the actuators (sinusoidal)
         if stdThresh>0:
             #define a mask of valid subaps based on those with low rms.
             sstd=s.std(0)#get standard deviation of each subap
             maxstd=sstd.max()#find the max...
             valid=numpy.where(sstd<maxstd*stdThresh,1,0)
             s*=valid
         sList.append(s)
         vList.append(vmes)
     return vList,sList
Beispiel #6
0
import sys
import numpy
import darc
import FITS
rcond=float(sys.argv[1])
pmx=FITS.Read("pmx.fits")[1]#This contains high order DM and TT.
rmx=-numpy.linalg.pinv(pmx,rcond).T#separating out the TT from rest would be better - but I'm too lazy...
FITS.Write(rmx,"rmx%g.fits"%rcond)
d=darc.Control("main")
d.Set("rmx",rmx)
print "Saved rmx%g.fits and set in darc"%rcond
Beispiel #7
0
    def valid(self,label,val,buf):
        """Checks a value is valid.  buf is the buffer that contains all the other parameters"""
        #buf=self.guibuf
        if label=="reconstructMode":
            if(val not in ["simple","truth","open","offset"]):
                raise Exception(label)
        elif label=="windowMode":
            if val not in ["basic","adaptive","global"]:
                raise Exception(label)
        elif label in ["cameraName","mirrorName","comment","slopeName","figureName","version","configfile"]:
            if type(val)!=type(""):
                raise Exception(label)
        elif label in ["reconName","calibrateName","bufferName"]:
            if type(val) not in [type(""),type(None)]:
                raise Exception(label)
        elif label=="centroidMode":
            if type(val)==numpy.ndarray:
                nsubaps=buf.get("nsub").sum()
                try:
                    val=self.checkArray(val,nsubaps,"i")
                except:
                    print "centroidMode array wrong"
                    traceback.print_exc()
                    raise
            elif val not in ["WPU","CoG","Gaussian","CorrelationCoG","CorrelationGaussian",0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]:
                print "centroidMode not correct (%s)"%str(val)
                raise Exception(label)
        elif label in ["cameraParams","mirrorParams","slopeParams","figureParams","reconParams","calibrateParams","bufferParams"]:
            if type(val)==type(""):
                l=4-len(val)%4
                if l<4:
                    val+="\0"*l
                val=numpy.fromstring(val,dtype=numpy.int32)

            if type(val)==type([]):
                val=numpy.array(val)
            if type(val)!=type(None) and type(val)!=numpy.ndarray:
                print "ERROR in val for %s: %s"%(label,str(val))
                raise Exception(label)
        elif label in ["closeLoop","nacts","thresholdAlgo","delay","maxClipped","camerasFraming","camerasOpen","mirrorOpen","clearErrors","frameno","corrThreshType","nsubapsTogether","nsteps","addActuators","recordCents","averageImg","averageCent","kalmanPhaseSize","figureOpen","printUnused","reconlibOpen","currentErrors","xenicsExposure","calibrateOpen","iterSource","bufferOpen","bufferUseSeq","subapLocType","noPrePostThread","asyncReset","openLoopIfClip","threadAffElSize","mirrorStep","mirrorUpdate","mirrorReset","mirrorGetPos","mirrorDoMidRange","lqgPhaseSize","lqgActSize"]:
            val=int(val)
        elif label in ["dmDescription"]:
            if val.dtype.char!="h":
                raise Exception("dmDescription type not int16")
        elif label in ["actuators"]:
            val=self.checkNoneOrArray(val,None,"f")
            if val is not None:
                if val.size%buf.get("nacts")==0:
                    # shape okay... multiple of nacts.
                    pass
                else:
                    raise Exception("actuators should be array (nacts,) or (X,nacts)")
        elif label in ["actMax","actMin"]:
            nact=buf.get("nacts")
            try:
                val=self.checkArray(val,nact,None)
            except:
                print "WARNING (Check.py) - actMax/actMin as int now depreciated... this may not work (depending on which version of RTC you're running).  The error was"
                #traceback.print_exc()
                #val=int(val)
                print "Continuing... using %s"%str(val)
        #elif label in["lastActs"]:
        #    nact=buf.get("nacts")
        #    val=self.checkNoneOrArray(val,nact,"H")
        elif label in ["actInit"]:
            val=self.checkNoneOrArray(val,None,"H")
        elif label in ["actMapping"]:
            val=self.checkNoneOrArray(val,None,"i")
        elif label in ["figureActSource"]:
            val=self.checkNoneOrArray(val,None,"i")
        elif label in ["figureActScale","figureActOffset","actScale","actOffset"]:
            val=self.checkNoneOrArray(val,None,"f")
        elif label in ["actuatorMask"]:
            val=self.checkNoneOrArray(val,None,"f")
            if val is not None:
                if val.size==buf.get("nacts"):
                    # shape okay... multiple of nacts.
                    pass
                else:
                    raise Exception("actuatorMask should be array (nacts,)")
        elif label in ["actSequence"]:
            actuators=buf.get("actuators")
            if actuators is None:
                size=None
            else:
                size=actuators.size/buf.get("nacts")
            val=self.checkNoneOrArray(val,size,"i")
        elif label in ["bgImage","flatField","darkNoise","pxlWeight","calmult","calsub","calthr"]:
            val=self.checkNoneOrArray(val,(buf.get("npxlx")*buf.get("npxly")).sum(),"f")
        elif label in ["thresholdValue"]:
            if type(val)==type(""):
                if os.path.exists(val):
                    val=FITS.Read(val)[1]
                else:
                    val=eval(val)
            if type(val)==numpy.ndarray:
                npxls=(buf.get("npxlx")*buf.get("npxly")).sum()
                if val.size==npxls:
                    val=self.checkArray(val,(npxls,),"f")
                else:
                    val=self.checkArray(val,(buf.get("nsub").sum(),),"f")
            else:
                try:
                    val=float(val)
                except:
                    print "thresholdValue: %s"%str(type(val))
                    print "thresholdValue should be float or array of floats"
                    raise
        elif label in ["useBrightest"]:
            if type(val)==type(""):
                if os.path.exists(val):
                    val=FITS.Read(val)[1]
                else:
                    val=eval(val)
            if type(val)==numpy.ndarray:
                val=self.checkArray(val,(buf.get("nsub").sum(),),"i")
            else:
                try:
                    val=int(val)
                except:
                    print "%s: %s"%(label,str(type(val)))
                    print "%s should be int or array of ints size equal to total number of subapertures (valid and invalid)"%label
                    raise
        elif label in ["fluxThreshold"]:
            if type(val)==type(""):
                if os.path.exists(val):
                    val=FITS.Read(val)[1]
                else:
                    val=eval(val)
            if type(val)==numpy.ndarray:
                val=self.checkArray(val,buf.get("subapFlag").sum(),"f")
            else:
                try:
                    val=float(val)
                except:
                    print "%s: %s"%(label,str(type(val)))
                    print "%s should be float or array of floats size equal to tutal number of used subapertures"
                    raise

        elif label in ["maxAdapOffset"]:
            if type(val)==type(""):
                if os.path.exists(val):
                    val=FITS.Read(val)[1]
                else:
                    val=eval(val)
            if type(val)==numpy.ndarray:
                val=self.checkArray(val,buf.get("subapFlag").sum(),"i")
            else:
                try:
                    val=int(val)
                except:
                    print "maxAdapOffset",val
                    print "maxAdapOffset should be int or array of ints of size equal to number of valid subaps %s"%str(type(val))
                    raise
        elif label in ["powerFactor","adaptiveWinGain","corrThresh","figureGain","uEyeFrameRate","uEyeExpTime"]:
            val=float(val)
        elif label=="bleedGain":
            if type(val)==numpy.ndarray:
                if val.dtype.char!='f':
                    val=val.astype('f')
            else:
                val=float(val)
        elif label=="bleedGroups":
            val=self.checkNoneOrArray(val,buf.get("nacts"),"i")
        elif label in ["switchTime"]:
            val=self.checkDouble(val)
        elif label in ["fakeCCDImage"]:
            val=self.checkNoneOrArray(val,(buf.get("npxlx")*buf.get("npxly")).sum(),"f")
        elif label in ["centroidWeight"]:
            val=self.checkNoneOrFloat(val)
        elif label in ["gainE","E"]:
            if val is None:
                pass
            else:
                if type(val)==numpy.ndarray:
                    if val.dtype!=numpy.float32:
                        val=val.astype(numpy.float32)
                    if val.shape!=(buf.get("nacts"),buf.get("nacts")) and val.shape!=(buf.get("subapFlag").sum()*2,buf.get("nacts")):
                        raise Exception("E should be shape nacts,nacts or nslopes,nacts")
                else:#lazy - this doesn't check for nslopes,nacts...
                    val=self.checkArray(val,(buf.get("nacts"),buf.get("nacts")),"f")
        elif label in ["gainReconmxT"]:
            val=self.checkArray(val,(buf.get("subapFlag").sum()*2,buf.get("nacts")),"f")
        elif label in ["kalmanAtur"]:
            val=self.checkArray(val,(buf.get("kalmanPhaseSize"),buf.get("kalmanPhaseSize")),"f")
        elif label in ["kalmanInvN"]:
            val=self.checkNoneOrArray(val,buf.get("nacts")*buf.get("kalmanPhaseSize"),"f")
            if val is not None:#now check shape
                val=self.checkArray(val,(buf.get("nacts"),buf.get("kalmanPhaseSize")),"f")
        elif label in ["kalmanHinfDM"]:
            val=self.checkArray(val,(buf.get("kalmanPhaseSize")*3,buf.get("kalmanPhaseSize")),"f")
        elif label in ["kalmanHinfT"]:
            val=self.checkArray(val,(buf.get("subapFlag").sum()*2,buf.get("kalmanPhaseSize")*3),"f")
        elif label in ["kalmanReset","kalmanUsed","printTime","usingDMC","go","pause","switchRequested","startCamerasFraming","stopCamerasFraming","openCameras","closeCameras","centFraming","slopeOpen"]:
            val=self.checkFlag(val)
        elif label in ["nsub","ncamThreads","npxlx","npxly"]:
            val=self.checkArray(val,buf.get("ncam"),"i")
        elif label in ["pxlCnt","subapFlag"]:
            val=self.checkArray(val,buf.get("nsub").sum(),"i")
        elif label in ["refCentroids"]:
            val=self.checkNoneOrArray(val,buf.get("subapFlag").sum()*2,"f")
        elif label in ["centCalBounds"]:
            val=self.checkNoneOrArray(val,buf.get("subapFlag").sum()*2*2,"f")
        elif label in ["centCalSteps","centCalData"]:
            ncents=buf.get("subapFlag").sum()*2
            val=self.checkNoneOrArray(val,None,"f")
            if val is not None:
                nsteps=val.size/ncents
                if val.size!=nsteps*ncents:
                    raise Exception("%s wrong shape - should be multiple of %d, is %d"%(label,ncents,val.size))
        elif label in ["subapLocation"]:
            slt=buf.get("subapLocType")
            if slt==0:
                val=self.checkArray(val,(buf.get("nsub").sum(),6),"i")
            else:
                val=self.checkArray(val,None,"i")
                n=val.size//buf.get("nsub").sum()#get the size and test again
                val=self.checkArray(val,(buf.get("nsub").sum(),n),"i")
        elif label in ["subapAllocation"]:
            val=self.checkNoneOrArray(val,buf.get("nsub").sum(),"i")
        elif label in ["gain"]:
            val=self.checkArray(val,buf.get("nacts"),"f")
        elif label in ["v0"]:
            val=self.checkNoneOrArray(val,buf.get("nacts"),"f")
        elif label in ["asyncInitState","asyncScales","asyncOffsets"]:
            val=self.checkNoneOrArray(val,buf.get("nacts"),"f")
        elif label in ["asyncCombines","asyncUpdates","asyncStarts","asyncTypes"]:
            val=self.checkNoneOrArray(val,None,"i")
        elif label in ["decayFactor"]:
            val=self.checkNoneOrArray(val,buf.get("nacts"),"f")
        elif label in ["rmx"]:
            if val is None and buf.get("reconName") not in ["libreconpcg.so","libreconneural.so","libreconLQG.so","libreconcure.so"]:
                raise Exception("rmx is None")
            elif val is not None:
                val=self.checkArray(val,(buf.get("nacts"),buf.get("subapFlag").sum()*2),"f",raiseShape=1)
        elif label in ["slopeSumMatrix"]:
            val=self.checkNoneOrArray(val,None,"f")
            if (val is not None) and val.size%buf.get("nacts")!=0:
                raise Exception("slopeSumMatrix wrong size")
        elif label in ["slopeSumGroup"]:
            val=self.checkNoneOrArray(val,buf.get("subapFlag").sum()*2,"i")
            if (val is not None) and numpy.max(val)+1!=(buf.get("slopeSumMatrix").size/buf.get("nacts")):
                raise Exception("Groupings in slopeSumGroup not consistent with size of slopeSumMatrix")
        elif label in ["ncam"]:
            val=int(val)
            if val<1:
                raise Exception("Illegal ncam")
        elif label in ["threadAffinity"]:
            if val is None:
                pass
            elif type(val)==numpy.ndarray:
                if val.dtype!="i":
                    val=val.astype("i")
                if val.size%(buf.get("ncamThreads").sum()+1)!=0:
                    raise Exception("threadAffinity error (size not multiple of %d)"%(buf.get("ncamThreads").sum()+1))
            else:
                raise Exception("threadAffinity error (should be an array, or None)")
        elif label in ["threadPriority"]:
            val=self.checkNoneOrArray(val,buf.get("ncamThreads").sum()+1,"i")
        elif label in ["corrFFTPattern","corrPSF"]:
            if type(val)==numpy.ndarray:
                val=val.astype(numpy.float32)
            elif val is not None:
                raise Exception("corrFFTPattern error")
            #val=self.checkNoneOrArray(val,(buf.get("npxlx")*buf.get("npxly")).sum(),"f")
        elif label in ["adaptiveGroup"]:
            val=self.checkNoneOrArray(val,buf.get("subapFlag").sum(),"i")
        elif label in ["asyncNames"]:
            pass#no checking needed...
        elif label in ["adapWinShiftCnt"]:
            val=self.checkNoneOrArray(val,buf.get("nsub").sum()*2,"i")
        elif label in ["centIndexArray"]:
            if type(val)==type([]):
                val=numpy.array(val)
            elif type(val)==type(""):
                if os.path.exists(val):
                    print "Loading %s"%val
                    val=FITS.Read(val)[1]
                else:
                    print "File %s not found"%val
                    raise Exception("File %s not found"%val)
            if val is None:
                pass
            elif type(val)==numpy.ndarray:
                val=val.astype("f")
                fft=buf.get("corrFFTPattern",None)
                if fft is None:
                    npxls=(buf.get("npxlx")*buf.get("npxly")).sum()
                else:
                    npxls=fft.size
                if val.size not in [npxls,npxls*2,npxls*3,npxls*4]:
                    raise Exception("centIndexArray wrong size")
            else:
                raise Exception("centIndexArray")
        elif label=="actsToSend":
            val=self.checkNoneOrArray(val,None,"i")
        elif label in ["mirrorSteps","mirrorMidRange"]:#used for mirrorLLS.c
            val=self.checkArray(val,buf.get("nacts"),"i")
        elif label in ["lqgAHwfs"]:
            val=self.checkArray(val,(buf.get("lqgPhaseSize")*2,buf.get("lqgPhaseSize")),"f",raiseShape=1)
        elif label in ["lqgAtur"]:
            val=self.checkArray(val,(buf.get("lqgPhaseSize"),buf.get("lqgPhaseSize")),"f",raiseShape=1)
        elif label in ["lqgHT"]:
            val=self.checkArray(val,(buf.get("subapFlag").sum()*2,2*buf.get("lqgPhaseSize")),"f",raiseShape=1)
        elif label in ["lqgHdm"]:
            try:
                val=self.checkArray(val,(2*buf.get("lqgPhaseSize"),buf.get("nacts")),"f",raiseShape=1)
            except:
                val=self.checkArray(val,(2,2*buf.get("lqgPhaseSize"),buf.get("nacts")),"f",raiseShape=1)
                
        elif label in ["lqgInvN"]:
            try:
                val=self.checkArray(val,(buf.get("nacts"),buf.get("lqgPhaseSize")),"f",raiseShape=1)
            except:
                val=self.checkArray(val,(2,buf.get("nacts"),buf.get("lqgPhaseSize")),"f",raiseShape=1)

        elif label in ["lqgInvNHT"]:
            val=self.checkArray(val,(buf.get("subapFlag").sum()*2,buf.get("nacts")),"f",raiseShape=1)

        elif CustomCheck is not None:
            val=CustomCheck.valid(label,val,buf)
        else:
            print "Unchecked parameter %s"%label
                                      
        return val
Beispiel #8
0
def loadBuf(fname, hdu=0):
    data = FITS.Read(fname)[hdu * 2 + 1]
    b = Buffer(None, size=data.size)
    b.assign(data)
    return b
Beispiel #9
0
import controlCorba
import FITS
import sys
import time
file="tmp.fits"
if len(sys.argv)>1:
    file=sys.argv[1]

#Create the corba client
c=controlCorba.controlClient()

def set(name,val,com="",swap=1,check=1):
    c.obj.Set(controlCorba.sdata(name),controlCorba.encode([val]),controlCorba.sdata(com),swap,check)
    #time.sleep(0.01)

set("fakeCCDImage",FITS.Read("shimage.fits")[1][0])
FITS.Write(controlCorba.decode(c.obj.AverageCentroids(1)),file)

set("thresholdAlgorithm",2)
FITS.Write(controlCorba.decode(c.obj.AverageCentroids(1)),file,writeMode="a")

set("thresholdAlgorithm",0)
FITS.Write(controlCorba.decode(c.obj.AverageCentroids(1)),file,writeMode="a")

set("thresholdValue",0)
FITS.Write(controlCorba.decode(c.obj.AverageCentroids(1)),file,writeMode="a")

set("thresholdAlgorithm",1)
FITS.Write(controlCorba.decode(c.obj.AverageCentroids(1)),file,writeMode="a")

set("thresholdAlgorithm",2)
Beispiel #10
0
 "nacts":nacts,
 "ncam":ncam,
 "nsub":nsub,
 "npxly":npxly,
 "npxlx":npxlx,
 "ncamThreads":ncamThreads,
 "pxlCnt":pxlCnt,
 "subapLocation":subapLocation,
 "bgImage":bgImage,
 "darkNoise":darkNoise,
 "closeLoop":1,
 "flatField":flatField,#numpy.random.random((npxls,)).astype("f"),
 "thresholdValue":1.0,
 "powerFactor":1.,#raise pixel values to this power.
 "subapFlag":subapFlag,
 "fakeCCDImage":FITS.Read("/home/ali/pyr.fits")[1],#None,#(numpy.random.random((npxls,))*20).astype("f"),
 "printTime":0,#whether to print time/Hz
 "rmx":rmx,#numpy.random.random((nacts,ncents)).astype("f"),
 "gain":numpy.ones((nacts,),"f"),
 "E":numpy.zeros((nacts,nacts),"f"),#E from the tomoalgo in openloop.
 "threadAffinity":None,
 "threadPriority":numpy.ones((ncamThreads.sum()+1,),numpy.int32)*10,
 "delay":10000,#will usually be zero (except if you want to set your own frame rate, e.g. if loading images from a file)
 "clearErrors":0,
 "camerasOpen":0,
 "cameraName":"libcamfile.so",#"libsl240Int32cam.so",#"camfile",
 "cameraParams":cameraParams,
 "mirrorName":"libmirrorSL240.so",
 "mirrorParams":mirrorParams,
 "mirrorOpen":0,
 "frameno":0,
Beispiel #11
0
dmDescription[0] = 1  #1 DM
dmDescription[1] = 8  #1st DM has nacts linear actuators
tmp = dmDescription[2:]
tmp[:] = -1
tmp.shape = 8, 8
dmflag = tel.Pupil(8, 4, 0).fn.ravel()
numpy.put(tmp, dmflag.nonzero()[0], numpy.arange(52))

corrClip = 1
corrNStore = 20
corrThresh = 0.0
corrThreshType = 2  #CORR_FRAC_SUB
corrUpdateGain = 0.
centroidMode = "CorrelationCoG"

psf = FITS.Read(fname.strip("\0"))[1].mean(0).ravel() - bgImage
psf = numpy.where(psf < 0, 0, psf)

import correlation
corrdata = correlation.transformPSF(
    psf, ncam, npxlx, npxly, nsub, subapLocation, subapFlag, pad=8
)  #Note - to get identical slope estimates when doing auto correlation update and using the correlation result for shift and add (corrUpdateToCoG=0), probably need pad to be larger, to avoid wrapping.  But in practice, the difference in results is small.
corrFFTPattern = corrdata["corrFFTPattern"]
corrSubapLoc = corrdata["corrSubapLoc"]
corrNpxlx = corrdata["corrNpxlx"]
corrNpxlCum = corrdata["corrNpxlCum"]

#Now populate the control structure - this is what gets used.

control = {
    "switchRequested":
Beispiel #12
0
        if rmx.shape[1] != gainmx.shape[0]:
            transpose = 1
            rmx = rmx.T
        gainmx = numpy.dot(rmx, gainmx)
        if transpose:
            gainmx = gainmx.T
    return gainmx


if __name__ == "__main__":
    import sys
    import FITS
    if len(sys.argv) < 5:
        print(
            "Usage: %s globalGain [modal,gain,list] output.fits slopeToZernMx.fits optionalRmx"
            % sys.argv[0])
        sys.exit(0)
    gain = sys.argv[1]
    modalGainList = eval(sys.argv[2])
    outMx = sys.argv[3]
    slopeToZernMx = FITS.Read(sys.argv[4])[1]
    if slopeToZernMx[0].std() == 0:  #first row all zeros - probably piston
        print("Stripping piston from %s" % sys.argv[4])
        slopeToZernMx = slopeToZernMx[1:]
    rmx = None
    if len(sys.argv) > 5:
        rmx = FITS.Read(sys.argv[5])[1]
    gmx = computeModalGainMx(gain, modalGainList, slopeToZernMx, rmx)

    FITS.Write(gmx, outMx)