Example #1
0
def writeObject(obj, filename):
    '''Write Gyoto object (e.g. Scenery) to XML file'''
    core.Factory(obj).write(filename)
Example #2
0
def mk_video(scenery=None,
             func="orbiting_screen",
             orbit_trajectory=None,
             orbit_t0=0.,
             orbit_t1=1000.,
             static_t0=0.,
             static_t1=1000.,
             static_unit='geometrical',
             acceleration_maxvel=0.99,
             growth_factor_first=None,
             growth_factor_last=None,
             duration=10,
             fps=3,
             width=128,
             height=72,
             dangle1=None,
             dangle2=None,
             fov=None,
             verbose=0,
             debug=False,
             nthreads=8,
             output=None,
             backend=OpenCVVideoWriter,
             cmap=None,
             observerkind=None,
             plot=False,
             frame_first=0,
             frame_last=None):
    '''Make a video from a Gyoto Scenery

    Keyword arguments:

    scenery  -- the Scenery to animate, a string (XML file name),
                Gyoto.core.Scenery instance or None in which case a
                default Scenery is used
    func     -- a callable which will be called as func(scenery, k)
                where k is the frame number. func() is responsible to
                mutate the Scenery for each frame, for instance by
                moving the camera, changing its field-of view etc..
                func may also be a string, the name of one of the
                built-in callables: orbiting_screen (default),
                orbiting_screen_forward, static_screen,
                accelerating_tangential_screen or growing_mass. Those
                options take parameters below
    orbit_trajectory -- 
                only if func above starts with 'orbiting_screen', a
                gyoto.std.Star instance or a string (XML file name) or
                None (in which case a default trajectory is used)
                specifying the trajectory of the Screen.
    orbit_t0 -- only if func above starts with 'orbiting_screen',
                proper time along the trajectory at the beginning of
                the movie
    orbit_t1 -- only if func above starts with 'orbiting_screen',
                proper time along the trajectory at the end of the
                movie
    static_t0-- only if func above is 'static_screen', coordinate
                observing time offset at first frame
    static_t0-- only if func above is 'static_screen', coordinate
                observing time offset at last frame
    static_unit --
                only if func above is 'static_screen', unit in which
                static_t0 and static_t1 are expressed ('geometrical').
    acceleration_maxvel --
                only if func is 'accelerating_tangential_screen',
                maximum velocity of the observer, in terms of c
                (default: 0.99)
    growth_factor_first --
                only if func is 'growing_mass', scale factor for first
                frame.
    growth_factor_last --
                only if func is 'growing_mass', scale factor for last
                frame.
    duration -- duration pf the movie in seconds (default: 10.)
    fps      -- frames per second (default: 3)
    width    -- width of the movie in pixels (default: 128)
    height   -- height of the movie in pixels (default: 72)
    dangle1  -- rotate the camera dangle1 degrees horizontally
    dangle2  -- rotate the camera dangle2 degrees vertically
    fov      -- screen field-of-view
    verbose  -- verbosity level (default: 0)
    debug    -- debug mode (default: False)
    nthreads -- number of parallel threads to use (default: 8)
    output   -- output file name
    backend  -- class implementing VideoWriter
    observerkind --
                change observer kind (default: VelocitySpecified)
    plot     -- show each frame (default: False)

    '''

    # Set a few variables
    nframes = int(duration * fps)

    # Read or create Scenery
    if scenery is None:
        sc = defaultScenery()
    elif type(scenery) is core.Scenery:
        sc = scenery
    else:
        sc = core.Factory(scenery).scenery()
    screen = sc.screen()
    metric = sc.metric()

    # Select video type, init func callable
    if func == 'orbiting_screen':
        # Read or create trajectory
        if orbit_trajectory is None:
            traj = defaultTrajectory(screen)
        elif type(orbit_trajectory) is std.Star:
            traj = orbit_trajectory
        else:
            traj = std.Star(core.Factory(orbit_trajectory).astrobj())
            traj.metric(metric)
        screen.observerKind('VelocitySpecified')
        func = orbiting_screen(trajectory=traj, t0=orbit_t0, t1=orbit_t1)
    elif func == 'static_screen':
        func = static_screen(unit=static_unit, t0=static_t0, t1=static_t1)
    elif func == 'orbiting_screen_forward':
        # Read or create trajectory
        if orbit_trajectory is None:
            traj = defaultTrajectory(screen)
        elif type(orbit_trajectory) is std.Star:
            traj = orbit_trajectory
        else:
            traj = std.Star(core.Factory(orbit_trajectory).astrobj())
            traj.metric(metric)
        screen.observerKind('FullySpecified')
        func = orbiting_screen_forward(trajectory=traj,
                                       t0=orbit_t0,
                                       t1=orbit_t1)
    elif func == 'accelerating_tangential_screen':
        screen.observerKind('VelocitySpecified')
        screen.dangle1(-45, 'degree')
        screen.fieldOfView(90, 'degree')
        func = accelerating_tangential_screen(maxvel=acceleration_maxvel)
    elif func == 'growing_mass':
        func = growing_mass(sc)
        if growth_factor_first is not None:
            func.factor_first = growth_factor_first
        if growth_factor_last is not None:
            func.factor_last = growth_factor_last
    # else assume func is a callable

    # Override some values set on command-line
    if (observerkind is not None):
        screen.observerKind(observerkind)
    if dangle1 is not None:
        screen.dangle1(dangle1, 'degree')
    if dangle2 is not None:
        screen.dangle2(dangle2, 'degree')
    if fov is not None:
        screen.fieldOfView(fov, 'degree')

    # Prepare for ray-tracing
    nframes = int(duration * fps)
    screen.resolution(max(height, width))
    core.verbose(verbose)
    core.debug(debug)
    sc.nThreads(nthreads)

    # Open video
    if backend == 'OpenCV':
        backend = OpenCVVideoWriter
    elif backend == 'PyAV':
        backend = PyAVVideoWriter
    elif backend is None or backend == 'Null':
        backend = NullVideoWriter

    if type(output) == str or backend is NullVideoWriter:
        video = backend(output, fps, width, height)
    elif isinstance(output, VideoWriter):
        video = output
    else:
        raise ValueError('output needs to be a string or VideoWriter')
    if type(cmap) == str:
        video.cmap = plt.cm.get_cmap(cmap)
    elif cmap is not None:
        video.cmap = cmap

    # Loop on frame number
    if frame_last is None:
        frame_last = nframes - 1
    for k in range(frame_first, frame_last + 1):
        print(k, "/", nframes)
        intensity = rayTraceFrame(sc, func, k, nframes, width, height)
        frame = video.colorize(intensity)
        if plot:
            plt.imshow(frame, origin='lower')
            plt.show()
        video.write(frame)

    # Close video
    del video
