def __init__(self, coordList, gridArray, pointsArray=None, pointsFile=None, myMethod='sbs', methodVal=None, debugFlag=False, title=""): """ initialize the class """ self.debugFlag = debugFlag self.title = title self.nCoord = len(coordList) self.coordList = coordList # vignetting HARDCODED self.radiusVignetted = 225.0 # decam info self.decam = decaminfo() # Array with interpolation grid size and number of points # should contain a 4 tuple of [ny,ylo,yhi,nx,xlo,xhi] for each nCoord # these ylo,yhi and xlo,xhi should be the region EDGES self.gridArray = gridArray.copy() # contains an array of Points for each nCoord # [npoints,0] is the X value # [npoints,1] is the Y value # [npoints,2] is the Z value # [npoints,3] is the Weight value # the arrays are stored in a Python dictionary, keyed by nCoord index # NOTE: nothing in this code enforces that pointArray has this content!!! if pointsArray != None: self.pointsArray = pointsArray.copy() elif pointsFile != None: self.readPointsFromFile(pointsFile) else: print("PointMesh: no input points") # construct the interpolation grid for each coordinate system self.myMethod = myMethod self.methodVal = methodVal self.interpPresent = False if self.checkMethod(myMethod, methodVal): self.interpPresent = True self.makeInterpolation(self.myMethod, self.methodVal)
def __init__(self,coordList,gridArray,pointsArray=None,pointsFile=None,myMethod='sbs',methodVal=None,debugFlag=False,title=""): """ initialize the class """ self.debugFlag = debugFlag self.title = title self.nCoord = len(coordList) self.coordList = coordList # vignetting HARDCODED self.radiusVignetted = 225.0 # decam info self.decam = decaminfo() # Array with interpolation grid size and number of points # should contain a 4 tuple of [ny,ylo,yhi,nx,xlo,xhi] for each nCoord # these ylo,yhi and xlo,xhi should be the region EDGES self.gridArray = gridArray.copy() # contains an array of Points for each nCoord # [npoints,0] is the X value # [npoints,1] is the Y value # [npoints,2] is the Z value # [npoints,3] is the Weight value # the arrays are stored in a Python dictionary, keyed by nCoord index # NOTE: nothing in this code enforces that pointArray has this content!!! if pointsArray!=None: self.pointsArray = pointsArray.copy() elif pointsFile!=None: self.readPointsFromFile(pointsFile) else: print "PointMesh: no input points" # construct the interpolation grid for each coordinate system self.myMethod = myMethod self.methodVal = methodVal self.interpPresent = False if self.myMethod=='sbs' or self.myMethod=='rbf' or self.myMethod=='tmean' or self.myMethod=='grid' or self.myMethod == "idw": self.interpPresent = True self.makeInterpolation(self.myMethod,self.methodVal)
def findDonuts(dataAmp, xOffset, inputDict, extName): """ find donuts in the data array """ nBlock = inputDict["nBlock"] fluxThreshold = inputDict["fluxThreshold"] kNNFind = inputDict["kNNFind"] distanceLimit = inputDict["distanceLimit"] fluxMinCut = inputDict["fluxMinCut"] fluxMaxCut = inputDict["fluxMaxCut"] npixelsMinCut = inputDict["npixelsMinCut"] npixelsMaxCut = inputDict["npixelsMaxCut"] nDonutWanted = inputDict[ "nDonutWanted"] // 2 # divide by 2 for 2 amplifiers ellipCut = inputDict["ellipCut"] # info about CCDs dinfo = decaminfo() # time it startingTime = time.clock() # list for output of donuts donutList = [] # convert from 2048 by 1024 to 128 by 64, by python magic dataBlockView = block_view(dataAmp, (nBlock, nBlock)) dataBlock = dataBlockView.sum(2).sum(2) # find sky background and subtract skyBkg = calcSky(dataBlock) dataBlock = dataBlock - skyBkg # zero edge values - they are screwy dataBlock[0, :] = 0.0 dataBlock[-1, :] = 0.0 dataBlock[:, -1] = 0.0 dataBlock[:, 0] = 0.0 # zero pixels lower than the threshold dataPeak = numpy.where(dataBlock > fluxThreshold, dataBlock, 0.) # keep track of which pixels are above threshold too # = 1 is > threshold, =0 is below # later we'll use this array to keep track of which pixels # aren't in a cluster yet dataOn = numpy.where(dataBlock > fluxThreshold, 1, 0) # find list of pixels that are non-zero nzList = numpy.argwhere(dataPeak).tolist() numOverThreshold = len(nzList) # build a kdTree to locate nearest neighbors kdtree = cKDTree(nzList) # also sort the array, the [::-1] is python magic to reverse the order of the array! ny, nx = dataPeak.shape dataPeakFlat = dataPeak.reshape(ny * nx) indSort = numpy.argsort(dataPeakFlat)[::-1] # get the sorted indices as a tuple of iy,ix 'es ixSort = numpy.mod(indSort, nx).tolist() iySort = ((indSort - ixSort) // nx).tolist() iyxSort = list(zip(iySort, ixSort)) # now loop over pixels in sorted order # but only look at those above the threshold for i in range(numOverThreshold): # get the iy,ix tuple iyx = iyxSort[i] # check that this pixel is still available if dataOn[iyx] == 1: # try this pixel as the center of a donut # find all nearby overthreshold pixels d, ind = kdtree.query(iyx, k=kNNFind, distance_upper_bound=distanceLimit) # get the centroid of these guys, sum the flux # looks like we have to loop tempX = numpy.zeros(kNNFind) tempY = numpy.zeros(kNNFind) tempV = numpy.zeros(kNNFind) nOk = 0 nLengthInd = len(ind) for i in range(nLengthInd): # if we don't find enough neighbors, the others have d==inf and ind=nLength if ind[i] < numOverThreshold: iy, ix = nzList[ind[i]] # check that this pixel is still available if dataOn[iy, ix] == 1: nOk = nOk + 1 tempY[i] = iy tempX[i] = ix tempV[i] = dataPeak[iy, ix] # remove from dataOn array, so we don't reuse dataOn[iy, ix] = 0 # now all the neighbors are collected # calculate flux and centroid and ellipticity, see if its a good guy! if nOk > npixelsMinCut: # calculate flux, centroid and moments flux = tempV.sum() xCentroid = (tempV * tempX).sum() / flux yCentroid = (tempV * tempY).sum() / flux xDiff = tempX - xCentroid yDiff = tempY - yCentroid xxMoment = (tempV * xDiff * xDiff).sum() / flux yyMoment = (tempV * yDiff * yDiff).sum() / flux xyMoment = (tempV * xDiff * yDiff).sum() / flux if (xxMoment + yyMoment) > 1.e-10: ellip1 = (xxMoment - yyMoment) / (xxMoment + yyMoment) ellip2 = 2.0 * xyMoment / (xxMoment + yyMoment) else: ellip1 = 0.0 ellip2 = 0.0 # check if this guy passes the cuts # calculate the pixels ixDonut = int(xCentroid * nBlock) + nBlock // 2 + xOffset iyDonut = int(yCentroid * nBlock) + nBlock // 2 # calculate rdecam xdecam, ydecam = dinfo.getPosition(extName, ixDonut, iyDonut) rdecam = numpy.sqrt(xdecam * xdecam + ydecam * ydecam) if nOk < npixelsMaxCut and flux > fluxMinCut and flux < fluxMaxCut and numpy.abs( ellip1) < ellipCut and numpy.abs( ellip2) < ellipCut and rdecam < 225.0: # make output list of Dictionaries # convert x,y to 2048x2048 coordinates info = {"x": ixDonut, "y": iyDonut, "mag": flux} donutList.append(info) if len(donutList) >= nDonutWanted: return donutList # clear all guys nearby too # for j in range(len(ind)): # if d[j]<3.0*distanceLimit: # iy,ix = nzList[ind[j]] # dataOn[iy,ix] = 0 # Done! return donutList
def __init__(self, **inputDict): # init contains all initializations which are done only once for all fits # parameters in fixParamArray1 are nEle,rzero,bkgd,Z2,Z3,Z4,....Z11 self.paramDict = { "nZernikeTerms": 11, "nFits": 1, "fixedParamArray1": [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1], #need defaults up to quadrefoil "debugFlag": False, "outputWavefront": False, "outputDiff": True, "outputChi2": False, "printLevel": 1, "maxIterations": 1000, "calcRzeroDerivative": True } # search for key in inputDict, change defaults self.paramDict.update(inputDict) # setup the fit engine self.gFitFunc = donutengine(**self.paramDict) # need dummy versions before calling self.chisq self.imgarray = numpy.zeros(1) self.weight = numpy.ones(1) self.sigmasq = numpy.ones(1) # get decam info or desi info if self.paramDict["iTelescope"] == 6 or self.paramDict[ "iTelescope"] == 7 or self.paramDict["iTelescope"] == 8: print('This is for DESI CI') from donutlib.desiutil import desiciinfo self.dInfo = desiciinfo() elif self.paramDict["iTelescope"] == 5: print('This is for DESI GFA') from donutlib.desiutil import desiinfo self.dInfo = desiinfo() else: print('This is for DECam') from donutlib.decamutil import decaminfo self.dInfo = decaminfo() # setup MINUIT self.gMinuit = ROOT.TMinuit(self.gFitFunc.npar) self.gMinuit.SetFCN(self.chisq) # arglist is for the parameters in Minuit commands arglist = array('d', 10 * [0.]) ierflg = ctypes.c_int(1982) #L ROOT.Long(1982) # set the definition of 1sigma arglist[0] = 1.0 self.gMinuit.mnexcm("SET ERR", arglist, 1, ierflg) # turn off Warnings arglist[0] = 0 self.gMinuit.mnexcm("SET NOWARNINGS", arglist, 0, ierflg) # set printlevel arglist[0] = self.paramDict["printLevel"] self.gMinuit.mnexcm("SET PRINTOUT", arglist, 1, ierflg) # do initial setup of Minuit parameters # status/limit arrays for Minuit parameters self.startingParam = numpy.zeros(self.gFitFunc.npar) self.errorParam = numpy.ones(self.gFitFunc.npar) self.loParam = numpy.zeros(self.gFitFunc.npar) self.hiParam = numpy.zeros(self.gFitFunc.npar) self.paramStatusArray = numpy.zeros( self.gFitFunc.npar) # store =0 Floating, =1 Fixed # Set starting values and step sizes for parameters # (note that one can redefine the parameters, so this method can be called multiple times) for ipar in range(self.gFitFunc.npar): self.gMinuit.DefineParameter(ipar, self.gFitFunc.parNames[ipar], self.startingParam[ipar], self.errorParam[ipar], self.loParam[ipar], self.hiParam[ipar])
def __init__(self, **inputDict): """ initialize """ # initialize the parameter Dictionary, and update defaults from inputDict self.paramDict = { "inputFile": "", "wfmFile": "", "wfmArray": None, "writeToFits": False, "outputPrefix": "testone", "xDECam": 0.0, "yDECam": 0.0, "debugFlag": False, "rootFlag": False, "iTelescope": 0, "waveLength": 700.0e-9, "nZernikeTerms": 37, "nbin": 512, "nPixels": 64, "gridCalcMode": True, "pixelOverSample": 8, "scaleFactor": 1., "rzero": 0.125, "nEle": 1.0e6, "background": 4000., "randomFlag": False, "randomSeed": 209823, # if this is an invalid integer, crazy errors will ensue "gain": 1.0, "flipFlag": False, "ZernikeArray": [] } self.paramDict.update(inputDict) # check parameters are ok if self.paramDict["nbin"] != self.paramDict[ "nPixels"] * self.paramDict["pixelOverSample"]: print("makedonut: nbin must = nPixels * pixelOverSample !!!") sys.exit(1) # also require that _Lu > 2R, ie. that pupil fits in pupil plane # this translates into requiring that (Lambda F / pixelSize) * pixelOverSample * scaleFactor > 1 # Why does this depend on scaleFactor, but not Z4?? Answer: scaleFactor effectively changes the wavelength, so # it must be included. It is also possible that Z4 is too big for the nPixels - buts that another limit than this one F = 2.9 # hardcode for DECam for now pixelSize = 15.e-6 if self.paramDict["pixelOverSample"] * self.paramDict["scaleFactor"] * ( self.paramDict["waveLength"] * F / pixelSize) < 1.: print("makedonut: ERROR pupil doesn't fit!!!") print( " value = ", self.paramDict["pixelOverSample"] * self.paramDict["scaleFactor"] * (self.paramDict["waveLength"] * F / pixelSize)) #sys.exit(2) # for WFM, need to turn gridCalcMode to False for donutengine #if self.paramDict["useWFM"]: # self.paramDict["gridCalcMode"] = False # # don't do this by default, may need it if Zemax is used, but not if correct bins sizes are used. # and it isn't coded with c++ donutengine yet either... # declare fit function self.gFitFunc = donutengine(**self.paramDict) # DECam info self.dinfo = decaminfo() # set random seed numpy.random.seed(self.paramDict["randomSeed"])
def __init__(self,**inputDict): # init contains all initializations which are done only once for all fits # parameters in fixParamArray1 are nEle,rzero,bkgd,Z2,Z3,Z4,....Z11 self.paramDict = {"nZernikeTerms":11, "nFits":1, "fixedParamArray1":[0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1], #need defaults up to quadrefoil "debugFlag":False, "outputWavefront":False, "outputDiff":True, "outputChi2":False, "printLevel":1, "maxIterations":1000} # search for key in inputDict, change defaults self.paramDict.update(inputDict) # setup the fit engine self.gFitFunc = donutengine(**self.paramDict) # need dummy versions before calling self.chisq self.imgarray = numpy.zeros(1) self.weight = numpy.ones(1) self.sigmasq = numpy.ones(1) # get decam info self.decamInfo = decaminfo() # setup MINUIT self.gMinuit = ROOT.TMinuit(self.gFitFunc.npar) self.gMinuit.SetFCN( self.chisq ) # arglist is for the parameters in Minuit commands arglist = array( 'd', 10*[0.] ) ierflg = ROOT.Long(1982) # set the definition of 1sigma arglist[0] = 1.0 self.gMinuit.mnexcm( "SET ERR", arglist, 1, ierflg ) # turn off Warnings arglist[0] = 0 self.gMinuit.mnexcm("SET NOWARNINGS", arglist,0,ierflg) # set printlevel arglist[0] = self.paramDict["printLevel"] self.gMinuit.mnexcm("SET PRINTOUT", arglist,1,ierflg) # do initial setup of Minuit parameters # status/limit arrays for Minuit parameters self.startingParam = numpy.zeros(self.gFitFunc.npar) self.errorParam = numpy.ones(self.gFitFunc.npar) self.loParam = numpy.zeros(self.gFitFunc.npar) self.hiParam = numpy.zeros(self.gFitFunc.npar) self.paramStatusArray = numpy.zeros(self.gFitFunc.npar) # store =0 Floating, =1 Fixed # Set starting values and step sizes for parameters # (note that one can redefine the parameters, so this method can be called multiple times) for ipar in range(self.gFitFunc.npar): self.gMinuit.DefineParameter(ipar,self.gFitFunc.parNames[ipar],self.startingParam[ipar],self.errorParam[ipar],self.loParam[ipar],self.hiParam[ipar])
def findDonuts(dataAmp,xOffset,inputDict,extName): """ find donuts in the data array """ nBlock = inputDict["nBlock"] fluxThreshold = inputDict["fluxThreshold"] kNNFind = inputDict["kNNFind"] distanceLimit = inputDict["distanceLimit"] fluxMinCut = inputDict["fluxMinCut"] fluxMaxCut = inputDict["fluxMaxCut"] npixelsMinCut = inputDict["npixelsMinCut"] npixelsMaxCut = inputDict["npixelsMaxCut"] nDonutWanted = inputDict["nDonutWanted"]/2 # divide by 2 for 2 amplifiers ellipCut = inputDict["ellipCut"] # info about CCDs dinfo = decaminfo() # time it startingTime = time.clock() # list for output of donuts donutList = [] # convert from 2048 by 1024 to 128 by 64, by python magic dataBlockView = block_view(dataAmp,(nBlock,nBlock)) dataBlock = dataBlockView.sum(2).sum(2) # find sky background and subtract skyBkg = calcSky(dataBlock) dataBlock = dataBlock - skyBkg # zero edge values - they are screwy dataBlock[0,:] = 0.0 dataBlock[-1,:] = 0.0 dataBlock[:,-1] = 0.0 dataBlock[:,0] = 0.0 # zero pixels lower than the threshold dataPeak = numpy.where(dataBlock>fluxThreshold,dataBlock,0.) # keep track of which pixels are above threshold too # = 1 is > threshold, =0 is below # later we'll use this array to keep track of which pixels # aren't in a cluster yet dataOn = numpy.where(dataBlock>fluxThreshold,1,0) # find list of pixels that are non-zero nzList = numpy.argwhere(dataPeak).tolist() numOverThreshold = len(nzList) # build a kdTree to locate nearest neighbors kdtree = cKDTree(nzList) # also sort the array, the [::-1] is python magic to reverse the order of the array! ny,nx = dataPeak.shape dataPeakFlat = dataPeak.reshape(ny*nx) indSort = numpy.argsort(dataPeakFlat)[::-1] # get the sorted indices as a tuple of iy,ix 'es ixSort = numpy.mod(indSort,nx).tolist() iySort = ((indSort - ixSort)/nx).tolist() iyxSort = zip(iySort,ixSort) # now loop over pixels in sorted order # but only look at those above the threshold for i in range(numOverThreshold): # get the iy,ix tuple iyx = iyxSort[i] # check that this pixel is still available if dataOn[iyx]==1: # try this pixel as the center of a donut # find all nearby overthreshold pixels d,ind = kdtree.query(iyx,k=kNNFind,distance_upper_bound=distanceLimit) # get the centroid of these guys, sum the flux # looks like we have to loop tempX = numpy.zeros(kNNFind) tempY = numpy.zeros(kNNFind) tempV = numpy.zeros(kNNFind) nOk = 0 nLengthInd = len(ind) for i in range(nLengthInd): # if we don't find enough neighbors, the others have d==inf and ind=nLength if ind[i]<numOverThreshold: iy,ix = nzList[ind[i]] # check that this pixel is still available if dataOn[iy,ix] == 1: nOk = nOk + 1 tempY[i] = iy tempX[i] = ix tempV[i] = dataPeak[iy,ix] # remove from dataOn array, so we don't reuse dataOn[iy,ix] = 0 # now all the neighbors are collected # calculate flux and centroid and ellipticity, see if its a good guy! if nOk>npixelsMinCut: # calculate flux, centroid and moments flux = tempV.sum() xCentroid = (tempV*tempX).sum()/flux yCentroid = (tempV*tempY).sum()/flux xDiff = tempX - xCentroid yDiff = tempY - yCentroid xxMoment = (tempV*xDiff*xDiff).sum()/flux yyMoment = (tempV*yDiff*yDiff).sum()/flux xyMoment = (tempV*xDiff*yDiff).sum()/flux if (xxMoment+yyMoment) > 1.e-10: ellip1 = (xxMoment - yyMoment)/(xxMoment + yyMoment) ellip2 = 2.0*xyMoment/(xxMoment+yyMoment) else: ellip1 = 0.0 ellip2 = 0.0 # check if this guy passes the cuts # calculate the pixels ixDonut = int(xCentroid * nBlock) + nBlock/2 + xOffset iyDonut = int(yCentroid * nBlock) + nBlock/2 # calculate rdecam xdecam,ydecam = dinfo.getPosition(extName,ixDonut,iyDonut) rdecam = numpy.sqrt(xdecam*xdecam + ydecam*ydecam) if nOk<npixelsMaxCut and flux>fluxMinCut and flux<fluxMaxCut and numpy.abs(ellip1)<ellipCut and numpy.abs(ellip2)<ellipCut and rdecam<225.0: # make output list of Dictionaries # convert x,y to 2048x2048 coordinates info = {"x":ixDonut,"y":iyDonut,"mag":flux} donutList.append(info) if len(donutList) >= nDonutWanted: return donutList # clear all guys nearby too # for j in range(len(ind)): # if d[j]<3.0*distanceLimit: # iy,ix = nzList[ind[j]] # dataOn[iy,ix] = 0 # Done! return donutList
def __init__(self,**inputDict): """ initialize """ # initialize the parameter Dictionary, and update defaults from inputDict self.paramDict = {"inputFile":"", "wfmFile":"", "wfmArray":None, "writeToFits":False, "outputPrefix":"testone", "xDECam":0.0, "yDECam":0.0, "debugFlag":False, "rootFlag":False, "iTelescope":0, "waveLength":700.0e-9, "nZernikeTerms":37, "nbin":512, "nPixels":64, "gridCalcMode":True, "pixelOverSample":8, "scaleFactor":1., "rzero":0.125, "nEle":1.0e6, "background":4000., "randomFlag":False, "randomSeed":209823, # if this is an invalid integer, crazy errors will ensue "gain":1.0, "flipFlag":False, "ZernikeArray":[]} self.paramDict.update(inputDict) # check parameters are ok if self.paramDict["nbin"] != self.paramDict["nPixels"]*self.paramDict["pixelOverSample"]: print "makedonut: nbin must = nPixels * pixelOverSample !!!" sys.exit(1) # also require that _Lu > 2R, ie. that pupil fits in pupil plane # this translates into requiring that (Lambda F / pixelSize) * pixelOverSample * scaleFactor > 1 # Why does this depend on scaleFactor, but not Z4?? Answer: scaleFactor effectively changes the wavelength, so # it must be included. It is also possible that Z4 is too big for the nPixels - buts that another limit than this one F = 2.9 # hardcode for DECam for now pixelSize = 15.e-6 if self.paramDict["pixelOverSample"] * self.paramDict["scaleFactor"] * (self.paramDict["waveLength"] * F / pixelSize) < 1. : print "makedonut: ERROR pupil doesn't fit!!!" print " value = ",self.paramDict["pixelOverSample"] * self.paramDict["scaleFactor"] * (self.paramDict["waveLength"] * F / pixelSize) #sys.exit(2) # for WFM, need to turn gridCalcMode to False for donutengine #if self.paramDict["useWFM"]: # self.paramDict["gridCalcMode"] = False # # don't do this by default, may need it if Zemax is used, but not if correct bins sizes are used. # and it isn't coded with c++ donutengine yet either... # declare fit function self.gFitFunc = donutengine(**self.paramDict) # DECam info self.dinfo = decaminfo() # set random seed numpy.random.seed(self.paramDict["randomSeed"])