Changeset 31


Ignore:
Timestamp:
May 20, 2014 3:22:42 PM (10 years ago)
Author:
JohnLightfoot
Message:

various improvements

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/doublefourier.py

    r17 r31  
    22
    33import collections
     4import math
    45import numpy as np
    56import pp
    67
    7 def test(nx=50, ny=50):
    8     # NOT WORKING
    9     # all wavenumbers are cm-1
    10     wn_max = 100.0
    11     wn_min = 50.0
    12 
    13     resolution_min = 300.0
    14 
    15     delta_wn = wn_min / resolution_min
    16 
    17     # spectra are evenly sampled from 0 to wn_max with spacing delta_wn
    18     nfreq = np.ceil(wn_max / delta_wn)
    19     wn_max = delta_wn * nfreq
    20 
    21     freqs = np.arange(nfreq)
    22     freqs *= delta_wn
    23 
    24     # construct a dummy 'sky'
    25     # numpy default indexing is C-style so that the rightmost index
    26     # 'changes the fastest'.
    27     sky_s = np.zeros([nfreq, ny, nx], np.float)
    28     sky_s[:,ny/2,nx/2] = 1.0
    29 
    30     # x coords in radians
    31     arcsec2rad = 1.0 / 206265
    32     sky_x = (np.arange(nx) - nx/2) * 1.0 * arcsec2rad
    33     sky_y = (np.arange(ny) - ny/2) * 1.0 * arcsec2rad
    34 
    35     # dummy baselines (each baseline entry is [u,v] in centimetres)
    36     baselines = []
    37     for i in range(500):
    38         baselines.append([20000.0, 20000.0])
    39 
    40     df = DoubleFourier(sky_s=sky_s, freqs=freqs, sky_x=sky_x, sky_y=sky_y,
    41       baselines=baselines)
    42 
    43     df.matlab_transform()
     8import common.commonobjects as co
     9
     10def fftshift(data, shift):
     11    """Method to shift a 2d complex data array by applying the
     12       given phase shift to its Fourier transform.
     13    """
     14    # move centre of image to array origin
     15    temp = numpy.fft.fftshift(data)
     16    # 2d fft
     17    temp = numpy.fft.fft2(temp)
     18    # apply phase shift
     19    temp *= shift
     20    # transform and shift back
     21    temp = numpy.fft.ifft2(temp)
     22    temp = numpy.fft.fftshift(temp)
     23
     24    return temp
    4425
    4526
     
    4829    """
    4930
    50     def __init__(self, parameters, previous_results):
     31    def __init__(self, parameters, previous_results, job_server):
    5132        self.parameters = parameters
    5233        self.previous_results = previous_results
    53 
    54         # paralle processing stuff
    55         ppservers = ()
    56         self.job_server = pp.Server(ppservers=ppservers)
    57         print 'DoubleFourier starting pp with %s workers' % \
    58           self.job_server.get_ncpus()
     34        self.job_server = job_server
    5935
    6036        self.result = collections.OrderedDict()     
     
    6440
    6541        fts = self.previous_results['fts']
    66         frequency_axis = fts['fts_wn']
     42        fts_wn = fts['fts_wn']
    6743        opd_max = fts['opd_max']
    6844        fts_nsample = fts['ftsnsample']
     
    8157        skymodel = skygenerator['sky model']
    8258        spatial_axis = self.result['spatial axis'] = skygenerator['spatial axis']
    83         self.result['frequency axis'] = frequency_axis
     59        self.result['frequency axis'] = fts_wn
    8460
    8561        # assuming nx is even then transform has 0 freq at origin and [nx/2] is
     
    10076            # FTS path diff and possibly baseline itself vary with time
    10177            for tindex,t in enumerate(times):
    102 #            for tindex,t in enumerate(times[:1]):
    103 
     78
     79                # calculate the sky that the system is observing at this
     80                # moment, incorporating various errors in turn
    10481                sky_now = skymodel
    105 
    106                 # what is the system looking at?
    107                 # add 'errors' in order
    10882
    10983                # 1. baseline should be perp to centre of field.
     
    11387                # for now assume 0 error but do full calculation for timing
    11488                # purposes
    115                 baseline_dx = 0.0
    116                 baseline_dy = 0.0
     89
     90                # perfect baseline is perpendicular to direction to 'centre'
     91                # on sky. Add errors in x,y,z - z towards sky 'centre'
     92                bz = 0.0
     93                # convert bz to angular error
     94                blength = math.sqrt(baseline[0]*baseline[0] +
     95                  baseline[1]*baseline[1])
     96                bangle = (180.0 * 3600.0 / math.pi) * bz / blength
     97                bx_error = bangle * baseline[0] / blength
     98                by_error = bangle * baseline[1] / blength
    11799
    118100                # calculate xpos, ypos in units of pixel - numpy arrays
    119101                # [row,col]
    120102                nx = len(spatial_axis)
    121                 colpos = float(nx-1) * float (baseline_dx - spatial_axis[0]) / \
     103                colpos = float(nx-1) * bx_error / \
    122104                  (spatial_axis[-1] - spatial_axis[0])
    123                 rowpos = float(nx-1) * float (baseline_dy - spatial_axis[0]) / \
     105                rowpos = float(nx-1) * by_error / \
    124106                  (spatial_axis[-1] - spatial_axis[0])
    125 
    126                 if colpos < 0 or colpos > (nx-1) or rowpos < 0 or rowpos > \
    127                   (nx-1):
    128                     raise Exception, \
    129                       'baseline centre outside limits of sky model'
    130107
    131108                # calculate fourier phase shift to move point at [0,0] to
    132109                # [rowpos, colpos]
     110                print 'shift', colpos, rowpos
    133111                shiftx = np.zeros([nx], np.complex)
    134112                shiftx[:nx/2] = np.arange(nx/2, dtype=np.complex)
     
    147125                    shift[:,i] *= shifty
    148126
     127                jobs = {}
    149128                # go through freq planes and shift them
    150                 for iwn,wn in enumerate(frequency_axis):
    151                     # move centre of image to array origin
    152                     temp = np.fft.fftshift(sky_now[:,:,iwn])
    153                     # 2d fft
    154                     temp = np.fft.fft2(temp)
    155                     # apply phase shift
    156                     temp *= shift
    157                     # transform and shift back
    158                     temp = np.fft.ifft2(temp)
    159                     temp = np.fft.fftshift(temp)
    160 #                    imag part should still be 0
    161 #                    print 'max real', np.max(np.real(temp))
    162 #                    print 'max imag', np.max(np.imag(temp))
    163                     temp = np.abs(temp)
    164                     sky_now[:,:,iwn] = np.fft.fftshift(temp)
     129                for iwn,wn in enumerate(fts_wn):
     130                    # submit jobs
     131                    indata = (sky_now[:,:,iwn], shift,)
     132                    jobs[wn] = self.job_server.submit(fftshift,
     133                      indata, (), ('numpy',))
     134               
     135                for iwn,wn in enumerate(fts_wn):
     136                    # collect and store results
     137                    temp = jobs[wn]()
     138                    sky_now[:,:,iwn] = temp
    165139
    166140                if t == times[0]:
    167141                    self.result['sky at time 0'] = sky_now
    168                
     142
    169143                # 2. telescopes should be centred on centre of field
    170144                #    Telescopes collect flux from the 'sky' and pass
     
    176150
    177151                # multiply sky by amplitude beam 1 * amplitude beam 2
    178                 for iwn,wn in enumerate(frequency_axis):
     152                amp_beam_1 = beamsgenerator['primary amplitude beam'].data
     153                amp_beam_2 = beamsgenerator['primary amplitude beam'].data
     154
     155                for iwn,wn in enumerate(fts_wn):
    179156                    # calculate shifted beams here
    180157                    # for now assume no errors and just use beam
    181158                    # calculated earlier
    182 
    183                     amplitude_beam = beamsgenerator['primary amplitude beam']\
    184                       [wn]               
    185                     amp_beam_1 = amplitude_beam.data
    186                     amp_beam_2 = amplitude_beam.data
    187                     sky_now[:,:,iwn] *= amp_beam_1 * amp_beam_2
     159                    pass
     160
     161                # multiply sky by amplitude beams of 2 antennas
     162                sky_now *= amp_beam_1 * amp_beam_2
    188163
    189164                if t == times[0]:
     
    192167                # 3. baseline error revisited
    193168                # derive baseline at this time
     169                #
     170                # Perhaps baseline should be a continuous function in
     171                # time, which would allow baselines that intentionally
     172                # smoothly vary (as in rotating tethered assembly)
     173                # and errors to be handled by one description.
     174                #
     175                # what follows assumes zero error
     176
    194177                baseline_error = 0.0
    195178                baseline_now = baseline + baseline_error
    196 #                print 'baseline_now', baseline_now
    197 
    198 #                gamma_12[(baseline,t)] = 0.0
     179
    199180                fft_now = np.zeros(np.shape(sky_now), np.complex)
    200                 spectrum = np.zeros(np.shape(frequency_axis), np.complex)
    201                 for iwn,wn in enumerate(frequency_axis):
     181                spectrum = np.zeros(np.shape(fts_wn), np.complex)
     182                for iwn,wn in enumerate(fts_wn):
    202183
    203184                    # derive shift needed to place baseline at one of FFT coords
    204185                    # this depends on physical baseline and frequency
    205186                    baseline_now_lambdas = baseline_now * wn * 100.0
    206 #                    print 'baseline lambda', wn, baseline_now_lambdas
    207 
    208                     # calculate baseline position in units of pixels of FFTed sky -
    209                     # numpy arrays [row,col]
    210                     colpos = float(nx-1) * float(baseline_now_lambdas[0] - spatial_freq_axis[0]) / \
     187
     188                    # calculate baseline position in units of pixels of FFTed
     189                    # sky - numpy arrays [row,col]
     190                    colpos = float(nx-1) * \
     191                      float(baseline_now_lambdas[0] - spatial_freq_axis[0]) / \
    211192                      (spatial_freq_axis[-1] - spatial_freq_axis[0])
    212                     rowpos = float(nx-1) * float(baseline_now_lambdas[1] - spatial_freq_axis[0]) / \
     193                    rowpos = float(nx-1) * \
     194                      float(baseline_now_lambdas[1] - spatial_freq_axis[0]) / \
    213195                      (spatial_freq_axis[-1] - spatial_freq_axis[0])
    214 #                    print 'spatial colpos, rowpos', colpos, rowpos
     196                    colpos = 0.0
     197                    rowpos = 0.0
     198                    print 'spatial colpos, rowpos', colpos, rowpos
    215199
    216200                    # calculate fourier phase shift to move point at [rowpos,colpos] to
     
    219203                    shiftx[:nx/2] = np.arange(nx/2, dtype=np.complex)
    220204                    shiftx[nx/2:] = np.arange(-nx/2, 0, dtype=np.complex)
    221                     shiftx = np.exp((-2.0j * np.pi * colpos * shiftx) / float(nx))
     205                    shiftx = np.exp((-2.0j * np.pi * colpos * shiftx) / \
     206                      float(nx))
    222207
    223208                    shifty = np.zeros([nx], np.complex)
     
    238223                    # 2d fft
    239224                    temp = np.fft.fft2(temp)
    240                     # shift 0 freq to centre of array
    241                     fft_now[:,:,iwn] = np.fft.ifftshift(temp)
    242 
     225                    fft_now[:,:,iwn] = temp
     226
     227                    # set amp/phase at this frequency
    243228                    spectrum[iwn] = temp[0,0]
    244229
    245230                if t == times[0]:
    246231                    self.result['skyfft at time 0'] = fft_now
     232
     233                    axis = co.Axis(data=fts_wn, title='wavenumber',
     234                      units='cm-1')
     235                    temp = co.Spectrum(data=spectrum, axis=axis,
     236                      title='Detected spectrum', units='W sr-1 m-2 Hz-1')
     237                    self.result['skyfft spectrum at time 0'] = temp
    247238
    248239                # 3. FTS sampling should be accurate
    249240                #    derive lag due to FTS path difference
    250241                #    0 error for now
     242
     243                if t == times[0]:
     244                    # test version
     245                    # inverse fft of emission spectrum at this point
     246                    temp = np.fft.ifft(spectrum)
     247                    pos = np.fft.rfftfreq(len(spectrum))
     248
     249                    # move 0 frequency to centre of array
     250                    temp = np.fft.fftshift(temp)
     251                    pos = np.fft.fftshift(pos)
     252
     253                    axis = co.Axis(data=pos, title='path difference',
     254                      units='cm')
     255                    temp = co.Spectrum(data=temp,
     256                      title='Detected interferogram', units='')
     257
     258                    self.result['test FTS at time 0'] = temp
     259
    251260                mirror_error = 0.0
    252261                opd = 2.0 * (vdrive * t + mirror_error)
     
    255264
    256265                # make spectrum symmetric
    257                 nfreq = len(frequency_axis)
     266                nfreq = len(fts_wn)
    258267                symmetric_spectrum = np.zeros([2*nfreq])
    259268                symmetric_spectrum[:nfreq] = spectrum
     
    271280                measurement[tindex] = spectrum_fft[0]
    272281
    273             self.result['baseline interferograms'][tuple(baseline)] = measurement
     282            self.result['baseline interferograms'][tuple(baseline)] = \
     283              measurement
    274284
    275285        return self.result
Note: See TracChangeset for help on using the changeset viewer.