From 4122183a540dfd235dc115536b46c704159bb298 Mon Sep 17 00:00:00 2001 From: rfetick <r.fetick@gmail.com> Date: Mon, 27 May 2019 18:30:27 +0200 Subject: [PATCH] Add functions in instrument.py --- paompy/__pycache__/instrument.cpython-36.pyc | Bin 208 -> 4625 bytes paompy/__pycache__/utils.cpython-36.pyc | Bin 5661 -> 5565 bytes paompy/instrument.py | 127 +++++++++++++++++++ 3 files changed, 127 insertions(+) diff --git a/paompy/__pycache__/instrument.cpython-36.pyc b/paompy/__pycache__/instrument.cpython-36.pyc index 60647b04140b2e9681e454842f07a3fa53851a19..915fdb330ce7eaeb4bbba25aedb467e8b5beddc1 100644 GIT binary patch literal 4625 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 Ko9{Q3X6-*Q`$vob delta 100 zcmbQJa)Hsnn3tDpGt--xJO&1a$3P4Rj6jwH5EpX*i4=w?h7`tN22G}kODskGG#PKP m$H%ASC&$OHWGG?+Dkx%_9Kq};Xp@_tQks)$#}3j6#0&tuv=fp5 diff --git a/paompy/__pycache__/utils.cpython-36.pyc b/paompy/__pycache__/utils.cpython-36.pyc index cf5630f41dc860396ee1340f3c0391cf5401bb68..b49526342a64130321eef33d19fbb9dedd266e10 100644 GIT binary patch delta 1301 zcmZ8g&2Jk;6yKTMwbyHV?Gl@|v=LS%+H7h<^Kq(5K9sbfs7foh64LS!ZFi>jhW*l8 zr;SfOkPG5~(3S&-N*uW4>=OrW`~jSY0|>4h;L3@4<0v?t(fsDk%zMB6y|**3x<B0< zuh#4KhvmOM`Swjs`%{}~hO{^3$Uy?rJdF`XBjQmx>yaKCo<VTWh|IX;m6T1RvR7s% zrw7&*jg?xOSJ~BAnOVmgv$*|*?p4_wt1$bRcr{jKwc{(AS7$Beu!h`nSd(2i*1QIz zk2Sab%^#a>BIv<$mx$W_qu%|!C;QtEA3W?$o|Er&ViXt6E-{N8^POwD)F{kg7{=Vy zg^}~<8JM_d_|VT!G-wxJnLETSeldT&SCR*NZV50$s3BAkstD7de2~6?Hm?5%SszVQ z!XyA5^JI9Z_^0&y@{~%Sp{k#cQt>L($UhIW-3hfgDV5R5D&h*PT|g7%PdOTBDNRTu z^e`C;nq<O+^e|yljdn3--)x;%2A8D!qoQYrV;d<{GG{!XXfZdqh_tnQ=numn=EFhC z;4<#Ng@7b8DW8c~+HjR)Dpt)PGo3nfwQ8-Rd;+RXZdY}E9t-1^g%O4MQ0Q@(Kohwg zg!#gAZd^LAUzCFo0w17XeCNDPR*N5<AIM4ZS>tN4MX!&Kx}(nfog`a|`w+5^Z{1$L z)kXN!?#Q;jzTRQ}(3dU??=HKGi$|TsQ)_h2VgG5ENGFL&nDiGgrn}-Q7X?62pVDr^ zytIXx5B!W%xLUkytgXDR`IP8O>6v4Gnr)M&?2hVP0vnTm8!ss-6<@z`eXJ^=SZNl* zs-k}};K1eW_Cpx$4|tSukT>%^JTr1X&V-%@fiTmU_kBS?m|?>B(ab-Z-YpD&C4;6a zE?dN+O*w2i918d4NnlLY=AMv`FuA@QvNbnhQBJ3;zc*Y8RIY`dAI7c;yV8bx2zL=a zP)ES?*FFy0^5Ey<w^n<M)(PF)a|t|<rkpl$YQln?gqa-1*=SnUdLD$?XerNl5c-k& ztXI$cR5~mLY4R-WPv3-km|GZa_qKLcwtCx-?{14y`t*PY!|98`I>H9R4(6%k%t$=D i!@{}~r|dA|>-hTemIQ-Zq$ay%I!3c+U$a{FjsF0TcL@0a delta 1393 zcmZ8h&2Jk;6yMnod%anI#CDpbPFpJ#R92%1LMy0*AR$evK<YwT4qYLoo1Jws>F(OR zSyKfLIgk?q1X{R6LgK)sLL4BsN<DCeBe&@V35f$jf<J-x)+J5r(fr<<_vZcP&D%GA zc=4OL{g=vR=M(Gi_r5=+X@6)ZekSURIOPKbu6Y_~T#uNiqckETHa#=8JS#4E1x7wI zD#o^F=eiY@V#jlGy%3GXuIJ`@F)GIuuafI}RQ0MnVBC&s@whks*jV@K`9Te@!AqgO z+iYpvX=>iYHI0vP_dw%rc<N)ro8*(c%qs`Xo8nboJJ7soKE><2ftJ&}$tTd#;`&Xk zGyUb^;w?kjy<RGJL@!k)Y75E|Bsxs#yB{FBn{RKdb#HAh-&nt~fot=g4++Y06#6pV zl<yCH2qhXy5ezp2KiCO>{O4PPIoTKH92?6Xn$OJ^uu{qjQW1w8Lzyy+dN4*d(}!(& zUxQX=T36Y8wq`wAb<xr76u?0Vb%H9vIKe1L?)2|Li`GwI2A8TNk^sUuOwy%nxA6Om zBP!zrRpaTXJU$OK<y|pYKl-Q`vO<|QRkA;AxHL&Br9a}BAT7^{h?F6cRO!h;S<oLQ ze3WA?`?PcszYgv^riZh*d^h{GByQKpkzeMR2Xb1v8=OH<u1x(@1aX+|^f{a(dz*kr zPF(p3JC*8m_L*~zIY&P@CF2ZTyi-(WBxI_LSR{a5tU;6DeD+)U!Yfbbr;34qzz2wM zhorsQgw0&`|7@b(WV1S4$rdW#y*%@VNZNkV7O}q_wzu}$e!J%fX&>5m?%n}Lr{oz} za2|DK$sK<X!fbX}y|nP`!CN9pM6&%kZj@9TO?OxgM<pL~3|4-seWf!u`?~&oHNQp9 zsSgAu^Gm&DUB(zM`>Q@P@eH-;3)nl%T8(MeJ-Xbu&Gsp&Z8}5KYK!m!ipQ&eU+?H( z;aVAT7<VjKM;+cGc$46I?!rDlQGRM0SVQ<3rzC34XzDgw)z9ipmV55&-EN1$JLp2O zx=(Tj=20js8ODRXygptj*XQxsfsQ^f2<UG{m1Q6Xd-HM-2Evc>488Ke?_=nE&`)|| zJ8w>9)1$;HN+?oTWfayQ;ENL<hF}w6Rm1aDsW(jUOZ6iOCEBV(sBG@1Aw5pGMkZ%t z>FUDL#`4XTWmV{J?S?@*>i#Q4vqI1%pu3-_$8kF<`_;J5hf(+%B_pY8O{`0kO}W@c SG^nj=R>iDsIJ36vT=)-v9x5yV diff --git a/paompy/instrument.py b/paompy/instrument.py index 18f721c..d5f2807 100644 --- a/paompy/instrument.py +++ b/paompy/instrument.py @@ -6,3 +6,130 @@ Created on Mon May 27 17:30:51 2019 @author: rfetick """ +from paompy.utils import circarr, airy, RAD2ARCSEC +from paompy.config import _DEFAULT_RES + +#%% DETECTOR CLASS AND ITS SUBCLASSES + +class Detector(object): + """Represents a detector + + Attributes + ---------- + resolution : float + Pixel scale [meter] + Npix : tuple, list, numpy.ndarray + Number of pixels on X and Y axis + gainADU : float + Detector gain [electron/ADU] + RON : float + Read-Out-Noise [electron] + + """ + + def __init__(self,Npix,resolution=_DEFAULT_RES,gainADU=1.,RON=0.): + self.resolution_pixel = resolution + self.Npix = Npix + self.gainADU = gainADU + self.RON = RON + self.binning = 1 + + def __repr__(self): + s = "PAOMPY Detector\n" + s += "---------------\n" + s += "Pixels : (%u,%u)\n" % (self.Npix[0],self.Npix[1]) + s += "Resolution: %u um\n" % round(self.resolution*1e6) + s += "Binning : %u\n" % self.binning + s += "Gain ADU : %.2f e-/ADU\n" % self.gainADU + s += "RON : %.2f e-" % self.RON + return s + + @property + def resolution(self): + return self.resolution_pixel * self.binning + + +ZIMPOL_DETECTOR = Detector((1024,1024),30*1e-6,gainADU=10.5,RON=20.) + +# Equivalent detector resolution after image reduction pipeline +MUSE_DETECTOR = Detector((200,200),237.14745*1e-6,gainADU=5.,RON=15.) + + + + +#%% INSTRUMENT CLASS AND ITS SUBCLASSES + +class Instrument(object): + """Represents an optical system + + Attributes + ---------- + D : float + Entrance pupil diameter [meter] + detector : Detector + Camera at the focal plane + filters : dict + Dictionary of available filters as tuples (central wvl, width) [meter] + AO_Nact : int + Linear number of actuators + """ + + def __init__(self,D,detector=None,occ=0.): + self.D = D + self.occ = occ # occultation ratio + self.detector = detector + self.filters = {} + self.AO_Nact = 0 + self.focal_length = None + self.name = "" + + def __repr__(self): + s = self.name+" OpticalSystem\n" + s += "-------------------------\n" + s += "Diameter: %.2g m (occ=%u%%)\n" % (self.D,self.occ*100) + s += "AO_Nact : %u\n" % self.AO_Nact + s += "Focal : %s m\n" % str(self.focal_length) + s += "Filters : %u" % len(self.filters) + return s + + @property + def resolution_mas(self): + if self.focal_length is None: + raise ValueError("Cannot compute `resolution_mas` if `focal_length` is not set") + return self.detector.resolution/self.focal_length * RAD2ARCSEC * 1e3 + + def pupil(self,Npix,wvl=None,samp=None): + """Returns the 2D array of the pupil transmission function""" + Dpix = min(Npix)/2 + pup = circarr(Npix) + return (pup < Dpix) * (pup >= Dpix*self.occ) + + def samp(self,wvl): + """Returns sampling value for the given wavelength""" + if self.detector is None: + raise ValueError("Cannot compute sampling if `detector` is not defined") + if self.focal_length is None: + raise ValueError("Cannot compute sampling if `focal_length` is not defined") + return wvl*self.focal_length/(self.detector.resolution*self.D) + + def wvl(self,samp): + """Returns wavelength for the given sampling""" + if self.detector is None: + raise ValueError("Cannot compute wavelength if `detector` is not defined") + if self.focal_length is None: + raise ValueError("Cannot compute wavelength if `focal_length` is not defined") + return samp*(self.detector.resolution*self.D)/self.focal_length + + + def PSFdl(self,Npix,wvl): + """Returns the diffraction limited PSF + + Parameters + ---------- + Npix : tuple, list of 2 elements + Size of the output 2D array + wvl : float + Observation wavelength + """ + return airy(Npix,self.samp(wvl),self.occ) + -- GitLab