From 647b7ef9da5e21cfac302bae222da01f6f977451 Mon Sep 17 00:00:00 2001 From: Jameson Graef Rollins <jrollins@finestructure.net> Date: Wed, 8 Nov 2017 14:49:27 -0800 Subject: [PATCH] Add ability to load ifo data from YAML and MATLAB .mat files This adds a Struct() class that mimics a MATLAB struct by storing values as class attributes, but also includes methods for converting to/from dicts, yaml, and mat_struct objects. A convenience function load_ifo() is included to load an ifo definition either from a .yaml or .mat file or from an included <ifo>.yaml. An 'aLIGO.yaml' definition is included. --- gwinc/__init__.py | 1 + gwinc/ifo/__init__.py | 219 ++++++++++++++++++++++++++++++++ gwinc/ifo/aLIGO.yaml | 289 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 509 insertions(+) create mode 100644 gwinc/ifo/aLIGO.yaml diff --git a/gwinc/__init__.py b/gwinc/__init__.py index 85a98ed..a825ae4 100644 --- a/gwinc/__init__.py +++ b/gwinc/__init__.py @@ -1,3 +1,4 @@ +from ifo import load_ifo from util import precompIFO from gwinc import noise_calc from gwinc import gwinc diff --git a/gwinc/ifo/__init__.py b/gwinc/ifo/__init__.py index e69de29..0dec5e8 100644 --- a/gwinc/ifo/__init__.py +++ b/gwinc/ifo/__init__.py @@ -0,0 +1,219 @@ +import os +import re +import yaml +import scipy +import scipy.io +import numpy as np +from scipy.io.matlab.mio5_params import mat_struct + + +# HACK: fix loading number in scientific notation +# +# https://stackoverflow.com/questions/30458977/yaml-loads-5e-6-as-string-and-not-a-number +# +# An apparent bug in python-yaml prevents it from regognizing +# scientific notation as a float. The following is a modified version +# of the parser that recognize scientific notation appropriately. +# +loader = yaml.SafeLoader +loader.add_implicit_resolver( + u'tag:yaml.org,2002:float', + re.compile(u'''^(?: + [-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+]?[0-9]+)? + |[-+]?(?:[0-9][0-9_]*)(?:[eE][-+]?[0-9]+) + |\\.[0-9_]+(?:[eE][-+][0-9]+)? + |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]* + |[-+]?\\.(?:inf|Inf|INF) + |\\.(?:nan|NaN|NAN))$''', re.X), + list(u'-+0123456789.')) + + +class Struct(object): + """Matlab struct-like object + + This is a simple implementation of a MATLAB struct-like object + that stores values as attributes of a simple class: and allows assigning to + attributes recursively, e.g.: + + >>> s = Struct() + >>> s.a = 4 + >>> s.b = Struct() + >>> s.b.c = 8 + + Various classmethods allow creating one of these objects from YAML + file, a nested dict, or a MATLAB struct object. + + """ + + # FIXME: This would be a way to allow setting nested struct + # attributes, e.g.: + # + # >>> s = Struct() + # >>> s.a.b.c = 4 + # + # Usage of __getattr__ like this is dangerous and creates + # non-intuitive behavior (i.e. an empty struct is returned with + # accessing attributes that don't exist). Is there a way to + # accomplish this without that adverse side affect? + # + # def __getattr__(self, name): + # if name not in self.__dict__: + # self.__dict__[name] = Struct() + # return self.__dict__[name] + + ########## + + def __contains__(self, item): + return item in self.__dict__ + + def to_dict(self): + """Return nested dictionary representation of Struct. + + """ + d = {} + for k,v in self.__dict__.iteritems(): + if isinstance(v, Struct): + d[k] = v.to_dict() + else: + # handle lists of Structs + try: + d[k] = [i.to_dict() for i in v] + except (AttributeError, TypeError): + d[k] = v + return d + + def to_yaml(self, path=None): + """Return YAML representation of Struct as nested dict. + + Or write Struct to YAML file if file 'path' argument + specified. + + """ + y = yaml.dump(self.to_dict(), default_flow_style=False) + if path: + with open(path, 'w') as f: + f.write(y) + else: + return y + + def __repr__(self): + return self.to_yaml().strip('\n') + + def __str__(self): + return '<GWINC Struct: {}>'.format(self.__dict__.keys()) + + def __iter__(self): + return iter(self.__dict__) + + def walk(self): + """Iterate over all leaves in the struct tree. + + """ + for k,v in self.__dict__.iteritems(): + if type(v) is Struct: + for sk,sv in v.walk(): + yield k+'.'+sk, sv + else: + try: + for i,vv in enumerate(v): + for sk,sv in vv.walk(): + yield '{}[{}].{}'.format(k,i,sk), sv + except (AttributeError, TypeError): + yield k, v + + @classmethod + def from_dict(cls, d): + """Create Struct from nested dict. + + """ + c = cls() + for k,v in d.iteritems(): + if type(v) == dict: + c.__dict__[k] = Struct.from_dict(v) + else: + try: + c.__dict__[k] = map(Struct.from_dict, v) + except (AttributeError, TypeError): + c.__dict__[k] = v + return c + + @classmethod + def from_matstruct(cls, s): + """Create Struct from scipy.io.matlab mat_struct object. + + """ + c = cls() + # FIXME: handle 'ifo' attribute at top level. should we + # ignore this? + try: + s = s['ifo'] + except: + pass + for k,v in s.__dict__.iteritems(): + if k in ['_fieldnames']: + # skip these fields + pass + # FIXME: manaually converting Stage list to individual + # named elements. what's the right thing to do here? + elif k == 'Stage': + for i,stage in enumerate(v): + name = 'Stage{}'.format(i+1) + struct = Struct.from_matstruct(stage) + c.__dict__[name] = struct + elif type(v) is mat_struct: + c.__dict__[k] = Struct.from_matstruct(v) + else: + # handle lists of Structs + try: + c.__dict__[k] = map(Struct.from_matstruct, v) + except: + c.__dict__[k] = v + return c + + + @classmethod + def from_file(cls, path): + """Load Struct from .yaml or GWINC .mat file. + + File type will be determined by extension. + + """ + (root, ext) = os.path.splitext(path) + with open(path, 'r') as f: + if ext in ['.yaml', '.yml']: + d = yaml.load(f, Loader=loader) + return cls.from_dict(d) + elif ext == '.mat': + s = scipy.io.loadmat(f, squeeze_me=True, struct_as_record=False) + return cls.from_matstruct(s) + else: + raise IOError("Unknown file type: {}".format(ext)) + + + +def load_ifo(name_or_path): + """Load IFO by name or from file. + + IFO names will correspond to basename of included .yaml IFO + definition file. + + When specifying path may be either .yaml or .mat. + + """ + if os.path.exists(name_or_path): + path = name_or_path + else: + path = os.path.join(os.path.dirname(__file__), + name_or_path+'.yaml') + s = Struct.from_file(path) + return s + + +################################################## + + +if __name__ == '__main__': + import sys + ifo = load_ifo(sys.argv[1]) + # print(ifo.to_yaml()) + print(ifo.to_dict()) diff --git a/gwinc/ifo/aLIGO.yaml b/gwinc/ifo/aLIGO.yaml new file mode 100644 index 0000000..8a0b06d --- /dev/null +++ b/gwinc/ifo/aLIGO.yaml @@ -0,0 +1,289 @@ +# GWINC aLIGO interferometer parameters +# +# parameters for quad pendulum suspension updated 3rd May 2006, NAR +# References: +# LIGO-T000012-00-D +# * Differentiate between silica and sapphire substrate absorption +# * Change ribbon suspension aspect ratio +# * Change pendulum frequency +# References: +# 1. Electro-Optic Handbook, Waynant & Ediger (McGraw-Hill: 1993) +# 2. LIGO/GEO data/experience +# 3. Suspension reference design, LIGO-T000012-00 +# 4. Quartz Glass for Optics Data and Properties, Heraeus data sheet, +# numbers for suprasil +# 5. Y.S. Touloukian (ed), Thermophysical Properties of Matter +# (IFI/Plenum,1970) +# 6. Marvin J. Weber (ed) CRC Handbook of laser science and technology, +# Vol 4, Pt 2 +# 7. R.S. Krishnan et al.,Thermal Expansion of Crystals, Pergamon Press +# 8. P. Klocek, Handbook of infrared and optical materials, Marcel Decker, +# 1991 +# 9. Rai Weiss, electronic log from 5/10/2006 +# 10. Wikipedia online encyclopedia, 2006 +# 11. D.K. Davies, The Generation and Dissipation of Static Charge on +# dielectrics in a Vacuum, page 29 +# 12. Gretarsson & Harry, Gretarsson thesis +# 13. Fejer +# 14. Braginsky +# +# + +Constants: + # Temperature of the Vacuum + Temp: 290 # K + +Infrastructure: + Length: 3995 # m + ResidualGas: + pressure: 4.0e-7 # Pa + mass: 3.35e-27 # kg; Mass of H_2 (ref. 10) + polarizability: 7.8e-31 # m^3 + +TCS: + s_cc: 7.024 # Watt^-2 + s_cs: 7.321 # Watt^-2 + s_ss: 7.631 # Watt^-2 + # The hardest part to model is how efficient the TCS system is in + # compensating this loss. Thus as a simple Ansatz we define the + # TCS efficiency TCSeff as the reduction in effective power that produces + # a phase distortion. E.g. TCSeff=0.99 means that the compensated distortion + # of 1 Watt absorbed is eqivalent to the uncompensated distortion of 10mWatt. + # The above formula thus becomes: + # S= s_cc P_coat^2 + 2*s_cs*P_coat*P_subst + s_ss*P_subst^2 * (1-TCSeff)^2 + # + # To avoid iterative calculation we define TCS.SCRloss = S as an input + # and calculate TCSeff as an output. + # TCS.SRCloss is incorporated as an additional loss in the SRC + SRCloss: 0.00 + +Seismic: + Site: 'LHO' # LHO or LLO (only used for Newtonian noise) + KneeFrequency: 10 # Hz; freq where 'flat' noise rolls off + LowFrequencyLevel: 1e-9 # m/rtHz; seismic noise level below f_knee + Gamma: .8 # abruptness of change at f_knee + Rho: 1.8e3 # kg/m^3; density of the ground nearby + Beta: 0.5 # quiet times beta: 0.35-0.60 + # noisy times beta: 0.15-1.4 + Omicron: 1 # Feedforward cancellation factor + +Suspension: + # 0 for cylindrical suspension + #Type: 'Quad' + Type: 2 + # 0: round, 1: ribbons + FiberType: 0 + BreakStress: 750e6 # Pa; ref. K. Strain + Temp: 290 + VHCoupling: + theta: 1e-3 # vertical-horizontal x-coupling + + Silica: + Rho : 2200 # Kg/m^3; + C : 772 # J/Kg/K; + K : 1.38 # W/m/kg; + Alpha : 3.9e-7 # 1/K; + dlnEdT: 1.52e-4 # (1/K), dlnE/dT + Phi : 4.1e-10 # from G Harry e-mail to NAR 27April06 dimensionless units + Y : 72e9 # Pa; Youngs Modulus + Dissdepth: 1.5e-2 # from G Harry e-mail to NAR 27April06 + + C70Steel: + Rho: 7800 + C: 486 + K: 49 + Alpha: 12e-6 + dlnEdT: -2.5e-4 + Phi: 2e-4 + Y: 212e9 # measured by MB for one set of wires + + MaragingSteel: + Rho: 7800 + C: 460 + K: 20 + Alpha: 11e-6 + dlnEdT: 0 + Phi: 1e-4 + Y: 187e9 + + # ref ---- http://design.caltech.edu/Research/MEMS/siliconprop.html + # all properties should be for T ~ 20 K + Silicon: + Rho: 2330 # Kg/m^3; density + C: 772 # J/kg/K heat capacity + K: 4980 # W/m/K thermal conductivity + Alpha: 1e-9 # 1/K thermal expansion coeff + # from Gysin, et. al. PRB (2004) E(T): E0 - B*T*exp(-T0/T) + # E0: 167.5e9 Pa T0: 317 K B: 15.8e6 Pa/K + dlnEdT: 2.5e-10 # (1/K) dlnE/dT T=20K + Phi: 2e-9 # Nawrodt (2010) loss angle 1/Q + Y: 150e9 # Pa Youngs Modulus + Dissdepth: 1.5e-3 # 10x smaller surface loss depth (Nawrodt (2010)) + + # Note stage numbering: mirror is at beginning of stack, not end + # + # last stage length adjusted for d: 10mm and and d_bend = 4mm + # (since 602mm is the CoM separation, and d_bend is accounted for + # in suspQuad, so including it here would double count) + Stage1: + Mass: 39.6 # kg; current numbers May 2006 NAR + Length: 0.59 # m + Dilution: .nan # + K: .nan # N/m; vertical spring constant + WireRadius: .nan # m + Blade: .nan # blade thickness + NWires: 4 + + Stage2: + Mass: 39.6 + Length: 0.341 + Dilution: 106 + K: 5200 + WireRadius: 310e-6 + Blade: 4200e-6 + NWires: 4 + + Stage3: + Mass: 21.8 + Length: 0.277 + Dilution: 80 + K: 3900 + WireRadius: 350e-6 + Blade: 4600e-6 + NWires: 4 + + Stage4: + Mass: 22.1 + Length: 0.416 + Dilution: 87 + K: 3400 + WireRadius: 520e-6 + Blade: 4300e-6 + NWires: 2 + + Ribbon: + Thickness: 115e-6 # m + Width: 1150e-6 # m + + Fiber: + Radius: 205e-6 # m + Blade: 4300e-6 + +## Optic Material ------------------------------------------------------- +Materials: + MassRadius: 0.17 # m; + MassThickness: 0.200 # m; Peter F 8/11/2005 + + ## Dielectric coating material parameters---------------------------------- + Coating: + ## high index material: tantala + Yhighn: 140e9 + Sigmahighn: 0.23 + CVhighn: 2.1e6 # Crooks et al, Fejer et al + Alphahighn: 3.6e-6 # 3.6e-6 Fejer et al, 5e-6 from Braginsky + Betahighn: 1.4e-5 # dn/dT, value Gretarrson (G070161) + ThermalDiffusivityhighn: 33 # Fejer et al + Phihighn: 2.3e-4 + Indexhighn: 2.06539 + + ## low index material: silica + Ylown: 72e9 + Sigmalown: 0.17 + CVlown: 1.6412e6 # Crooks et al, Fejer et al + Alphalown: 5.1e-7 # Fejer et al + Betalown: 8e-6 # dn/dT, (ref. 14) + ThermalDiffusivitylown: 1.38 # Fejer et al + Philown: 4.0e-5 + Indexlown: 1.45 + + ## Substrate Material parameters-------------------------------------------- + Substrate: + c2 : 7.6e-12 # Coeff of freq depend. term for bulk mechanical loss, 7.15e-12 for Sup2 + MechanicalLossExponent: 0.77 # Exponent for freq dependence of silica loss, 0.822 for Sup2 + Alphas: 5.2e-12 # Surface loss limit (ref. 12) + MirrorY: 7.27e10 # N/m^2; Youngs modulus (ref. 4) + MirrorSigma: 0.167 # Kg/m^3; Poisson ratio (ref. 4) + MassDensity: 2.2e3 # Kg/m^3; (ref. 4) + MassAlpha: 3.9e-7 # 1/K; thermal expansion coeff. (ref. 4) + MassCM: 739 # J/Kg/K; specific heat (ref. 4) + MassKappa: 1.38 # J/m/s/K; thermal conductivity (ref. 4) + RefractiveIndex: 1.45 # mevans 25 Apr 2008 + +## Laser------------------------------------------------------------------- +Laser: + Wavelength: 1.064e-6 # m + Power: 125 # W + +## Optics------------------------------------------------------------------ +Optics: + Type: 'SignalRecycled' + PhotoDetectorEfficiency: 0.95 # photo-detector quantum efficiency + Loss: 37.5e-6 # average per mirror power loss + BSLoss: 0.5e-3 # power loss near beamsplitter + coupling: 1.0 # mismatch btwn arms & SRC modes; used to + + #SubstrateAbsorption: 0.5e-4 # 1/m; bulk absorption coef (ref. 2) + SubstrateAbsorption: 0.3e-4 # 1/m; 0.3 ppm/cm for Hereaus + pcrit: 10 # W; tolerable heating power (factor 1 ATC) + Quadrature: + dc: 1.5707963 # pi/2 # demod/detection/homodyne phase + + ITM: + BeamRadius: 0.055 # m, 1/e^2 power radius + Transmittance: 0.014 + CoatingThicknessLown: 0.308 + CoatingThicknessCap: 0.5 + CoatingAbsorption: 0.5e-6 + SubstrateAbsorption: 0.3e-4 # 1/m, 0.3 ppm/cm for Hereaus + ETM: + BeamRadius: 0.062 # m, 1/e^2 power radius + Transmittance: 5e-6 + CoatingThicknessLown: 0.27 + CoatingThicknessCap: 0.5 + PRM: + Transmittance: 0.03 + SRM: + Transmittance: 0.20 + CavityLength: 55 # m, ITM to SRM distance + Tunephase: 0.0 # SEC tuning + + Curvature: # ROC + ITM: 1970 + ETM: 2192 + +## Squeezer Parameters------------------------------------------------------ +# Define the squeezing you want: +# None: ignore the squeezer settings +# Freq Independent: nothing special (no filter cavties) +# Freq Dependent = applies the specified filter cavites +# Optimal = find the best squeeze angle, assuming no output filtering +# OptimalOptimal = optimal squeeze angle, assuming optimal readout phase +Squeezer: + Type: 'None' + AmplitudedB: 10 # SQZ amplitude [dB] + InjectionLoss: 0.05 # power loss to sqz + SQZAngle: 0 # SQZ phase [radians] + + # Parameters for frequency dependent squeezing + FilterCavity: + fdetune: -14.5 # detuning [Hz] + L: 100 # cavity length + Ti: 0.12e-3 # input mirror trasmission [Power] + Te: 0 # end mirror trasmission + Lrt: 100e-6 # round-trip loss in the cavity + Rot: 0 # phase rotation after cavity + +## Variational Output Parameters-------------------------------------------- +# Define the output filter cavity chain +# None = ignore the output filter settings +# Chain = apply filter cavity chain +# Optimal = find the best readout phase +OutputFilter: + Type: 'None' + FilterCavity: + fdetune: -30 # detuning [Hz] + L: 4000 # cavity length + Ti: 10e-3 # input mirror trasmission [Power] + Te: 0 # end mirror trasmission + Lrt: 100e-6 # round-trip loss in the cavity + Rot: 0 # phase rotation after cavity -- GitLab