-
Notifications
You must be signed in to change notification settings - Fork 16
/
lisasim-swig.i
1502 lines (1103 loc) · 45.3 KB
/
lisasim-swig.i
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* $Id$
* $Date$
* $Author$
* $Revision$
*/
/* File : lisasim-swig.i */
// Directors are not needed (only for AnyLISA, deprecated)
// %module(directors="1") lisaswig
%module lisaswig
%{
#include "lisasim.h"
%}
%include lisasim-typemaps.i
%define initsave(theclass)
%feature("addtofunc") theclass::theclass {
self.initargs = args
}
%enddef
%define initdoc(theclass)
%feature("docstring") theclass::theclass "
Constructor. See above.
"
%feature("docstring") theclass::~theclass "
Destructor. See above.
"
%enddef
%define exceptionhandle(thefunction,theexception,theerror)
%exception thefunction {
try {
$action
} catch (theexception &e) {
PyErr_SetString(theerror,"");
return NULL;
}
};
%enddef
%pythoncode %{
import numpy
import math
import sys
import random
import time
%}
/* ------- random numbers ------- */
%pythoncode %{
globalseed = 0
cseeds = []
def setglobalseed(seed = 0):
globalseed = seed
random.seed(globalseed)
def getglobalseed():
if globalseed == 0:
setglobalseed(int(time.time()))
return globalseed
def getcseed():
if globalseed == 0:
setglobalseed(int(time.time()))
while True:
ret = random.randint(0,2**32)
if not ret in cseeds:
cseeds.append(ret)
return ret
%}
/* -------- LISA objects -------- */
%feature("docstring") LISA "
LISA is the base class for all LISA geometries. All derived LISA
classes must define putn(l,t), putp(i,t), and armlength(l,t). LISA,
and most of its derived classes, are defined in lisasim-lisa.cpp"
%feature("docstring") LISA::putn "
LISA.putn(l,t) -> (nlx,nly,nlz) returns a 3-tuple with the SSB
components (normalized) of arm l (1,2,3,-1,-2,-3) at time t [s]."
%feature("docstring") LISA::putp "
LISA.putp(i,t) -> (pix,piy,piz) returns a 3-tuple with the SSB
coordinates of spacecraft i (1,2,3) at time t [s]."
%feature("docstring") LISA::putv "
LISA.putv(i,t) -> (vix,viy,viz) returns a 3-tuple with the SSB
coordinate speed of spacecraft i (1,2,3) at time t [s], given
in units of the speed of light."
%feature("docstring") LISA::armlength "
LISA.armlength(l,t) the armlength [s] of LISA link l (1,2,3,-1,-2,-3)
for laser pulse reception at time t [s]."
%feature("docstring") LISA::dotarmlength "
LISA.armlength(l,t) the instantaneous rate of change of the armlength
of LISA link l (1,2,3,-1,-2,-3) for laser pulse reception a time t [s],
given in units of the speed of light."
%feature("docstring") LISA::reset "
LISA.reset() resets any underlying pseudo-random or ring-buffer
elements used by the LISA object."
%nodefault LISA;
class LISA {
public:
virtual void putp(Vector &outvector, int craft, double t);
virtual void putn(Vector &outvector, int arm, double t);
virtual void putv(Vector &outvector, int craft, double t);
virtual double armlength(int arm, double t);
virtual double dotarmlength(int arm, double t);
virtual void reset();
};
%feature("docstring") OriginalLISA "
OriginalLISA(L1,L2,L3) returns a static LISA object with armlengths
given by L1, L2, L3 (in seconds). If omitted, the Li take the standard
value Lstd.
The positions of the spacecraft are chosen so that 1) the baricenter
is in the SSB origin; 2) piz = 0 for all spacecraft; 3) the spacecraft
sequence 1 -> 2 -> 3 -> 1 traces a clockwise path, as seen from above;
p1y = 0."
initdoc(OriginalLISA)
initsave(OriginalLISA)
class OriginalLISA : public LISA {
public:
OriginalLISA(double arm1 = Lstd,double arm2 = Lstd,double arm3 = Lstd);
};
%feature("docstring") ModifiedLISA "
ModifiedLISA(L1,L2,L3) returns a stationary LISA object set equal to
OriginalLISA(L1,L2,L3) at time 0, but rotating around its baricenter
(at the SSB origin) with angular speed 2*pi/yr. L1, L2, L3 are given
in seconds; if omitted, they take the standard value Lstd.
Because of the rotation, the armlengths depend on the
direction of light propagation."
initdoc(ModifiedLISA)
initsave(ModifiedLISA)
class ModifiedLISA : public OriginalLISA {
public:
ModifiedLISA(double arm1 = Lstd,double arm2 = Lstd,double arm3 = Lstd);
};
%nodefault ApproxLISA;
class ApproxLISA {
public:
virtual double geteta0();
virtual double getxi0();
virtual double getsw();
};
%feature("docstring") CircularRotating "
CircularRotating(eta0=0,xi0=0,sw=1,t0=0) and
CircularRotating(myL,eta0,xi0,sw,t0) return rigid LISA objects where
the armlengths are equal and constant before aberration is taken into
account. The parameters eta0 and xi0 are the true anomaly of the LISA
guiding center and the initial phase of the LISA array at t=t0; sw<0
will swap spacecraft 2 and 3, so that the spacecraft sequence 1 -> 2
-> 3 -> 1 goes ccw as seen from above. If given (in which case all
parameters must be specified), myL is the common armlength; if not
given, it is set to Lstd.
CircularRotating() is legal and replaces stdlisa(). The LISA
baricenter moves on a circular orbit in the ecliptic, while the
constellation rotates around the guiding center with the same angular
velocity. The orbits follow Krolak et al, PRD 70, 022003 (2004)."
initdoc(CircularRotating)
initsave(CircularRotating)
class CircularRotating : public LISA, public ApproxLISA {
public:
CircularRotating(double eta0=0.0, double xi0=0.0, double sw=0.0, double t0=0.0);
CircularRotating(double myL,double e0,double x0,double sw,double t0);
};
class HaloAnalytic : public LISA {
public:
HaloAnalytic(double myL,double t0=0.0);
double genarmlength(int arm,double t);
};
%feature("docstring") EccentricInclined "
EccentricInclined(eta0=0,xi0=0,sw=1,t0=0) returns a realistic LISA
geometry modeled up to second order in the eccentricity, following
Cornish and Rubbo, PRD 67, 022001 (2003), but with the approximate
parametrization of CircularRotating (eta0 and xi0 true anomaly of
baricenter and array phase at t0=0; sw<0 swaps spacecraft); myL is
the common armlength; if not given, it is set to Lstd."
initdoc(EccentricInclined)
initsave(EccentricInclined)
class EccentricInclined : public LISA, public ApproxLISA {
public:
EccentricInclined(double eta0=0.0, double xi0=0.0, double sw=1.0, double t0=0.0);
EccentricInclined(double myL,double e0,double x0,double sw,double t0);
double genarmlength(int arm,double t);
};
class ZeroLISA : public LISA {
public:
ZeroLISA();
};
%feature("docstring") PyLISA "
PyLISA(baseLISA,Func) returns a LISA object with physical geometry
(used for light propagation and GW and noise responses) given by the
LISA object baseLISA, but with nominal armlengths (as used for the TDI
delays) given by the Python function Func(i,t) (i=1,2,3,-1,-2,-3, time
in seconds).
PyLISA attempts to provide a more general (if less efficient)
mechanism for the nominal-armlength computations previously performed
with NoisyLISA, NominalLISA, LinearLISA, MeasureLISA (all
experimental and now removed from the main distribution)."
initdoc(PyLISA)
initsave(PyLISA)
%apply PyObject* PYTHONFUNC { PyObject *func };
class PyLISA : public LISA {
public:
LISA *baseLISA;
PyLISA(LISA *base,PyObject *func);
};
%feature("docstring") AllPyLISA "
AllPyLISA(putpfunc,armlengthfunc = 0)
returns a LISA object that takes the positions of spacecraft from
the Python function putpfunc(craft,time), where craft = 1,2,3, and
time is given in seconds; and that takes the armlengths from the
Python function armlengthfunc(link,time), where link = 1,2,3,-1,-2,-3.
If armlengthfunc is not given, the armlengths will be determined from
the s/c positions using the exact light-propagation equation (solved
in the base LISA class).
Note: simulations that use AllPyLISA can be speeded up somewhat by
enclosing the AllPyLISA object in a CacheLengthLISA object."
initdoc(AllPyLISA)
initsave(AllPyLISA)
%apply PyObject* PYTHONFUNC { PyObject *sfunc, PyObject *afunc };
class AllPyLISA : public LISA {
public:
AllPyLISA(PyObject *sfunc,PyObject *afunc = 0);
};
%feature("docstring") CacheLISA "
CacheLISA(baseLISA)
returns a LISA object that works by routing all putp-putn calls to the
baseLISA object, passed on construction. It will however interpose a
layer of its own making for retard() calls, effectively caching
chained retardations for the most recently accessed time.
CacheLISA, defined in lisasim-retard.h, might improve performance for
complicated (or multiple) TDI-variable evaluations, especially when
performed in conjunction with PyLISA."
initdoc(CacheLISA)
initsave(CacheLISA)
class CacheLISA : public LISA {
public:
CacheLISA(LISA *base);
};
%feature("docstring") SampledLISA "
SampledLISA(p1,p2,p3,deltat,prebuffer,interp)
returns a LISA object that takes the positions of its spacecraft from
the 2-dimensional numpy arrays p1, p2, p3; each of these consists of
three columns that give the SSB coordinates of corresponding LISA
spacecraft.
The array data is understood to be spaced by intervals deltat [s], and
it is offset so that (for instance)
p1x(t) = p1[(t - prebuffer)/deltat,0],
p1y(t) = p1[(t - prebuffer)/deltat,1],
p1z(t) = p1[(t - prebuffer)/deltat,2].
Last, interp (> 1) sets the semiwidth of the data window used in
Lagrange interpolation of the positions.
Note 1: SampledLISA makes copies of the positions arrays, so these can
be safely destroyed after calling the SampledLISA constructor; on the
other hand, modifying the arrays passed to the constructor will have no
effect on the positions returned by SampledLISA.putp().
Note 2: currently armlength are computed explicitly by SampledLISA by
solving the backward light propagation equation."
initdoc(SampledLISA)
/* SampledLISA makes copies of the positions arrays, so initsave is not
needed */
class SampledLISA : public LISA {
public:
SampledLISA(double *numarray,long length,double *numarray,long length,double *numarray,long length,double deltat,double prebuffer,int interplen = 1);
};
%feature("docstring") CacheLengthLISA "
CacheLengthLISA(baseLISA,bufferlength,deltat,interplen = 1)
returns a LISA object that caches and interpolates armlengths found by
solving the light-propagation equation for the spacecraft positions
returned by baseLISA.putp(). The light-propagation equation is solved
every deltat seconds, and results remain available in a time window of
duration bufferlength*deltat. Last, interplen is the semiwidth of the
interpolation kernel (with 0 nearest-neighbor interpolation and 1 linear
interpolation).
Note: the current implementation does not support changing the physical
LISA of baseLISA on the fly, and is untested for different nominal and
physical LISAs."
initdoc(CacheLengthLISA)
initsave(CacheLengthLISA)
class CacheLengthLISA : public LISA {
public:
CacheLengthLISA(LISA *lisa,long length,double deltat,int interplen = 4);
~CacheLengthLISA();
};
extern double retardation(LISA *lisa,int ret1,int ret2,int ret3,int ret4,int ret5,int ret6,int ret7,int ret8,double t);
/* -------- Signal/Noise objects -------- */
exceptionhandle(SignalSource::__getitem__,ExceptionOutOfBounds,PyExc_IndexError)
%nodefault SignalSource;
class SignalSource {
public:
virtual void reset(unsigned long seed = 0);
%extend {
double __getitem__(long pos) {
return (*self)[pos];
};
};
};
%feature("docstring") WhiteNoiseSource::setglobalseed "
WhiteNoiseSource.setglobalseed(seed) sets the global seed that will be
used to initialize the next pseudorandom-number generator to be created
or reset. The argument should be an unsigned long integer. The global
seed is increased by one after each creation or initialization. This is
a class (static) method. "
%feature("docstring") WhiteNoiseSource::getglobalseed "
WhiteNoiseSource.getglobalseed() returns the global seed that will be
used to initialize the next pseudorandom-number generator to be created
or reset. The seed is an unsigned long integer. The global seed is
increased by one after each creation or initialization. This is a class
(static) method. "
class WhiteNoiseSource : public SignalSource {
public:
WhiteNoiseSource(long len,unsigned long seed = 0,double norm = 1.0);
static void setglobalseed(unsigned long seed = 0);
static unsigned long getglobalseed();
};
initsave(SampledSignalSource)
class SampledSignalSource : public SignalSource {
public:
SampledSignalSource(double *numarray,long length,double norm = 1.0);
};
initsave(SampledSignalSource)
class FileSignalSource : public SignalSource {
public:
FileSignalSource(char *filename,long bufferlen,long prebuffer,int endianness = -1,double norm = 1.0);
~FileSignalSource();
};
%nodefault Filter;
class Filter;
class NoFilter : public Filter {
public:
NoFilter();
};
class IntFilter : public Filter {
public:
IntFilter(double a = 0.9999);
};
class DiffFilter : public Filter {
public:
DiffFilter();
};
class BandIntFilter : public Filter {
public:
BandIntFilter(double deltat,double flow,double fhi);
};
class FIRFilter: public Filter {
public:
FIRFilter(double *doublearray,int doublenum);
};
class IIRFilter : public Filter {
public:
IIRFilter(double *doublearray,int doublenum,double *doublearray,int doublenum);
};
initsave(SignalFilter)
class SignalFilter : public SignalSource {
public:
SignalFilter(long length,SignalSource *src,Filter *flt);
};
exceptionhandle(Signal::value,ExceptionOutOfBounds,PyExc_IndexError)
exceptionhandle(Signal::__call__,ExceptionOutOfBounds,PyExc_IndexError)
%nodefault Signal;
class Signal {
public:
virtual void reset(unsigned long seed = 0);
virtual double value(double time);
virtual double value(double timebase,double timecorr);
%extend {
double __call__(double time) {
return self->value(time);
};
};
};
typedef Signal Noise;
%nodefault Interpolator;
class Interpolator;
class NearestInterpolator : public Interpolator {
public:
NearestInterpolator();
};
class LinearInterpolator : public Interpolator {
public:
LinearInterpolator();
};
class LinearExtrapolator : public Interpolator {
public:
LinearExtrapolator();
};
class LagrangeInterpolator : public Interpolator {
public:
LagrangeInterpolator(int semiwin);
};
class DotLagrangeInterpolator : public Interpolator {
public:
DotLagrangeInterpolator(int semiwin);
};
class NewLagrangeInterpolator : public Interpolator {
public:
NewLagrangeInterpolator(int semiwin);
};
class NoSignal : public Signal {
public:
NoSignal();
};
initsave(SumSignal)
class SumSignal : public Signal {
public:
SumSignal(Signal *s1,Signal *s2);
};
initsave(InterpolatedSignal)
class InterpolatedSignal : public Signal {
public:
InterpolatedSignal(SignalSource *src,Interpolator *interp,
double deltat,double prebuffer = 0.0,double norm = 1.0);
~InterpolatedSignal();
void setinterp(Interpolator *inte);
};
%pythoncode %{
def getInterpolator(interplen=1):
if interplen == 0:
ret = NearestInterpolator()
elif interplen == -1:
ret = LinearExtrapolator()
elif interplen == 1:
ret = LinearInterpolator()
elif interplen > 1:
ret = LagrangeInterpolator(interplen)
elif interplen < -1:
ret = DotLagrangeInterpolator(-interplen)
else:
raise NotImplementedError, "getInterpolator: undefined interpolator length %s (lisasim-swig.i)." % interplen
return ret
def getDerivativeInterpolator(interplen=2):
if interplen > 1:
return DotLagrangeInterpolator(interplen)
else:
raise NotImplementedError, "getDerivativeInterpolator: undefined interpolator length %s (lisasim-swig.i)." % interplen
%}
%pythoncode %{
def PowerLawNoise(deltat,prebuffer,psd,exponent,interplen=1,seed=0):
nyquistf = 0.5 / deltat
if exponent == 0:
filter = NoFilter()
normalize = math.sqrt(psd) * math.sqrt(nyquistf)
elif exponent == 2:
filter = DiffFilter()
normalize = math.sqrt(psd) * math.sqrt(nyquistf) / (2.00 * math.pi * deltat)
elif exponent == -2:
filter = IntFilter()
normalize = math.sqrt(psd) * math.sqrt(nyquistf) * (2.00 * math.pi * deltat)
elif exponent == -4:
filter = IIRFilter([1,2,1],[0,0.9999*2,-0.9999])
normalize = math.sqrt(psd) * math.sqrt(nyquistf) * (math.pi * deltat)**2
else:
raise NotImplementedError, "PowerLawNoise: undefined PowerLaw exponent %s (lisasim-swig.i)." % exponent
if seed == 0:
seed = getcseed()
whitenoise = WhiteNoiseSource(int(prebuffer/deltat+32),seed)
filterednoise = SignalFilter(int(prebuffer/deltat+32),whitenoise,filter)
interp = getInterpolator(interplen)
noise = InterpolatedSignal(filterednoise,interp,deltat,prebuffer,normalize)
noise.xmltype = 'PowerLawNoise'
noise.xmlargs = [deltat,prebuffer,psd,exponent,interplen,seed]
return noise
%}
%pythoncode %{
def SampledSignal(array,deltat,buffer = 136.0,norm = 1.0,filter = None,interplen = 1,timeoffset = 0.0,endianness = -1,readbuffer=2**20):
interp = getInterpolator(interplen)
if isinstance(array,numpy.ndarray):
samplednoise = SampledSignalSource(array,norm)
elif isinstance(array,str):
readbuffer = max(int(buffer/deltat),int(readbuffer))
# the endianness parameter supports the MATLAB convention,
# as well as the XSIL descriptors
if endianness == 'n':
endianness = -1
elif endianness == 'b' or endianness == 'BigEndian':
endianness = 0
elif endianness == 'l' or endianness == 'LittleEndian':
endianness = 1
samplednoise = FileSignalSource(array,readbuffer,int(buffer/deltat),endianness,norm)
else:
raise NotImplementedError, "SampledSignal: need numpy array or filename as first argument (lisasim-swig.i)."
if not filter:
filteredsamples = 0
interpolatednoise = InterpolatedSignal(samplednoise,interp,deltat,-timeoffset)
else:
filteredsamples = SignalFilter(int(buffer/deltat),samplednoise,filter)
interpolatednoise = InterpolatedSignal(filteredsamples,interp,deltat,-timeoffset)
return interpolatednoise
%}
%feature("docstring") CachedSignal "
CachedSignal(Signal,bufferlen,deltat,interplen = 4)
"
initsave(CachedSignal)
class CachedSignal : public Signal {
public:
CachedSignal(Signal *s,long length,double deltat,int interplen = 4);
};
/* -------- Wave objects -------- */
%feature("docstring") Wave "
Wave is the base class for all GW objects; all Wave objects represent
plane waves incoming from a definite position in the sky (as
characterized by its SSB ecliptic latitude and longitude) with a
definite polarization angle.
- Wave provides putk(), which returns the GW direction of propagation,
and putwave(t), which returns the gravitational strain tensor at
time t at the SSB.
- All derived Wave objects must define hp(t) and hc(t), which describe
the time dependence of the two independent GW polarizations.
Wave, and most of its derived classes, are defined in lisasim-wave.cpp"
%feature("docstring") Wave::putk "
Wave.putk() -> (kx,ky,kz) returns a 3-tuple with the SSB components
(normalized) of GW propagation vector."
%feature("docstring") Wave::putwave "
Wave.putwave(t) -> ((hxx,hxy,hxz),(hyx,hyy,hyz),(hzx,hzy,hzz)) returns
a nested 3-tuple with the gravitational strain tensor at time t [s] at
the SSB."
%feature("docstring") Wave::hp "
Wave.hp(t) returns the hp polarization of the GW Wave at time t [s] at
the SSB."
%feature("docstring") Wave::hc "
Wave.hc(t) returns the hc polarization of the GW Wave at time t [s] at
the SSB."
%feature("docstring") Wave::putep "
Wave.putep(elat,elon,pol) returns the basic ep polarization tensor
for a plane Wave object at ecliptic latitude elat, longitude elon,
and polarization pol. This is a class (static) method.
"
%feature("docstring") Wave::putec "
Wave.putec(elat,elon,pol) returns the basic ec polarization tensor
for a plane Wave object at ecliptic latitude elat, longitude elon,
and polarization pol. This is a class (static) method.
"
class WaveObject;
%nodefault Wave;
class Wave : public WaveObject {
public:
void putk(Vector &outvector);
void putwave(Tensor &outtensor, double t);
virtual double hp(double t);
virtual double hc(double t);
static void putep(Tensor &outtensor,double b,double l,double p);
static void putec(Tensor &outtensor,double b,double l,double p);
};
%feature("docstring") SimpleBinary "
SimpleBinary(f,phi0,inc,amp,elat,elon,pol) returns a Wave object that
models the waveform emitted by a simple monochromatic binary with the
following parameters:
- the wave has frequency f [Hz] (so the binary has orbital frequency
f/2) and initial phase phi0;
- the hp and hc polarizations have a relative phase shift pi/2 and
have an amplitude amp distributed consistently with a binary
inclination angle inc:
hp = amp * (1 + cos(inc)^2) * cos(2*pi*f*t + phi0),
hc = amp * 2*cos(inc) * sin(2*pi*f*t + phi0);
- the wave is incoming from sky position (elat,elon), with
polarization pol.
This Wave object is deprecated in favor of GalacticBinary."
initdoc(SimpleBinary)
initsave(SimpleBinary)
class SimpleBinary : public Wave {
public:
SimpleBinary(double freq, double phi0, double inc, double amp, double elat, double elon, double pol);
};
%feature("docstring") GalacticBinary "
GalacticBinary(f,fdot,elat,elon,amp,inc,pol,phi0) returns a Wave object that
models the waveform emitted by a linearly chirping monochromatic binary
with the following parameters (compatible with MLDC conventions):
- the wave has frequency f [Hz] (so the binary has orbital frequency
f/2), frequency derivative fdot [Hz/s], both measured at time 0,
and initial phase phi0;
- the hp and hc polarizations have a relative phase shift pi/2 and
have an amplitude amp distributed consistently with a binary
inclination angle inc:
hp = amp * (1 + cos(inc)^2) * cos(2*pi*f*(t + 0.5*fdot*t**2) + phi0),
hc = amp * -2*cos(inc) * sin(2*pi*f*(t + 0.5*fdot*t**2) + phi0);
- the wave is incoming from sky position (elat,elon), with
polarization pol."
initdoc(GalacticBinary)
initsave(GalacticBinary)
class GalacticBinary : public Wave {
public:
GalacticBinary(double freq, double freqdot, double elat, double elon, double amp, double inc, double pol, double phi0, double freqddot = 0.0, double epsilon = 0.0);
};
%feature("docstring") SimpleMonochromatic "
SimpleMonochromatic(f,phi,gamma,amp,elat,elon,pol) returns a Wave
object that implements a simple sinusoidal wave with the following
parameters:
- the wave has frequency f [Hz];
- the hp and hc polarizations have a relative phase shift phi and
amplitude amp distributed according to the angle gamma:
hp = amp * sin(gamma) * sin(2*pi*f*t + phi),
hc = amp * cos(gamma) * sin(2*pi*f*t);
- the wave is incoming from sky position (elat,elon), with
polarization pol."
initdoc(SimpleMonochromatic)
class SimpleMonochromatic : public Wave {
public:
SimpleMonochromatic(double freq, double phi, double gamma, double amp, double elat, double elon, double pol);
};
%feature("docstring") GaussianPulse "
GaussianPulse(t0,efold,gamma,amp,elat,elon,pol) returns a Wave object
that implements a Gaussian wavepulse with the following parameters:
- the pulse is centered at SSB baricentric time t0 [seconds];
- the pulse has e-folding time efold [seconds];
- the pulse has amplitude amp, distributed as {ap,ac} =
amp*{sin(gamma),cos(gamma)} between the two polarizations
(the same convention as SimpleMonochromatic)
- the pulse is incoming from sky position (elat,elon), with
polarization pol.
The amplitude of the pulse is cut to zero at 10 efolding times from
the central time (this is set by GaussianPulse::sigma_cutoff in
lisasim-wave.cpp)."
initdoc(GaussianPulse)
class GaussianPulse : public Wave {
public:
GaussianPulse(double time, double decay, double gamma, double amp, double b, double l, double p);
};
%feature("docstring") SineGaussian "
SineGaussian(t0,efold,f,phi0,gamma,amp,elat,elon,pol) returns a Wave object
that implements a Sine-Gaussian wavepulse with the following parameters:
- the pulse is centered at SSB baricentric time t0 [seconds];
- the pulse has e-folding time efold [seconds];
- the pulse is modulated by a sinusoid of frequency f, centered at time
t0, with relative phase phi0 between the two polarizations;
- the pulse has amplitude amp, distributed as {ap,ac} =
amp*{sin(gamma),cos(gamma)} between the two polarizations
(the same convention as SimpleMonochromatic)
- the pulse is incoming from sky position (elat,elon), with
polarization pol.
The amplitude of the pulse is cut to zero at 10 efolding times from
the central time (this is set by SineGaussian::sigma_cutoff in
lisasim-wave.cpp)."
initdoc(SineGaussian)
class SineGaussian : public Wave {
public:
SineGaussian(double time, double decay, double freq, double phase0, double gamma, double amp, double b, double l, double p);
};
%feature("docstring") NoiseWave "
NoiseWave(hpnoise,hcnoise,elat,elon,pol),
NoiseWave(deltat,prebuffer,psd,filter,interp,elat,elon,pol)
return Wave objects that represent a noise-like plane GW incoming from
sky position (elat,elon) with polarization pol.
With the first form, hpnoise and hcnoise are Noise objects (previously
instantiated, e.g., with InterpolateNoise) that provide the GW
polarizations directly from the methods hpnoise.noise(t) and
hpnoise.noise(t)
With the second form, hp(t) and hc(t) are fed from two independent
pseudorandom noise streams (implemented with InterpolateNoise), where:
- deltat [s] is the time spacing of the pseudorandom samples at
generation;
- prebuffer [s ???] sets the minimum buffering interval for the
pseudorandom sequences, which are stored in ring buffers (i.e.,
after pseudorandom noise has been requested and computed at time t,
the earliest value guaranteed to be available will be at time t -
prebuffer);
- psd and filter set the one-sided PSD of the pseudorandom noise
stream to psd*(f/Hz)^filter Hz^-1 (currently only filter = -2, 0, 2
is implemented);
- interp (> 1) sets the semiwidth of the data window used in Lagrange
interpolation (1 yields linear interpolation).
The parameter prebuffer should generally be set higher for a NoiseWave
object than it would be for an InterpolateNoise object, because hp(t)
and hc(t) are defined in terms of SSB time, so the polarization values
needed to build (say) X at t = 0 may require accessing hp and hc at
the SSB t = -500 s, or earlier; on the other hand, when Synthetic LISA
builds new InterpolateNoise objects it fills the ring buffer with
values in the interval [-prebuffer,0].
NoiseWave can also be created from arrays of previously
generated waveform samples, using the SampledWave syntax (see help for
SampledWave):
NoiseWave(hparray,hcarray,len,deltat,prebuffer,norm,filter,interp,
elat,elon,pol)
TODO: details to be addressed: does the choice of interpolation affect
the effective prebuffering interval? ???"
initdoc(NoiseWave)
initsave(NoiseWave)
%apply double *NUMPY_ARRAY_DOUBLE { double *hpa };
%apply double *NUMPY_ARRAY_DOUBLE { double *hca };
class NoiseWave : public Wave {
public:
// with Noise objects, given directly
NoiseWave(Noise *noisehp, Noise *noisehc, double elat, double elon, double p);
// allocates its own Noise objects
NoiseWave(double sampletime, double prebuffer, double density, double exponent, int swindow, double elat, double elon, double p);
// from sampled buffers (using filters and interpolation...)
NoiseWave(double *hpa, double *hca, long samples, double sampletime, double prebuffer, double norm, Filter *filter, int swindow, double b, double l, double p);
~NoiseWave();
double hp(double t);
double hc(double t);
};
/* SampledWave is implemented as a Python factory function for
NoiseWave; this is the best way (better than a C++ factory
function) to assure that garbage collection does not disturb its
arguments. */
// ??? It would be interesting not to have to give the length of the arrays...
%pythoncode %{
def SampledWave(hparray,hcarray,len,deltat,prebuffer,norm,filter,interp,elat,elon,pol):
"""Returns a Wave object that represent a sampled plane GW incoming from
sky position (elat,elon) with polarization pol, where:
- hparray and hcarray are 1-D numpy arrays of length len containing
time series for the hp and hc polarizations;
- deltat [s] is the time spacing of the time series;
- prebuffer [s ???] sets the indexing offset of the arrays with
respect to the SSB time, so that (temporarily forgetting
interpolation) hp(t) = hparray[(t - prebuffer)/deltat].
This padding is needed because hp(t) and hc(t) are defined in terms
of SSB time: the polarization values needed to build (say) X at t =
0 may require accessing hp and hc at the SSB t = -500 s, or earlier;
- norm and filter set the normalization and filtering of the sampled
arrays. The parameter filter must be a SynthLISA Filter object, or
0 if only normalization is required;
- interp (> 1) sets the semiwidth of the data window used in Lagrange
interpolation (1 yields linear interpolation).
SampledWave is represented internally using NoiseWave.
TODO: check if the prebuffering formula above is exact or if there is
another displacement by one or so."""
wave = NoiseWave(hparray,hcarray,len,deltat,prebuffer,norm,filter,interp,elat,elon,pol)
wave.xmltype = 'SampledWave'
wave.xmlargs = [hparray,hcarray,len,deltat,prebuffer,norm,filter,interp,elat,elon,pol]
return wave
%}
/* Provide backward compatibility to InterpolateMemory (essentially
the same as SampledWave, without possibility of normalizing,
filtering, or changing the interpolation scheme); note that the
prebuffering convention might be slightly different. */
%pythoncode %{
def InterpolateMemory(hparray,hcarray,len,deltat,prebuffer,elat,elon,pol):
"""For backward compatibility, equivalent to
NoiseWave(hparray,hcarray,len,deltat,prebuffer,1.0,0,1,elat,elon,pol)."""
return NoiseWave(hparray,hcarray,len,deltat,prebuffer,1.0,0,1,elat,elon,pol)
%}
%feature("docstring") PyWave "
PyWave(hpfunc,hcfunc,elat,elon,pol)
returns a Wave object that represents a generic plane GW incoming from
ecliptic latitude elat and longitude elon, with polarization pol. The
parameters hpfunc(t) and hcfunc(t) are Python functions that must
return the hp and hc polarizations at SSB time t.
While not too efficient, PyWave may be the simplest way to extend the
Synthetic-LISA built-in Wave objects."
initdoc(PyWave)