예제 #1
0
    def test_colorfy(self):
        """Test colorfy"""

        color.colorfy("This is a plain string")
        color.colorfy("This is a {{%red string}}")
        color.colorfy("This is an {{%underline string}}")
        color.colorfy("This is an {{%yellow {{%underline string}}}}")
예제 #2
0
파일: progress.py 프로젝트: lwa-project/lsl
    def show(self):
        """
        Build a string representation of the progress bar and return it.
        """

        if self.print_percent:
            # If we want the percentage also displayed, trim a little
            # more from the progress bar's wdith
            barSpan = self.span - 9
            nMarks = float(self.amount) / self.max * barSpan
            nMarksFull = int(nMarks)
            if nMarksFull < barSpan:
                partial = nMarks - nMarksFull
                lastMark = self.rotations[int(partial * len(self.rotations))]
            else:
                lastMark = ''
            bar = self.sym * nMarksFull
            bar = bar + lastMark
            bar = bar + (' ' * (barSpan - (nMarksFull + len(lastMark))))
            nte = "%5.1f%%" % (float(self.amount) / self.max * 100)

            if self.color is None:
                out = "[%s] %s" % (bar, nte)
            else:
                out = colorfy("[{{%%%s %s}}] %s" % (self.color, bar, nte))
        else:
            # Progress bar only
            barSpan = self.span - 2
            nMarks = float(self.amount) / self.max * barSpan
            nMarksFull = int(nMarks)
            if nMarksFull < barSpan:
                partial = nMarks - nMarksFull
                lastMark = self.rotations[int(partial * len(self.rotations))]
            else:
                lastMark = ''
            bar = self.sym * nMarksFull
            bar = bar + lastMark
            bar = bar + (' ' * (barSpan - (nMarksFull + len(lastMark))))

            if self.color is None:
                out = "[%s]" % bar
            else:
                out = colorfy("[{{%%%s %s}}]" % (self.color, bar))

        return out