Example #3
0
def readScenery(filename):
    '''Read Scenery from XML file'''
    return core.Factory(filename).scenery()
Example #4
0
def rayTrace(sc,
             j=None,
             i=None,
             coord2dset=core.Grid,
             prefix='\r j = ',
             height=None,
             width=None):
    '''Ray-trace scenery

First form:

results=scenery.rayTrace([j, i, [coord2dset [,prefix]]])

optional parameters:
j       -- vertical specification of the part of the field to trace
           (see gyoto.util.Coord1dSet)
i       -- horizontal specification of the part of the field to trace
           (see gyoto.util.Coord1dSet)
coord2dset -- a Coord2dSet subclass. Default: gyoto.core.Grid. The other
           value that makes sense is gyoto.core.Bucket.
prefix  -- prefix to be written in front of the row number for
           progress output
height, width -- vertical and horizontal resolution (overrides what
           is specified in scenery.screen().resolution()

Output:
results -- dict containing the various requested quantities as per
           scenery.requestedQuantitiesString().

CAVEAT:
This high level-wrapper is Pythonic and take the arguments as j, i,
0-based indices whereas most Gyoto functions take them as i, j,
1-based indices.

TODO:
Support impactcoords.

Second form:

    '''
    if isinstance(i, core.AstrobjProperties):
        ij = j
        aop = i
        if not isinstance(coord2dset, type):
            ipct = coord2dset
        else:
            ipct = None
        core._core.Scenery_rayTrace(sc, ij, aop, ipct)
        return

    # If needed, read sc
    if type(sc) is str:
        sc = core.Factory(sc).scenery()

    # Determine resolution, width and height
    res = sc.screen().resolution()
    if width is not None:
        res = width
    else:
        width = res
    if height is not None and height > width:
        res = height
    else:
        height = res
    sc.screen().resolution(res)

    # Prepare coord2dset
    scalars = int(numpy.isscalar(i)) + int(numpy.isscalar(j))
    nx = None
    if isinstance(coord2dset, type):
        if not issubclass(coord2dset, core.Coord2dSet):
            raise TypeError(
                "when coord2dset is a type, it must be a subclass of gyoto.core.Coord2dSet"
            )
        if not isinstance(i, core.Coord1dSet):
            i = Coord1dSet(i, res, width)
        if not isinstance(j, core.Coord1dSet):
            j = Coord1dSet(j, res, height)
        try:
            coord2dset = coord2dset(i, j, prefix)
        except TypeError:
            coord2dset = coord2dset(i, j)
        nx = i.size()
        ntot = coord2dset.size()
        ny = ntot // nx
    elif isinstance(coord2dset, core.Coord2dSet):
        nx = ntot = coord2dset.size()
        ny = 1
    else:
        raise TypeError(
            'coord2dset must be a gyoto.core.Coord2dSet subclass or instance')

    if isinstance(coord2dset, core.Grid) and scalars is 0:
        dims = (ny, nx)
        array_double_fromnumpy1or2 = core.array_double_fromnumpy2
        array_double_fromnumpy2or3 = core.array_double_fromnumpy3
    else:
        dims = (ntot, )
        array_double_fromnumpy1or2 = core.array_double_fromnumpy1
        array_double_fromnumpy2or3 = core.array_double_fromnumpy2

    # Prepare arrays to store results
    res = dict()
    aop = core.AstrobjProperties()
    aop.offset = ntot

    if sc.getSpectralQuantitiesCount():
        nsamples = sc.screen().spectrometer().nSamples()

    if 'Intensity' in sc.requestedQuantitiesString():
        intensity = numpy.zeros(dims)
        pintensity = array_double_fromnumpy1or2(intensity)
        aop.intensity = pintensity
        res['Intensity'] = intensity

    if 'EmissionTime' in sc.requestedQuantitiesString():
        time = numpy.zeros(dims)
        ptime = array_double_fromnumpy1or2(time)
        aop.time = ptime
        res['EmissionTime'] = time

    if 'MinDistance' in sc.requestedQuantitiesString():
        distance = numpy.zeros(dims)
        pdistance = array_double_fromnumpy1or2(distance)
        aop.distance = pdistance
        res['MinDistance'] = distance

    if 'FirstDistMin' in sc.requestedQuantitiesString():
        first_dmin = numpy.zeros(dims)
        pfirst_dmin = array_double_fromnumpy1or2(first_dmin)
        aop.first_dmin = pfirst_dmin
        res['FirstDistMin'] = first_dmin

    if 'Redshift' in sc.requestedQuantitiesString():
        redshift = numpy.zeros(dims)
        predshift = array_double_fromnumpy1or2(redshift)
        aop.redshift = predshift
        res['Redshift'] = redshift

    if 'NbCrossEqPlane' in sc.requestedQuantitiesString():
        nbcrosseqplane = numpy.zeros(dims)
        pnbcrosseqplane = array_double_fromnumpy1or2(nbcrosseqplane)
        aop.nbcrosseqplane = pnbcrosseqplane
        res['NbCrossEqPlane'] = nbcrosseqplane

    if 'ImpactCoords' in sc.requestedQuantitiesString():
        impactcoords = numpy.zeros(dims + (16, ))
        pimpactcoords = array_double_fromnumpy2or3(impactcoords)
        aop.impactcoords = pimpactcoords
        res['ImpactCoords'] = impactcoords

    if 'User1' in sc.requestedQuantitiesString():
        user1 = numpy.zeros(dims)
        puser1 = array_double_fromnumpy1or2(user1)
        aop.user1 = puser1
        res['User1'] = user1

    if 'User1' in sc.requestedQuantitiesString():
        impactcoords = numpy.zeros(dims)
        pimpactcoords = array_double_fromnumpy1or2(impactcoords)
        aop.impactcoords = pimpactcoords
        res['User1'] = impactcoords

    if 'User2' in sc.requestedQuantitiesString():
        user2 = numpy.zeros(dims)
        puser2 = array_double_fromnumpy1or2(user2)
        aop.user2 = puser2
        res['User2'] = user2

    if 'User3' in sc.requestedQuantitiesString():
        user3 = numpy.zeros(dims)
        puser3 = array_double_fromnumpy1or2(user3)
        aop.user3 = puser3
        res['User3'] = user3

    if 'User4' in sc.requestedQuantitiesString():
        user4 = numpy.zeros(dims)
        puser4 = array_double_fromnumpy1or2(user4)
        aop.user4 = puser4
        res['User4'] = user4

    if 'User5' in sc.requestedQuantitiesString():
        user5 = numpy.zeros(dims)
        puser5 = array_double_fromnumpy1or2(user5)
        aop.user5 = puser5
        res['User5'] = user5

    if 'Spectrum' in sc.requestedQuantitiesString():
        spectrum = numpy.zeros((nsamples, ) + dims)
        pspectrum = array_double_fromnumpy2or3(spectrum)
        aop.spectrum = pspectrum
        res['Spectrum'] = spectrum

    if 'SpectrumStokesQ' in sc.requestedQuantitiesString():
        stokesQ = numpy.zeros((nsamples, ) + dims)
        pstokesQ = array_double_fromnumpy2or3(stokesQ)
        aop.stokesQ = pstokesQ
        res['SpectrumStokesQ'] = stokesQ

    if 'SpectrumStokesU' in sc.requestedQuantitiesString():
        stokesU = numpy.zeros((nsamples, ) + dims)
        pstokesU = array_double_fromnumpy2or3(stokesU)
        aop.stokesU = pstokesU
        res['SpectrumStokesU'] = stokesU

    if 'SpectrumStokesV' in sc.requestedQuantitiesString():
        stokesV = numpy.zeros((nsamples, ) + dims)
        pstokesV = array_double_fromnumpy2or3(stokesV)
        aop.stokesV = pstokesV
        res['SpectrumStokesV'] = stokesV

    if 'BinSpectrum' in sc.requestedQuantitiesString():
        binspectrum = numpy.zeros((nsamples, ) + dims)
        pbinspectrum = array_double_fromnumpy2or3(binspectrum)
        aop.binspectrum = pbinspectrum
        res['BinSpectrum'] = binspectrum

    # Perform the actual ray-tracing
    sc.rayTrace(coord2dset, aop)

    if scalars is 2:
        for key in res:
            res[key] = res[key][0]

    return res