def writeObject(obj, filename): '''Write Gyoto object (e.g. Scenery) to XML file''' core.Factory(obj).write(filename)
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
def readScenery(filename): '''Read Scenery from XML file''' return core.Factory(filename).scenery()
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