예제 #3
0
def downsample(vector, factor, rescale=True):
    """
    Downsample (i.e. co-add consecutive numbers) a vector by an integer 
    factor.  Trims the input timeseries to be a multiple of the downsample 
    factor, if needed.  If rescale == True, then divides each sum by factor 
    to produce a mean value, otherwise just adds the values in the vector.
    """

    if (len(vector) % factor):
        warnings.warn(colorfy("{{%%yellow Length of 'vector' is not divisible by 'factor'=%d, clipping!}}" % factor), RuntimeWarning)
        newlen = (len(vector)//factor)*factor
        warnings.warn(colorfy("{{%%yellow Oldlen %d, newlen %d}}" % (len(vector), newlen)), RuntimeWarning)
        vector = vector[:newlen]
    if rescale:
        newvector = numpy.reshape(vector, (len(vector)//factor, factor))/float(factor)
    else:
        newvector = numpy.reshape(vector, (len(vector)//factor, factor))
        
    return numpy.add.reduce(newvector, 1)
예제 #4
0
def _download_worker_standard(url, filename):
    """
    Download the URL and save it to a file.
    """

    # Attempt to download the data
    print("Downloading %s" % url)
    try:
        tecFH = urlopen(url, timeout=DOWN_CONFIG.get('timeout'))
        meta = tecFH.info()
        try:
            remote_size = int(meta.getheaders("Content-Length")[0])
        except AttributeError:
            remote_size = 1
        pbar = DownloadBar(max=remote_size)
        while True:
            new_data = tecFH.read(DOWN_CONFIG.get('block_size'))
            if len(new_data) == 0:
                break
            pbar.inc(len(new_data))
            try:
                data += new_data
            except NameError:
                data = new_data
            sys.stdout.write(pbar.show() + '\r')
            sys.stdout.flush()
        tecFH.close()
        sys.stdout.write(pbar.show() + '\n')
        sys.stdout.flush()
    except IOError as e:
        warnings.warn(
            colorfy("{{%%yellow Error downloading file from %s: %s}}" %
                    (url, str(e))), RuntimeWarning)
        data = ''
    except socket.timeout:
        data = ''

    # Did we get anything or, at least, enough of something like it looks like
    # a real file?
    if len(data) < 3:
        ## Fail
        return False
    else:
        ## Success!  Save it to a file
        with _CACHE_DIR.open(filename, 'wb') as fh:
            fh.write(data)

        ## Further processing, if needed
        if os.path.splitext(filename)[1] == '.Z':
            ## Save it to a regular gzip'd file after uncompressing it.
            _convert_to_gzip(filename)

        return True
예제 #5
0
파일: busy.py 프로젝트: lwa-project/lsl
    def _render_flow(self, active=True):
        out = [
            ' ',
        ] * self.width
        for i in (-2, -1, 0):
            out[self._i + i] = '>'
        out = ''.join(out)
        if self.color is not None:
            out = colorfy("{{%%%s %s}}" % (self.color, out))

        self._i += 1
        self._i %= self.width
        return out
예제 #6
0
def _regrid_linear(x, y, newx, allow_extrapolation=False):
    """
    Implement regrid() function using linear interpolation.
    """
    
    if allow_extrapolation:
        warnings.warn(colorfy("{{%yellow allow_extrapolation=True not honored for regrid_linear"), RuntimeWarning)
        
    if newx.min() < x.min():
        raise ValueError('x.min(%f) must be smaller than newx.min(%f)' % (x.min(), newx.min()))
    if newx.max() > x.max():
        raise ValueError('x.max(%f) must be larger than newx.max(%f)' % (x.max(), newx.max()))
        
    return numpy.interp(newx, x, y)
예제 #7
0
파일: busy.py 프로젝트: lwa-project/lsl
    def _render_boomerang(self, active=True):
        out = [
            ' ',
        ] * self.width
        out[self._i] = ('|', '/', '-', '\\')[self._i % 4]
        out = ''.join(out)
        if self.color is not None:
            out = colorfy("{{%%%s %s}}" % (self.color, out))

        self._i += self._dir
        if self._i < 0:
            self._i += 1
            self._dir = 1
        if self._i == self.width:
            self._i -= 2
            self._dir = -1
        return out
예제 #8
0
파일: busy.py 프로젝트: lwa-project/lsl
    def _run(self):
        """
        Internal function used by the thread to make/change the displayed text.
        """

        while self.alive.isSet():
            if self.color is None:
                out = "%s%s%s\r" % (self.message, '.' * self._i, ' ' *
                                    (self.dots - self._i))
            else:
                out = colorfy("%s{{%%%s %s}}%s\r" %
                              (self.message, self.color, '.' * self._i, ' ' *
                               (self.dots - self._i)))
            sys.stdout.write(out)
            sys.stdout.flush()

            self._i += 1
            self._i %= (self.dots + 1)
            time.sleep(self.interval)
예제 #9
0
파일: vdif.py 프로젝트: lwa-project/lsl
def read_guppi_header(filehandle):
    """
    Read in a GUPPI header at the start of a VDIF file from the VLA.  The 
    contents of the header are returned as a dictionary.
    """

    # Is there a GUPPI header?
    header = {}
    if not has_guppi_header(filehandle):
        warnings.warn(
            colorfy(
                "{{%yellow GUPPI header not found, returning an empty dictionary}}"
            ), RuntimeWarning)
        return header

    # Read in the GUPPI header
    while True:
        line = filehandle.read(80)
        try:
            line = line.decode(encoding='ascii', errors='ignore')
        except AttributeError:
            pass

        if line[:3] == 'END':
            break
        elif line[:8] == 'CONTINUE':
            junk, value2 = line.split(None, 1)
            value = "%s%s" % (value[:-1], value2[:-1])
        else:
            name, value = line.split('=', 1)
            name = name.strip()
        try:
            value = int(value, 10)
        except ValueError:
            try:
                value = float(value)
            except ValueError:
                value = value.strip().replace("'", '')
        header[name.strip()] = value
    header['OBSBW'] *= 1e6
    header['OBSFREQ'] *= 1e6

    return header
예제 #10
0
def is_valid(tarname, verbose=False):
    """
    Given a filename, see if it is valid metadata tarball or not.
    
    .. versionadded:: 1.2.0
    """

    passes = 0
    failures = 0
    try:
        get_session_spec(tarname)
        passes += 1
        if verbose:
            print(colorfy("Session specification - {{%green OK}}"))
    except IOError as e:
        raise e
    except:
        failures += 1
        if verbose:
            print(colorfy("Session specification - {{%red {{%bold FAILED}}}}"))

    try:
        get_observation_spec(tarname)
        passes += 1
        if verbose:
            print(colorfy("Observation specification(s) - {{%green OK}}"))
    except:
        failures += 1
        if verbose:
            print(
                colorfy(
                    "Observation specification(s) - {{%red {{%bold FAILED}}}}")
            )

    try:
        get_command_script(tarname)
        passes += 1
        if verbose:
            print(colorfy("Command script - {{%green OK}}"))
    except:
        failures += 1
        if verbose:
            print(colorfy("Command script - {{%red {{%bold FAILED}}}}"))

    if verbose:
        print("---")
        print("%i passed / %i failed" % (passes, failures))

    return False if failures else True
예제 #11
0
파일: busy.py 프로젝트: lwa-project/lsl
    def _render_pingpong(self, active=True):
        sym = 'o' if active else '.'
        out = ''
        if self._i == 0:
            out += ")%s" % sym
            out += ' ' * (self.width - 3)
            out += '|'
            self._dir = 1
        elif self._i == self.width - 3:
            out += '|'
            out += ' ' * (self.width - 3)
            out += "%s(" % sym
            self._dir = -1
        else:
            out += '|'
            out += ' ' * (self._i)
            out += sym
            out += ' ' * (self.width - self._i - 3)
            out += '|'
        if self.color is not None:
            out = colorfy(out.replace(sym, "{{%%%s %s}}" % (self.color, sym)))

        self._i += self._dir
        return out
예제 #12
0
파일: busy.py 프로젝트: lwa-project/lsl
    def stop(self, success=True):
        """
        Stop the indicator and display a 'Done'  or 'Failed' message depending on
        whether or not the 'success' keyword is True.
        
        .. note::
            This can take up to one BusyIndicator.interval to complete.
        """

        if self.thread is not None:
            if self.color is None:
                out = "%s%s%s%s\n" % (self.message, '.' * self._i, 'Done' if
                                      success else 'Failed', ' ' * self.dots)
            else:
                out = colorfy(
                    "%s{{%%%s %s}}%s%s\n" %
                    (self.message, self.color, '.' * self._i,
                     'Done' if success else 'Failed', ' ' * self.dots))
            sys.stdout.write(out)

            self.alive.clear()
            self.thread.join()
            self.thread = None
            self._i = 0
예제 #13
0
파일: vis.py 프로젝트: lwa-project/lsl
def build_sim_array(station,
                    antennas,
                    freq,
                    jd=None,
                    pos_error=0.0,
                    force_flat=False,
                    force_gaussian=False,
                    verbose=False):
    """
    Build a AIPY AntennaArray for simulation purposes.  Inputs are a station 
    object defined from the lwa_common module, a numpy array of stand 
    numbers, and a numpy array of frequencies in either Hz of GHz.  Optional 
    inputs are a Julian Date to set the array to and a positional error terms 
    that perturbs each of the stands in x, y, and z.  The output of this 
    module is an AIPY AntennaArray object.
    
    The shape of the antenna response is either flat (gain of 1 in all 
    directions), modeled by a 2-D Gaussian with the specified full width at
    half maximum in degrees, or modeled by a collection of spherical 
    harmonics that are polynomials in frequency.  The spherical harmonics 
    are used if the file 'beam_shape.npz' is found in the current directory.
    
    .. versionchanged:: 1.0.3
        Changed the meaning of the force_gaussian parameters so that the
        Gaussian full width at half maximum in degrees is passed in.
        
    .. versionchanged:: 1.0.1
        Moved the simulation code over from AIPY to the new _simFast module.  
        This should be much faster but under the caveats that the bandpass
        and antenna gain patterns are the same for all antennas.  This 
        should be a reasonable assumption for large-N arrays.
        
        Added an option to use a 2-D Gaussian beam pattern via the force_gaussian
        keyword.
        
    .. versionchanged:: 0.4.0
        Switched over to passing in Antenna instances generated by the
        :mod:`lsl.common.station` module instead of a list of stand ID numbers.
    """

    # If the frequencies are in Hz, we need to convert to GHz
    try:
        freqs = freq.copy()
    except AttributeError:
        freqs = numpy.array(freq)
        if freqs.shape == ():
            freqs.shape = (1, )
    if freqs.min() > 1e6:
        freqs /= 1.0e9

    # If the beam Alm coefficient file is present, build a more realistic beam
    # response.  Otherwise, assume a flat beam
    if force_gaussian:
        try:
            xw, yw = force_gaussian
            xw, yw = float(xw), float(yw)
        except (TypeError, ValueError) as e:
            xw = float(force_gaussian)
            yw = 1.0 * xw

        # FWHM to sigma
        xw /= 2.0 * numpy.sqrt(2.0 * numpy.log(2.0))
        yw /= 2.0 * numpy.sqrt(2.0 * numpy.log(2.0))

        # Degrees to radians
        xw *= numpy.pi / 180
        yw *= numpy.pi / 180

        if verbose:
            print(
                "Using a 2-D Gaussian beam with sigmas %.1f by %.1f degrees" %
                (xw * 180 / numpy.pi, yw * 180 / numpy.pi))
        beam = Beam2DGaussian(freqs, xw, yw)

    elif force_flat:
        if verbose:
            print("Using flat beam model")
        beam = Beam(freqs)

    else:
        if os.path.exists(os.path.join(dataPath, 'beam-shape.npz')):
            dd = numpy.load(os.path.join(dataPath, 'beam-shape.npz'))
            coeffs = dd['coeffs']

            deg = coeffs.shape[0] - 1
            lmax = int((math.sqrt(1 + 8 * coeffs.shape[1]) - 3) / 2)
            beamShapeDict = {}
            for i in range(deg + 1):
                beamShapeDict[i] = numpy.squeeze(coeffs[-1 - i, :])
            try:
                dd.close()
            except AttributeError:
                pass

            if verbose:
                print(
                    "Using Alm beam model with %i-order freq. polynomial and %i-order sph. harmonics"
                    % (deg, lmax))
            beam = BeamAlm(freqs,
                           lmax=lmax,
                           mmax=lmax,
                           deg=deg,
                           nside=128,
                           coeffs=beamShapeDict)
        else:
            if verbose:
                print("Using flat beam model")
            beam = Beam(freqs)

    if pos_error != 0:
        warnings.warn(
            colorfy(
                "{{%%yellow Creating array with positional errors between %.3f and %.3f m}}"
                % (-pos_error, pos_error)), RuntimeWarning)

    # Build an array of AIPY Antenna objects
    ants = []
    for antenna in antennas:
        top = numpy.array([antenna.stand.x, antenna.stand.y, antenna.stand.z])
        top += (2 * pos_error * numpy.random.rand(3) - pos_error
                )  # apply a random positional error if needed
        top.shape = (3, )
        eq = numpy.dot(aipy.coord.top2eq_m(0.0, station.lat), top)
        eq /= speedOfLight  # m -> s
        eq *= 1e9  # s -> ns

        delayCoeff = numpy.zeros(2)

        amp = 0 * antenna.cable.gain(freqs * 1e9) + 1

        ants.append(
            Antenna(eq[0],
                    eq[1],
                    eq[2],
                    beam,
                    phsoff=delayCoeff,
                    amp=amp,
                    stand=antenna.stand.id))

    # Combine the array of antennas with the array's location to generate an
    # AIPY AntennaArray object
    simAA = AntennaArray(station.aipy_location, ants)
    simAA._station = station

    # Set the Julian Data for the AntennaArray object if it is provided.  The try...except
    # clause is used to deal with people who may want to pass an array of JDs in rather than
    # just one.  If one isn't provided, use the date set for the input 'station'.
    if jd is None:
        simAA.date = station.date
    else:
        try:
            simAA.set_jultime(jd[0])
        except TypeError:
            simAA.set_jultime(jd)

    return simAA
예제 #14
0
    def __init__(self, necname, freq, rerun=True):
        # Modify NEC file to set FR card to use "freq"

        # Run NEC if necessary.
        # anntenna_pat_dB[az,alt] is the total gain or current in dB in the
        # direction az, alt (integer degrees), where az (azimuth) runs from
        # 0 to 359, where 0 is North and alt (altitude) runs from 0 to 89 ,
        # where 0 is the horizon The default pattern is all zeros (isotropic
        # response)
        self.antenna_pat_dB = zeros(shape=(360, 90), dtype=float32)
        self.antenna_pat_complex = zeros(shape=(360, 90), dtype=complex64)

        outname = os.path.splitext(necname)[0] + '.out'
        try:
            fh, filefreq = open_and_get_nec_freq(outname)
        except:
            warnings.warn(
                colorfy("{{%yellow NEC .out file not found!  Running NEC}}"),
                RuntimeWarning)
            fh = None

        if fh is None or not close_to(filefreq, freq):
            if rerun:
                warnings.warn(
                    colorfy(
                        "{{%yellow NEC output file is at a different frequency \
                    than the requested frequency: re-running}}"),
                    RuntimeWarning)
                if fh is not None:
                    fh.close()
                change_nec_freq(necname, freq)

                # Make sure we have NEC install
                if which_nec4() is None:
                    raise RuntimeError(
                        "NEC executable 'nec4d' not found in PATH")

                # Important NOTE:
                # This requires a modified version of NEC-4 that
                # takes 2 command line arguments instead of asking questions
                # interactively. See Paul Ray for info.
                try:
                    subprocess.check_call(['nec4d', necname, outname])
                except subprocess.CalledProcessError as e:
                    raise RuntimeError(
                        "Bad return value from nec2++ call : %e" % str(e))
                fh, filefreq = open_and_get_nec_freq(outname)
                if not close_to(filefreq, freq):
                    fh.close()
                    raise ValueError(
                        "NEC failed to generate a file with the correct frequency."
                    )

            else:
                raise ValueError("NEC output file is at a different frequency (%f) than the requested frequency (%f)." % \
                    (filefreq, freq))

        #  Now look for RADIATION PATTERN or EXCITATION and read it
        radpat = None
        for line in fh:
            if line.find('RADIATION PATTERN') >= 0:
                radpat = True
                break
            if line.find('EXCITATION') >= 0:
                radpat = False
                break
        else:
            raise RuntimeError("RADIATION PATTERN nor EXCITATION not found!")

        if radpat:
            self._read_radiation(fh)
        else:
            self._read_excitation(fh)

        fh.close()
예제 #15
0
파일: progress.py 프로젝트: lwa-project/lsl
    def show(self):
        """
        Build a string representation of the download bar and return it.
        """

        if self.t0 is None:
            # Have we started?
            cte = '----- B/s'
        elif self.amount == 0:
            # Have we gone far enough to get a "good" estimate?
            cte = '----- B/s'
        elif self.amount >= self.max:
            # Are we done?
            cte = self._pprint(self.amount)[:-2]
        elif self.t1 - self.t0 < 0.01:
            # Have we running long enough to get a "good" estimate?
            cte = '----- B/s'
        else:
            cte = self.amount / (self.t1 - self.t0)
            cte = self._pprint(cte)

        if self.print_percent:
            # If we want the percentage also displayed, trim a little
            # more from the progress bar's wdith
            barSpan = self.span - 10
            nMarks = float(self.amount) / self.max * barSpan
            nMarksFull = min([int(nMarks), barSpan])
            if nMarksFull < barSpan:
                partial = nMarks - nMarksFull
                lastMark = self.rotations[int(partial * len(self.rotations))]
            else:
                lastMark = ''
            bar = self.sym * nMarksFull
            bar = bar + lastMark
            bar = bar + (' ' * (barSpan - (nMarksFull + len(lastMark))))
            nte = "%5.1f%%" % (float(self.amount) / self.max * 100)
            if self.amount > self.max:
                nte = "-----%"

            if self.color is None:
                out = "[%s] %s %s" % (bar, nte, cte)
            else:
                out = colorfy("[{{%%%s %s}}] %s %s" %
                              (self.color, bar, nte, cte))
        else:
            # Progress bar only
            barSpan = self.span - 3
            nMarks = float(self.amount) / self.max * barSpan
            nMarksFull = int(nMarks)
            if nMarksFull < barSpan:
                partial = nMarks - nMarksFull
                lastMark = self.rotations[int(partial * len(self.rotations))]
            else:
                lastMark = ''
            bar = self.sym * nMarksFull
            bar = bar + lastMark
            bar = bar + (' ' * (barSpan - (nMarksFull + len(lastMark))))

            if self.color is None:
                out = "[%s] %s" % (bar, cte)
            else:
                out = colorfy("[{{%%%s %s}}] %s" % (self.color, bar, cte))

        return out
예제 #16
0
    'get_magnetic_field', 'compute_magnetic_declination',
    'compute_magnetic_inclination', 'get_tec_value',
    'get_ionospheric_pierce_point'
]

# Create the cache directory
try:
    _CACHE_DIR = FileCache(os.path.join(os.path.expanduser('~'), '.lsl',
                                        'ionospheric_cache'),
                           max_size=lambda: IONO_CONFIG.get('max_cache_size'))
except OSError:
    _CACHE_DIR = MemoryCache(
        max_size=lambda: IONO_CONFIG.get('max_cache_size'))
    warnings.warn(
        colorfy(
            "{{%yellow Cannot create or write to on-disk data cache, using in-memory data cache}}"
        ), RuntimeWarning)

# Create the on-line cache
_ONLINE_CACHE = {}

# Radius of the Earth in meters for the IGRF
_RADIUS_EARTH = 6371.2 * 1e3


def _load_igrf(filename):
    """
    Given a filename pointing to a list of IGRF coefficients, load in the 
    data and return a dictionary containing the raw coefficients.
    
    The dictionary keys are:
예제 #17
0
파일: sdfits.py 프로젝트: lwa-project/lsl
    def _write_singledish_hdu(self):
        """
        Define the SINGLE DISH table.
        """

        scanList = []
        dateList = []
        timeList = []
        intTimeList = []
        beamList = []
        mList = []
        rawList = []
        scanCount = 1
        for i, dataSet in enumerate(self.data):
            if dataSet.pol == self.stokes[0]:
                tempMList = {}
                for stokes in self.stokes:
                    tempMList[stokes] = {}

            beams = list(dataSet.dataDict.keys())
            beams.sort()
            for b in beams:
                specData = dataSet.dataDict[b]

                # Load the data into a matrix
                tempMList[dataSet.pol][b] = specData.ravel()

                if dataSet.pol == self.stokes[0]:
                    # Observation date and time
                    utc = astro.taimjd_to_utcjd(dataSet.obsTime)
                    date = astro.get_date(utc)
                    date.hours = 0
                    date.minutes = 0
                    date.seconds = 0
                    utc0 = date.to_jd()

                    scanList.append(scanCount)
                    dateList.append('%4i-%02i-%02i' %
                                    (date.years, date.months, date.days))
                    timeList.append((utc - utc0) * 24 * 3600)
                    intTimeList.append(dataSet.intTime)
                    beamList.append(b.id)
                    rawList.append(b)

            if dataSet.pol == self.stokes[-1]:
                for b in rawList:
                    matrix = numpy.zeros((self.nStokes, self.nChan),
                                         dtype=numpy.float32)
                    for p in range(self.nStokes):
                        try:
                            matrix[p, :] = tempMList[self.stokes[p]][b]
                        except KeyError:
                            warnings.warn(
                                colorfy(
                                    "{{%%yellow Key mis-match %s %s}}" %
                                    (str(b),
                                     str(tempMList[self.stokes[p]].keys()))),
                                RuntimeWarning)

                    mList.append(matrix.ravel())
                scanCount += 1
                rawList = []

        # Scan number
        c1 = astrofits.Column(name='SCAN',
                              format='1I',
                              array=numpy.array(scanList))
        ## Cycle
        #c2 = astrofits.Column(name='CYCLE', format='1J',
        #array=numpy.array([1,]*len(scanList)))
        # DATE-OBS
        c3 = astrofits.Column(name='DATE-OBS',
                              format='10A',
                              array=numpy.array(dateList))
        # Time elapsed since 0h
        c4 = astrofits.Column(name='TIME',
                              format='1D',
                              unit='s',
                              array=numpy.array(timeList))
        # Integration time (seconds)
        c5 = astrofits.Column(name='EXPOSURE',
                              format='1E',
                              unit='s',
                              array=numpy.array(intTimeList,
                                                dtype=numpy.float32))
        # Object name
        c6 = astrofits.Column(name='OBJECT',
                              format='16A',
                              array=numpy.array([
                                  'LWA_OBS',
                              ] * len(scanList)))
        # Object position (deg and deg)
        c7 = astrofits.Column(name='OBJ-RA',
                              format='1D',
                              unit='deg',
                              array=numpy.array([
                                  0.0,
                              ] * len(scanList)))
        c8 = astrofits.Column(name='OBJ-DEC',
                              format='1D',
                              unit='deg',
                              array=numpy.array([
                                  0.0,
                              ] * len(scanList)))
        # Rest frequency (Hz)
        c9 = astrofits.Column(name='RESTFRQ',
                              format='1D',
                              unit='Hz',
                              array=numpy.array([
                                  0.0,
                              ] * len(scanList)))
        # Observation mode
        c10 = astrofits.Column(name='OBSMODE',
                               format='16A',
                               array=numpy.array([
                                   self.mode,
                               ] * len(scanList)))
        # Beam (tuning)
        c11 = astrofits.Column(name='BEAM',
                               format='1I',
                               array=numpy.array(beamList))
        # IF
        c12 = astrofits.Column(name='IF',
                               format='1I',
                               array=numpy.array([
                                   self.freq[0].id,
                               ] * len(scanList)))
        # Frequency resolution (Hz)
        c13 = astrofits.Column(name='FREQRES',
                               format='1D',
                               unit='Hz',
                               array=numpy.array([
                                   self.freq[0].chWidth,
                               ] * len(scanList)))
        # Bandwidth of the system (Hz)
        c14 = astrofits.Column(name='BANDWID',
                               format='1D',
                               unit='Hz',
                               array=numpy.array([
                                   self.freq[0].totalBW,
                               ] * len(scanList)))
        # Frequency axis - 1
        c15 = astrofits.Column(name='CRPIX1',
                               format='1E',
                               array=numpy.array([
                                   self.refPix,
                               ] * len(scanList)))
        c16 = astrofits.Column(name='CRVAL1',
                               format='1D',
                               unit='Hz',
                               array=numpy.array([
                                   self.refVal,
                               ] * len(scanList)))
        c17 = astrofits.Column(name='CDELT1',
                               format='1D',
                               unit='Hz',
                               array=numpy.array([
                                   self.freq[0].chWidth,
                               ] * len(scanList)))
        c18 = astrofits.Column(name='CRVAL3',
                               format='1D',
                               unit='deg',
                               array=numpy.array([
                                   0.0,
                               ] * len(scanList)))
        # Dec. axis - 4
        c19 = astrofits.Column(name='CRVAL4',
                               format='1D',
                               unit='deg',
                               array=numpy.array([
                                   0.0,
                               ] * len(scanList)))
        ## Scan rate
        #c20 = astrofits.Column(name='SCANRATE', format='2E', unit='deg/s',
        #array=numpy.array([[0,0],]*len(scanList)))

        #
        # Calibration information (currently not implemented)
        #
        ## System temperature  *** UNKNOWN ***
        #c21 =  astrofits.Column(name='TSYS', format='2E', unit='K',
        #array=numpy.array([[self.tSys,self.tSys],]*len(scanList)))
        ## CALFCTR *** UNKNOWN ***
        #c22 =  astrofits.Column(name='CALFCTR', format='2E', unit='K',
        #array=numpy.array([[1,1],]*len(scanList)))

        # Data
        c23 = astrofits.Column(name='DATA',
                               format='%iE' % (self.nStokes * self.nChan),
                               unit='UNCALIB',
                               array=numpy.array(mList))

        #
        # Data masking table (currently not implemented)
        #
        # Flag table
        #c24 = astrofits.Column(name='FLAGGED', format='%iB' % (self.nStokes*self.nChan),
        #array=numpy.array([[0,]*self.nStokes*self.nChan for s in scanList]))

        #
        # Calibration information (currently not implemented)
        #
        ## TCAL *** UNKNOWN ***
        #c25 = astrofits.Column(name='TCAL', format='2E', unit='Jy',
        #array=numpy.array([[1,1] for s in scanList]))
        ## TCALTIME *** UNKNOWN ***
        #c26 = astrofits.Column(name='TCALTIME', format='16A',
        #array=numpy.array(['UNKNOWN',]*len(scanList)))

        #
        # Pointing information (currently not implemented)
        #
        ## Azimuth *** UNKNOWN ***
        #c27 = astrofits.Column(name='AZIMUTH', format='1E', unit='deg',
        #array=numpy.array([0,]*len(scanList)))
        ## Elevation *** UNKNOWN ***
        #c28 = astrofits.Column(name='ELEVATIO', format='1E', unit='deg',
        #array=numpy.array([0,]*len(scanList)))
        ## Parallactic angle *** UNKNOWN ***
        #c29 = astrofits.Column(name='PARANGLE', format='1E', unit='deg',
        #array=numpy.array([0,]*len(scanList)))

        #
        # Focusing information (currently not implemented and probably never will be)
        #
        ## FOCUSAXI *** NOT NEEDED ***
        #c30 = astrofits.Column(name='FOCUSAXI', format='1E', unit='m',
        #array=numpy.array([0,]*len(scanList)))
        ## FOCUSTAN *** NOT NEEDED ***
        #c31 = astrofits.Column(name='FOCUSTAN', format='1E', unit='m',
        #array=numpy.array([0,]*len(scanList)))
        ## FOCUSROT *** NOT NEEDED ***
        #c32 = astrofits.Column(name='FOCUSROT', format='1E', unit='deg',
        #array=numpy.array([0,]*len(scanList)))

        #
        # Weather information (currently not implemented)
        #
        ## Ambient temperature *** UNKNOWN ***
        #c33 = astrofits.Column(name='TAMBIENT', format='1E', unit='C',
        #array=numpy.array([0,]*len(scanList)))
        ## Air pressure *** UNKNOWN ***
        #c34 = astrofits.Column(name='PRESSURE', format='1E', unit='Pa',
        #array=numpy.array([0,]*len(scanList)))
        ## Humidity *** UNKNOWN ***
        #c35 = astrofits.Column(name='HUMIDITY', format='1E', unit='%',
        #array=numpy.array([0,]*len(scanList)))
        ## Wind speed *** UNKNOWN ***
        #c36 = astrofits.Column(name='WINDSPEE', format='1E', unit='m/s',
        #array=numpy.array([0,]*len(scanList)))
        ## Wind direction *** UNKNOWN ***
        #c37 = astrofits.Column(name='WINDDIRE', format='1E', unit='deg',
        #array=numpy.array([0,]*len(scanList)))

        # Gather together all of the needed columns and figure out which ones
        # store the data and flag tables.  This information is needed later to
        # set the appropriate TDIM keywords.
        cs = [
            c1, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16,
            c17, c18, c19, c23
        ]
        dataIndex = 0
        #flagIndex = 0
        for i, c in enumerate(cs):
            try:
                if c.name == 'DATA':
                    dataIndex = i + 1
                #if c.name == 'FLAGGED':
                #flagIndex = n
            except NameError:
                pass
        colDefs = astrofits.ColDefs(cs)

        # Create the SINGLE DISH table and update its header
        sd = astrofits.BinTableHDU.from_columns(colDefs)

        ## Single disk keywords - order seems to matter
        sd.header['EXTNAME'] = ('SINGLE DISH', 'SDFITS table name')
        sd.header['NMATRIX'] = 1
        sd.header['OBSERVER'] = (self.observer, 'Observer name(s)')
        sd.header['PROJID'] = (self.project, 'Project name')
        sd.header['TELESCOP'] = (self.site.name, 'Telescope name')
        x, y, z = self.site.geocentric_location
        sd.header['OBSGEO-X'] = (x, '[m] Antenna ECEF X-coordinate')
        sd.header['OBSGEO-Y'] = (y, '[m] Antenna ECEF Y-coordinate')
        sd.header['OBSGEO-Z'] = (z, '[m] Antenna ECEF Z-coordinate')

        sd.header['SPECSYS'] = ('LSRK',
                                'Doppler reference frame (transformed)')
        sd.header['SSYSOBS'] = ('TOPOCENT',
                                'Doppler reference frame of observation')
        sd.header['EQUINOX'] = (2000.0, 'Equinox of equatorial coordinates')
        sd.header['RADESYS'] = ('FK5', 'Equatorial coordinate system frame')

        ## Data and flag table dimensionality
        sd.header['TDIM%i' % dataIndex] = ('(%i,%i,1,1)' %
                                           (self.nChan, self.nStokes))
        #sd.header.set('TDIM%i' % flagIndex, '(%i,%i,1,1)' % (self.nChan, self.nStokes), after='TFORM%i' % flagIndex)

        ## Data and flag table axis descriptions
        ### Frequency
        sd.header['CTYPE1'] = ('FREQ', 'axis 1 is FREQ (frequency)')
        sd.header['CDELT1'] = self.freq[0].chWidth
        sd.header['CRPIX1'] = self.refPix
        sd.header['CRVAL1'] = self.refVal
        ### Stokes
        sd.header['CTYPE2'] = ('STOKES',
                               'axis 2 is STOKES axis (polarization)')
        if self.stokes[0] < 0:
            sd.header['CDELT2'] = -1.0
        else:
            sd.header['CDELT2'] = 1.0
        sd.header['CRPIX2'] = 1.0
        sd.header['CRVAL2'] = float(self.stokes[0])
        ### RA
        sd.header['CTYPE3'] = ('RA', 'axis 3 is RA axis (pointing)')
        sd.header['CRPIX3'] = 1.0
        sd.header['CDELT3'] = -1.0
        ### Dec
        sd.header['CTYPE4'] = ('DEC', 'axis 4 is Dec. axis (pointing)')
        sd.header['CRPIX4'] = 1.0
        sd.header['CDELT4'] = 1.0

        self.FITS.append(sd)
        self.FITS.flush()
예제 #18
0
파일: vdif.py 프로젝트: lwa-project/lsl
    def time(self):
        """
        Function to convert the time tag to seconds since the UNIX epoch as a 
        `lsl.reader.base.FrameTimestamp` instance.
        """

        # Get the reference epoch in the strange way that it is stored in VDIF
        # and convert it to a MJD
        epochDT = datetime(2000 + self.ref_epoch // 2,
                           (self.ref_epoch % 2) * 6 + 1, 1, 0, 0, 0, 0)
        epochMJD, epochMPM = datetime_to_mjdmpm(epochDT)
        epochMJD = epochMJD + epochMPM / 1000.0 / 86400.0

        # Get the frame MJD by adding the seconds_from_epoch value to the epoch
        frameMJD_i = epochMJD + self.seconds_from_epoch // 86400
        frameMJD_f = (self.seconds_from_epoch % 86400) / 86400.0
        frameMJD_s = 0.0

        if self.sample_rate == 0.0:
            # Try to get the sub-second time by parsing the extended user data
            try:
                ## Is there a sample rate to grab?
                eud = self.extended_user_data
                sample_rate = eud['sample_rate']
                sample_rate *= 1e6 if eud['sample_rate_units'] == 'MHz' else 1e3

                ## How many samples are in each frame?
                dataSize = self.frame_length * 8 - 32 + 16 * self.is_legacy  # 8-byte chunks -> bytes - full header + legacy offset
                samplesPerWord = 32 // self.bits_per_sample  # dimensionless
                nSamples = dataSize // 4 * samplesPerWord  # bytes -> words -> data samples
                nSamples = nSamples / self.nchan / (
                    2 if self.is_complex else 1
                )  # data samples -> time samples

                ## What is the frame rate?
                frameRate = sample_rate // nSamples

                frameMJD_s += 1.0 * self.frame_in_second / frameRate

            except KeyError:
                warnings.warn(
                    colorfy(
                        "{{%yellow Insufficient information to determine exact frame timestamp, time will be approximate"
                    ), RuntimeWarning)

        else:
            # Use what we already have been told
            ## How many samples are in each frame?
            dataSize = self.frame_length * 8 - 32 + 16 * self.is_legacy  # 8-byte chunks -> bytes - full header + legacy offset
            samplesPerWord = 32 // self.bits_per_sample  # dimensionless
            nSamples = dataSize // 4 * samplesPerWord  # bytes -> words -> samples
            nSamples = nSamples // self.nchan // (
                2 if self.is_complex else 1)  # data samples -> time samples

            ## What is the frame rate?
            frameRate = self.sample_rate // nSamples

            frameMJD_s += 1.0 * self.frame_in_second / frameRate

        # Convert from MJD to UNIX time
        if frameMJD_f > 1:
            frameMJD_i += 1
            frameMJD_f -= 1

        return FrameTimestamp.from_pulsar_mjd(frameMJD_i, frameMJD_f,
                                              frameMJD_s)