def create_FIR_whitener_kernel(length, duration, sample_rate, psd): assert psd # # Add another COMPLEX16TimeSeries and COMPLEX16FrequencySeries for kernel's FFT (Leo) # # Add another FFT plan for kernel FFT (Leo) fwdplan_kernel = lal.CreateForwardCOMPLEX16FFTPlan(length, 1) kernel_tseries = lal.CreateCOMPLEX16TimeSeries( name="timeseries of whitening kernel", epoch=LIGOTimeGPS(0.), f0=0., deltaT=1.0 / sample_rate, length=length, sampleUnits=lal.Unit("strain")) kernel_fseries = lal.CreateCOMPLEX16FrequencySeries( name="freqseries of whitening kernel", epoch=LIGOTimeGPS(0), f0=0.0, deltaF=1.0 / duration, length=length, sampleUnits=lal.Unit("strain s")) # # Obtain a kernel of zero-latency whitening filter and # adjust its length (Leo) # psd_fir_kernel = reference_psd.PSDFirKernel() (kernel, latency, fir_rate) = psd_fir_kernel.psd_to_linear_phase_whitening_fir_kernel( psd, nyquist=sample_rate / 2.0) ( kernel, theta ) = psd_fir_kernel.linear_phase_fir_kernel_to_minimum_phase_whitening_fir_kernel( kernel, fir_rate) kernel = kernel[-1::-1] # FIXME this is off by one sample, but shouldn't be. Look at the miminum phase function # assert len(kernel) == length if len(kernel) < length: kernel = numpy.append(kernel, numpy.zeros(length - len(kernel))) else: kernel = kernel[:length] kernel_tseries.data.data = kernel # # FFT of the kernel # lal.COMPLEX16TimeFreqFFT(kernel_fseries, kernel_tseries, fwdplan_kernel) #FIXME return kernel_fseries
def _parse_series(elem, creatorfunc, delta_target_unit_string): t, = elem.getElementsByTagName(ligolw.Time.tagName) a, = elem.getElementsByTagName(ligolw.Array.tagName) dims = a.getElementsByTagName(ligolw.Dim.tagName) f0 = ligolw_param.get_param(elem, u"f0") if t.Type != u"GPS": raise ValueError("epoch Type must be GPS") epoch = t.pcdata # Target units: inverse seconds inverse_seconds_unit = lal.Unit("s^-1") delta_target_unit = lal.Unit(delta_target_unit_string) # Parse units of f0 field f0_unit = lal.Unit(str(f0.Unit)) # Parse units of deltaF field delta_unit = lal.Unit(str(dims[0].Unit)) # Parse units of data sample_unit = lal.Unit(str(a.Unit)) # Initialize data structure series = creatorfunc( str(a.Name), epoch, f0.pcdata * float(f0_unit / inverse_seconds_unit), dims[0].Scale * float(delta_unit / delta_target_unit), sample_unit, len(a.array.T) ) # Assign data if np.iscomplexobj(series.data.data): series.data.data = a.array[1] + 1j * a.array[2] else: series.data.data = a.array[1] # Done! return series
def parse_REAL8FrequencySeries(elem): t, = elem.getElementsByTagName(ligolw.Time.tagName) a, = elem.getElementsByTagName(ligolw.Array.tagName) dims = a.getElementsByTagName(ligolw.Dim.tagName) f0 = ligolw_param.get_param(elem, u"f0") epoch = lal.LIGOTimeGPS(str(t.pcdata)) # Target units: inverse seconds inverse_seconds_unit = lal.Unit() lal.ParseUnitString(inverse_seconds_unit, "s^-1") # Parse units of f0 field f0_unit = lal.Unit() lal.ParseUnitString(f0_unit, str(f0.get_unit())) # Parse units of deltaF field deltaF_unit = lal.Unit() lal.ParseUnitString(deltaF_unit, str(dims[0].getAttribute(u"Unit"))) # Parse units of data sample_unit = lal.Unit() lal.ParseUnitString(sample_unit, str(a.getAttribute(u"Unit"))) # Parse data data = a.array[1] # Initialize data structure series = lal.CreateREAL8FrequencySeries( str(a.getAttribute(u"Name")), epoch, float(f0.pcdata) * lal.UnitRatio(f0_unit, inverse_seconds_unit), float(dims[0].getAttribute(u"Scale")) * lal.UnitRatio(deltaF_unit, inverse_seconds_unit), sample_unit, len(data)) # Copy data series.data.data = data # Done! return series
def to_lal_unit(aunit): """Convert the input unit into a `LALUnit` For example:: >>> u = to_lal_unit('m**2 / kg ** 4') >>> print(u) m^2 kg^-4 Parameters ---------- aunit : `~astropy.units.Unit`, `str` the input unit Returns ------- unit : `LALUnit` the LALUnit representation of the input Raises ------ ValueError if LAL doesn't understand the base units for the input """ if isinstance(aunit, string_types): aunit = units.Unit(aunit) aunit = aunit.decompose() lunit = lal.Unit() for base, power in zip(aunit.bases, aunit.powers): # try this base try: lalbase = LAL_UNIT_FROM_ASTROPY[base] except KeyError: lalbase = None # otherwise loop through the equivalent bases for eqbase in base.find_equivalent_units(): try: lalbase = LAL_UNIT_FROM_ASTROPY[eqbase] except KeyError: continue # if we didn't find anything, raise an exception if lalbase is None: raise ValueError("LAL has no unit corresponding to %r" % base) lunit *= lalbase**power return lunit
def snr_time_series(self): try: name = self._snr_name except ValueError: # C interface raises ValueError if the internal snr # pointer is NULL return None series = lal.CreateCOMPLEX8TimeSeries( name, lal.LIGOTimeGPS(self._snr_epoch_gpsSeconds, self._snr_epoch_gpsNanoSeconds), self._snr_f0, self._snr_deltaT, lal.Unit(self._snr_sampleUnits), self._snr_data_length) # we want to be able to keep the table row object in memory # for an extended period of time so we need to be able to # release the memory used by the SNR time series when we no # longer need it, and so we copy the data here instead of # holding a reference to the original memory. if we # allowed references to the original memory to leak out # into Python land we could never know if it's safe to free # it series.data.data[:] = self._snr_data return series
assert (is_value_and_type(tsw + tmy, tsw + tsw, LIGOTimeGPS)) assert (is_value_and_type(tmy + tsw, tsw + tsw, LIGOTimeGPS)) assert (is_value_and_type(tsw - tmy, tsw - tsw, LIGOTimeGPS)) assert (is_value_and_type(tmy - tsw, tsw - tsw, LIGOTimeGPS)) assert (is_value_and_type(tsw * tmy, tsw * tsw, LIGOTimeGPS)) assert (is_value_and_type(tmy * tsw, tsw * tsw, LIGOTimeGPS)) assert (is_value_and_type(tsw / tmy, tsw / tsw, LIGOTimeGPS)) assert (is_value_and_type(tmy / tsw, tsw / tsw, LIGOTimeGPS)) assert (lal.swig_lal_test_noptrgps(tmy) == lal.swig_lal_test_noptrgps(tsw)) del tsw lal.CheckMemoryLeaks() print("PASSED LIGOTimeGPS operations (Python specific)") # check LALUnit operations print("checking LALUnit operations ...") u1 = lal.Unit("kg m s^-2") assert (type(lal.Unit(u1)) is lal.Unit) assert (is_value_and_type(u1, lal.NewtonUnit, lal.Unit)) assert (str(u1) == "m kg s^-2") u2 = lal.MeterUnit * lal.KiloGramUnit / lal.SecondUnit**2 assert (is_value_and_type(u2, u1, lal.Unit)) u2 = lal.MeterUnit**(1, 2) * lal.KiloGramUnit**(1, 2) * lal.SecondUnit**-1 assert (is_value_and_type(u2, u1**(1, 2), lal.Unit)) try: lal.SecondUnit**(1, 0) expected_exception = True except: pass assert (not expected_exception) u1 *= lal.MeterUnit assert (is_value_and_type(u1, lal.JouleUnit, lal.Unit))
assert (tmy + tsw == tsw + tsw and isinstance(tmy + tsw, LIGOTimeGPS)) assert (tsw - tmy == tsw - tsw and isinstance(tsw - tmy, LIGOTimeGPS)) assert (tmy - tsw == tsw - tsw and isinstance(tmy - tsw, LIGOTimeGPS)) assert (tsw * tmy == tsw * tsw and isinstance(tsw * tmy, LIGOTimeGPS)) assert (tmy * tsw == tsw * tsw and isinstance(tmy * tsw, LIGOTimeGPS)) if swig_division_coercion_works: # FIXME: https://github.com/swig/swig/pull/617 assert (tsw / tmy == tsw / tsw and isinstance(tsw / tmy, LIGOTimeGPS)) assert (tmy / tsw == tsw / tsw and isinstance(tmy / tsw, LIGOTimeGPS)) assert (lal.swig_lal_test_noptrgps(tmy) == lal.swig_lal_test_noptrgps(tsw)) del tsw lal.CheckMemoryLeaks() print("PASSED LIGOTimeGPS operations (Python specific)") # check LALUnit operations print("checking LALUnit operations ...") u1 = lal.Unit("kg m s^-2") assert (isinstance(lal.Unit(u1), lal.Unit)) assert (u1 == lal.NewtonUnit and isinstance(u1, lal.Unit)) assert (str(u1) == "m kg s^-2") if swig_division_coercion_works: # FIXME: https://github.com/swig/swig/pull/617 u2 = lal.MeterUnit * lal.KiloGramUnit / lal.SecondUnit**2 assert (u1 == u2 and isinstance(u2, lal.Unit)) u2 = lal.MeterUnit**(1, 2) * lal.KiloGramUnit**(1, 2) * lal.SecondUnit**-1 assert (u1**(1, 2) == u2 and isinstance(u2, lal.Unit)) try: lal.SecondUnit**(1, 0) expected_exception = True except: pass assert (not expected_exception) u1 *= lal.MeterUnit
import math from scipy import optimize # LAL imports import lal import lalsimulation # My own imports from .decorator import memoized log = logging.getLogger('BAYESTAR') # Useful sample units unitInverseHertz = lal.Unit('s') unitInverseSqrtHertz = lal.Unit('s^1/2') # Memoize FFT plans CreateForwardCOMPLEX16FFTPlan = memoized(lal.CreateForwardCOMPLEX16FFTPlan) CreateForwardREAL8FFTPlan = memoized(lal.CreateForwardREAL8FFTPlan) CreateReverseCOMPLEX16FFTPlan = memoized(lal.CreateReverseCOMPLEX16FFTPlan) CreateReverseREAL8FFTPlan = memoized(lal.CreateReverseREAL8FFTPlan) def ceil_pow_2(n): """Return the least integer power of 2 that is greater than or equal to n. >>> ceil_pow_2(128.0) 128.0
prefix = detector.frDetector.prefix detectors.append(prefix) parser.add_option( '--' + prefix, choices=psd_names, metavar='func', help='PSD function for {0} detector [optional]'.format(name)) # Parse command line. opts, args = parser.parse_args() if args: parser.error('Did not expect any positional command line arguments') psds = {} unit = lal.Unit() unit = lal.UnitInvert(unit, lal.HertzUnit) n = int(opts.f_max // opts.df) epoch = lal.LIGOTimeGPS() progress = glue.text_progress_bar.ProgressBar() for detector in detectors: psd_name = getattr(opts, detector) if psd_name is None: continue psd_func = getattr(lalsimulation, psd_name_prefix + psd_name) series = lal.CreateREAL8FrequencySeries(None, epoch, 0, opts.df, unit, n) fmt = '%s (%%d / %d)' % (detector, n) for i in progress.iterate(range(1, n), format=fmt): f = i * opts.df
def __init__(self, template_table, approximant, psd, f_low, time_slices, autocorrelation_length=None, fhigh=None): self.template_table = template_table self.approximant = approximant self.f_low = f_low self.time_slices = time_slices self.autocorrelation_length = autocorrelation_length self.fhigh = fhigh self.sample_rate_max = max(time_slices["rate"]) self.duration = max(time_slices["end"]) self.length_max = int(round(self.duration * self.sample_rate_max)) if self.fhigh is None: self.fhigh = self.sample_rate_max / 2. # Some input checking to avoid incomprehensible error messages if not self.template_table: raise ValueError("template list is empty") if self.f_low < 0.: raise ValueError("f_low must be >= 0. %s" % repr(self.f_low)) # working f_low to actually use for generating the waveform. pick # template with lowest chirp mass, compute its duration starting # from f_low; the extra time is 10% of this plus 3 cycles (3 / # f_low); invert to obtain f_low corresponding to desired padding. # NOTE: because SimInspiralChirpStartFrequencyBound() does not # account for spin, we set the spins to 0 in the call to # SimInspiralChirpTimeBound() regardless of the component's spins. template = min(self.template_table, key=lambda row: row.mchirp) tchirp = lalsim.SimInspiralChirpTimeBound(self.f_low, template.mass1 * lal.MSUN_SI, template.mass2 * lal.MSUN_SI, 0., 0.) self.working_f_low = lalsim.SimInspiralChirpStartFrequencyBound( 1.1 * tchirp + 3. / self.f_low, template.mass1 * lal.MSUN_SI, template.mass2 * lal.MSUN_SI) # Add duration of PSD to template length for PSD ringing, round up to power of 2 count of samples self.working_length = templates.ceil_pow_2(self.length_max + round(1. / psd.deltaF * self.sample_rate_max)) self.working_duration = float( self.working_length) / self.sample_rate_max if psd is not None: # Smooth the PSD and interpolate to required resolution self.psd = condition_psd(psd, 1.0 / self.working_duration, minfs=(self.working_f_low, self.f_low), maxfs=(self.sample_rate_max / 2.0 * 0.90, self.sample_rate_max / 2.0)) if FIR_WHITENER: # Compute a frequency response of the time-domain whitening kernel and effectively taper the psd by zero-ing some elements for a FIR kernel self.kernel_fseries = taperzero_fseries(create_FIR_whitener_kernel(self.working_length, self.working_duration, self.sample_rate_max, self.psd),\ minfs = (self.working_f_low, self.f_low),\ maxfs = (self.sample_rate_max / 2.0 * 0.90, self.sample_rate_max / 2.0)\ ) self.revplan = lal.CreateReverseCOMPLEX16FFTPlan( self.working_length, 1) self.fwdplan = lal.CreateForwardREAL8FFTPlan(self.working_length, 1) self.tseries = lal.CreateCOMPLEX16TimeSeries( name="timeseries", epoch=LIGOTimeGPS(0.), f0=0., deltaT=1.0 / self.sample_rate_max, length=self.working_length, sampleUnits=lal.Unit("strain")) self.fworkspace = lal.CreateCOMPLEX16FrequencySeries( name="template", epoch=LIGOTimeGPS(0), f0=0.0, deltaF=1.0 / self.working_duration, length=self.working_length // 2 + 1, sampleUnits=lal.Unit("strain s")) # Calculate the maximum ring down time or maximum shift time if approximant in templates.gstlal_IMR_approximants: self.max_ringtime = max([ chirptime.ringtime( row.mass1 * lal.MSUN_SI + row.mass2 * lal.MSUN_SI, chirptime.overestimate_j_from_chi( max(row.spin1z, row.spin2z))) for row in self.template_table ]) else: if self.sample_rate_max > 2. * self.fhigh: # Calculate the maximum time we need to shift the early warning # waveforms forward by, calculated by the 3.5 approximation from # fhigh to ISCO. self.max_shift_time = max([ spawaveform.chirptime( row.mass1, row.mass2, 7, fhigh, 0., spawaveform.computechi(row.mass1, row.mass2, row.spin1z, row.spin2z)) for row in self.template_table ])
__author__ = "Leo Singer <*****@*****.**>" # General imports import numpy as np import math from scipy import optimize # LAL imports import lal import lalsimulation # My own imports from .decorator import memoized # Useful sample units unitInverseHertz = lal.Unit() unitInverseSqrtHertz = lal.Unit() lal.UnitInvert(unitInverseHertz, lal.lalHertzUnit) lal.UnitSqrt(unitInverseSqrtHertz, unitInverseHertz) # Memoize FFT plans CreateForwardCOMPLEX16FFTPlan = memoized(lal.CreateForwardCOMPLEX16FFTPlan) CreateForwardREAL8FFTPlan = memoized(lal.CreateForwardREAL8FFTPlan) CreateReverseCOMPLEX16FFTPlan = memoized(lal.CreateReverseCOMPLEX16FFTPlan) CreateReverseREAL8FFTPlan = memoized(lal.CreateReverseREAL8FFTPlan) def ceil_pow_2(number): """Return the least integer power of 2 that is greater than or equal to number.""" # frexp splits floats into mantissa and exponent, ldexp does the opposite. # For positive numbers, mantissa is in [0.5, 1.).