def breaches_records_to_pdf(breaches_records, pdf_path=None, figure_width=10, logger="bar"): """Plots figures of the breaches annotated in the records into a PDF file. Parameters ---------- breaches_records A least of records annotated with breaches, as returned by the pdf_path Either the path to a PDF, or a file handle (open in wb mode) or None for this method to return binary PDF data. logger Either "bar" for a progress bar, None for no logging, or any Proglog logger. The bar name is "sequence". """ pdf_io = BytesIO() if pdf_path is None else pdf_path logger = proglog.default_bar_logger(logger, min_time_interval=0.2) with PdfPages(pdf_io) as pdf: for record in logger.iter_bar(sequence=breaches_records): ax = plot_breaches_record(record, figure_width=figure_width) pdf.savefig(ax.figure, bbox_inches="tight") plt.close(ax.figure) if pdf_path is None: return pdf_io.getvalue()
def subprocess_call(cmd, logger="bar", errorprint=True): """ Executes the given subprocess command. Set logger to None or a custom Proglog logger to avoid printings. """ logger = proglog.default_bar_logger(logger) logger(message='Moviepy - Running:\n>>> "+ " ".join(cmd)') popen_params = {"stdout": sp.DEVNULL, "stderr": sp.PIPE, "stdin": sp.DEVNULL} if os.name == "nt": popen_params["creationflags"] = 0x08000000 proc = sp.Popen(cmd, **popen_params) out, err = proc.communicate() # proc.wait() proc.stderr.close() if proc.returncode: if errorprint: logger(message="Moviepy - Command returned an error") raise IOError(err.decode("utf8")) else: logger(message="Moviepy - Command successful") del proc
def ffmpeg_audiowrite(clip, filename, fps, nbytes, buffersize, codec='libvorbis', bitrate=None, write_logfile=False, verbose=True, ffmpeg_params=None, logger='bar'): """ A function that wraps the FFMPEG_AudioWriter to write an AudioClip to a file. NOTE: verbose is deprecated. """ if write_logfile: logfile = open(filename + ".log", 'w+') else: logfile = None logger = proglog.default_bar_logger(logger) logger(message="MoviePy - Writing audio in %s" % filename) writer = FFMPEG_AudioWriter(filename, fps, nbytes, clip.nchannels, codec=codec, bitrate=bitrate, logfile=logfile, ffmpeg_params=ffmpeg_params) for chunk in clip.iter_chunks(chunksize=buffersize, quantize=True, nbytes=nbytes, fps=fps, logger=logger): writer.write_frames(chunk) writer.close() if write_logfile: logfile.close() logger(message="MoviePy - Done.")
def subprocess_call(cmd, logger='bar', errorprint=True): """ Executes the given subprocess command. Set logger to None or a custom Proglog logger to avoid printings. """ logger = proglog.default_bar_logger(logger) logger(message='Moviepy - Running:\n>>> "+ " ".join(cmd)') popen_params = {"stdout": DEVNULL, "stderr": sp.PIPE, "stdin": DEVNULL} if os.name == "nt": popen_params["creationflags"] = 0x08000000 proc = sp.Popen(cmd, **popen_params) out, err = proc.communicate() # proc.wait() proc.stderr.close() if proc.returncode: if errorprint: logger(message='Moviepy - Command returned an error') raise IOError(err.decode('utf8')) else: logger(message='Moviepy - Command successful') del proc
def __init__( self, sequence, constraints=None, objectives=None, logger="bar", mutation_space=None, ): """Initialize""" if isinstance(sequence, SeqRecord): self.record = sequence self.sequence = str(sequence.seq).upper() else: self.record = None self.sequence = sequence.upper() self.constraints = [] if constraints is None else list(constraints) self.objectives = [] if objectives is None else list(objectives) self.logger = default_bar_logger( logger, bars=("objective", "constraint", "location"), ignored_bars=("mutation", ), min_time_interval=0.2, ) self.mutation_space = mutation_space self.initialize()
def iter_frames(self, fps=None, with_times=False, logger=None, dtype=None): """ Iterates over all the frames of the clip. Returns each frame of the clip as a HxWxN np.array, where N=1 for mask clips and N=3 for RGB clips. This function is not really meant for video editing. It provides an easy way to do frame-by-frame treatment of a video, for fields like science, computer vision... The ``fps`` (frames per second) parameter is optional if the clip already has a ``fps`` attribute. Use dtype="uint8" when using the pictures to write video, images... Examples --------- >>> # prints the maximum of red that is contained >>> # on the first line of each frame of the clip. >>> from moviepy.editor import VideoFileClip >>> myclip = VideoFileClip('myvideo.mp4') >>> print ( [frame[0,:,0].max() for frame in myclip.iter_frames()]) """ logger = proglog.default_bar_logger(logger) for t in logger.iter_bar(t=np.arange(0, self.duration, 1.0 / fps)): frame = self.get_frame(t) if (dtype is not None) and (frame.dtype != dtype): frame = frame.astype(dtype) if with_times: yield t, frame else: yield frame
def iter_frames(self, fps=None, with_times = False, logger=None, dtype=None): """ Iterates over all the frames of the clip. Returns each frame of the clip as a HxWxN np.array, where N=1 for mask clips and N=3 for RGB clips. This function is not really meant for video editing. It provides an easy way to do frame-by-frame treatment of a video, for fields like science, computer vision... The ``fps`` (frames per second) parameter is optional if the clip already has a ``fps`` attribute. Use dtype="uint8" when using the pictures to write video, images... Examples --------- >>> # prints the maximum of red that is contained >>> # on the first line of each frame of the clip. >>> from moviepy.editor import VideoFileClip >>> myclip = VideoFileClip('myvideo.mp4') >>> print ( [frame[0,:,0].max() for frame in myclip.iter_frames()]) """ logger = proglog.default_bar_logger(logger) for t in logger.iter_bar(t=np.arange(0, self.duration, 1.0/fps)): frame = self.get_frame(t) if (dtype is not None) and (frame.dtype != dtype): frame = frame.astype(dtype) if with_times: yield t, frame else: yield frame
def ffmpeg_audiowrite(clip, filename, fps, nbytes, buffersize, codec='libvorbis', bitrate=None, write_logfile=False, verbose=True, ffmpeg_params=None, logger='bar'): """ A function that wraps the FFMPEG_AudioWriter to write an AudioClip to a file. NOTE: verbose is deprecated. """ if write_logfile: logfile = open(filename + ".log", 'w+') else: logfile = None logger = proglog.default_bar_logger(logger) logger(message="MoviePy - Writing audio in %s") writer = FFMPEG_AudioWriter(filename, fps, nbytes, clip.nchannels, codec=codec, bitrate=bitrate, logfile=logfile, ffmpeg_params=ffmpeg_params) for chunk in clip.iter_chunks(chunksize=buffersize, quantize=True, nbytes=nbytes, fps=fps, logger=logger): writer.write_frames(chunk) writer.close() if write_logfile: logfile.close() logger(message="MoviePy - Done.")
def subprocess_call(cmd, logger="bar"): """Executes the given subprocess command. Set logger to None or a custom Proglog logger to avoid printings. """ logger = proglog.default_bar_logger(logger) logger(message="Moviepy - Running:\n>>> " + " ".join(cmd)) popen_params = cross_platform_popen_params({ "stdout": sp.DEVNULL, "stderr": sp.PIPE, "stdin": sp.DEVNULL }) proc = sp.Popen(cmd, **popen_params) out, err = proc.communicate() # proc.wait() proc.stderr.close() if proc.returncode: logger(message="Moviepy - Command returned an error") raise IOError(err.decode("utf8")) else: logger(message="Moviepy - Command successful") del proc
def iter_chunks( self, chunksize=None, chunk_duration=None, fps=None, quantize=False, nbytes=2, logger=None, ): """Iterator that returns the whole sound array of the clip by chunks""" if fps is None: fps = self.fps logger = proglog.default_bar_logger(logger) if chunk_duration is not None: chunksize = int(chunk_duration * fps) total_size = int(fps * self.duration) nchunks = total_size // chunksize + 1 positions = np.linspace(0, total_size, nchunks + 1, endpoint=True, dtype=int) for i in logger.iter_bar(chunk=list(range(nchunks))): size = positions[i + 1] - positions[i] assert size <= chunksize timings = (1.0 / fps) * np.arange(positions[i], positions[i + 1]) yield self.to_soundarray( timings, nbytes=nbytes, quantize=quantize, fps=fps, buffersize=chunksize )
def write_gif_with_image_io(clip, filename, fps=None, opt=0, loop=0, colors=None, logger="bar"): """Writes the gif with the Python library ImageIO (calls FreeImage).""" if colors is None: colors = 256 logger = proglog.default_bar_logger(logger) if not IMAGEIO_FOUND: raise ImportError( "Writing a gif with imageio requires ImageIO installed," " with e.g. 'pip install imageio'") if fps is None: fps = clip.fps quantizer = 0 if opt != 0 else "nq" writer = imageio.save(filename, duration=1.0 / fps, quantizer=quantizer, palettesize=colors, loop=loop) logger(message="MoviePy - Building file %s with imageio." % filename) for frame in clip.iter_frames(fps=fps, logger=logger, dtype="uint8"): writer.append_data(frame)
def write_images_sequence(self, nameformat, fps=None, verbose=True, withmask=True, logger='bar'): """ Writes the videoclip to a sequence of image files. Parameters ----------- nameformat A filename specifying the numerotation format and extension of the pictures. For instance "frame%03d.png" for filenames indexed with 3 digits and PNG format. Also possible: "some_folder/frame%04d.jpeg", etc. fps Number of frames per second to consider when writing the clip. If not specified, the clip's ``fps`` attribute will be used if it has one. withmask will save the clip's mask (if any) as an alpha canal (PNGs only). verbose Boolean indicating whether to print information. logger Either 'bar' (progress bar) or None or any Proglog logger. Returns -------- names_list A list of all the files generated. Notes ------ The resulting image sequence can be read using e.g. the class ``ImageSequenceClip``. """ logger = proglog.default_bar_logger(logger) logger(message='Moviepy - Writing frames %s.' % nameformat) tt = np.arange(0, self.duration, 1.0 / fps) filenames = [] total = int(self.duration / fps) + 1 for i, t in logger.iter_bar(t=list(enumerate(tt))): name = nameformat % i filenames.append(name) self.save_frame(name, t, withmask=withmask) logger(message='Moviepy - Done writing frames %s.' % nameformat) return filenames
def __init__(self, config, cache=None, logger="bar", verbose=False): """Initializes an instance and a connection to an ICE instance. Examples -------- >>> config = dict(root="https://ice.genomefoundry.org", >>> token="WHz+BC+7eFV=...", >>> client="icebot") >>> ice = icebreaker.IceClient(config) >>> # Alternative config via a yaml file: >>> ice = icebreaker.IceClient(config="config.yaml") Parameters ---------- config Authentication configuration of the ICE instance. Should be either a dictionnary or a yaml file representing a dictionnary (cf. documentation). The dictionnary should be of the form ``{root: email: password:}`` where root is the root address of your online ICE instance, or ``{root: token: client:}`` to authenticate with a client name and API token (a.k.a API key). cache Option to cache the ICE requests, which will greatly improve the speed of many scripts. Set to None for no caching, "memory" for in-RAM caching, and either "sqlite", "mongodb", "redis" for persistent caching in a database. See https://requests-cache.readthedocs.io for more. Beware that caching means updates to the database may be ignored, use with care. logger Either None for no logging, 'bar' for progress bar logging (useful in notebooks), or a custom Proglog logging object. """ if isinstance(config, str): with open(config, "r") as f: config = next(yaml.load_all(f.read())) self.verbose = verbose self.root = config["root"].strip("/") self.logger = proglog.default_bar_logger(logger) self.logger.ignore_bars_under = 2 if cache is not None: self.session = requests_cache.CachedSession(backend=cache) else: self.session = requests.Session() self.session.headers = headers = {} self.session_infos = {} if "session_id" in config: headers["X-ICE-Authentication-SessionId"] = config["session_id"] self.session_infos.update(config.get("session_infos", {})) if "client" in config: self.set_api_token(config["client"], config["token"]) elif "password" in config: self.get_new_session_id(config["email"], config["password"]) self.ice_version = self._get_ice_version()
def __init__( self, sequence_length, segment_score_function, cut_location_constraints=(), segment_constraints=(), forced_cuts=(), suggested_cuts=(), cuts_set_constraints=(), cut_spread_radius=0, min_segment_length=0, max_segment_length=None, coarse_grain=1, fine_grain=1, a_star_factor=0, path_size_limit=None, path_size_min_step=0.001, logger=None, bar_prefix="", ): self.segment_score_function = segment_score_function self.forced_cuts = set(list(forced_cuts) + [0, sequence_length]) self.suggested_cuts = set(suggested_cuts) self.cut_spread_radius = cut_spread_radius self.segments_constraints = list(segment_constraints) self.cuts_set_constraints = list(cuts_set_constraints) self.cut_location_constraints = list(cut_location_constraints) self.sequence_length = sequence_length if max_segment_length is None: self.max_segment_length = sequence_length else: self.max_segment_length = max_segment_length self.min_segment_length = min_segment_length self.coarse_grain = coarse_grain self.fine_grain = fine_grain self.a_star_factor = a_star_factor self.path_size_limit = path_size_limit self.path_size_min_step = path_size_min_step self.logger = default_bar_logger(logger, min_time_interval=0.2) self.bar_prefix = bar_prefix if len(forced_cuts) > 0: def forced_cuts_filter(segment): start, end = segment return not any((start < cut < end) for cut in forced_cuts) self.segments_constraints.append(forced_cuts_filter) if len(self.cut_location_constraints) == 0: self.valid_cuts = set(range(sequence_length + 1)) else: self.valid_cuts = set([ index for index in range(sequence_length + 1) if all( fl(index) for fl in self.cut_location_constraints) ])
def write_images_sequence(self, name_format, fps=None, with_mask=True, logger="bar"): """Writes the videoclip to a sequence of image files. Parameters ---------- name_format A filename specifying the numerotation format and extension of the pictures. For instance "frame%03d.png" for filenames indexed with 3 digits and PNG format. Also possible: "some_folder/frame%04d.jpeg", etc. fps Number of frames per second to consider when writing the clip. If not specified, the clip's ``fps`` attribute will be used if it has one. with_mask will save the clip's mask (if any) as an alpha canal (PNGs only). logger Either ``"bar"`` for progress bar or ``None`` or any Proglog logger. Returns ------- names_list A list of all the files generated. Notes ----- The resulting image sequence can be read using e.g. the class ``ImageSequenceClip``. """ logger = proglog.default_bar_logger(logger) # Fails on GitHub macos CI # logger(message="Moviepy - Writing frames %s." % name_format) timings = np.arange(0, self.duration, 1.0 / fps) filenames = [] for i, t in logger.iter_bar(t=list(enumerate(timings))): name = name_format % i filenames.append(name) self.save_frame(name, t, with_mask=with_mask) # logger(message="Moviepy - Done writing frames %s." % name_format) return filenames
def iter_frames(self, fps=None, with_times=False, logger=None, dtype=None): """Iterates over all the frames of the clip. Returns each frame of the clip as a HxWxN Numpy array, where N=1 for mask clips and N=3 for RGB clips. This function is not really meant for video editing. It provides an easy way to do frame-by-frame treatment of a video, for fields like science, computer vision... Parameters ---------- fps : int, optional Frames per second for clip iteration. Is optional if the clip already has a ``fps`` attribute. with_times : bool, optional Ff ``True`` yield tuples of ``(t, frame)`` where ``t`` is the current time for the frame, otherwise only a ``frame`` object. logger : str, optional Either ``"bar"`` for progress bar or ``None`` or any Proglog logger. dtype : type, optional Type to cast Numpy array frames. Use ``dtype="uint8"`` when using the pictures to write video, images... Examples -------- >>> # prints the maximum of red that is contained >>> # on the first line of each frame of the clip. >>> from moviepy import VideoFileClip >>> myclip = VideoFileClip('myvideo.mp4') >>> print ( [frame[0,:,0].max() for frame in myclip.iter_frames()]) """ logger = proglog.default_bar_logger(logger) for frame_index in logger.iter_bar( frame_index=np.arange(0, int(self.duration * fps)) ): # int is used to ensure that floating point errors are rounded # down to the nearest integer t = frame_index / fps frame = self.get_frame(t) if (dtype is not None) and (frame.dtype != dtype): frame = frame.astype(dtype) if with_times: yield t, frame else: yield frame
def __init__(self, assemblies, name="plan", logger="bar"): """Class to represent, analyze and simulate assembly plans Parameters ---------- assemblies List of Assembly instances. name Assembly plan name as it will appear in reports. logger Either "bar" for a progress bar, or None, or any Proglog logger. """ self.assemblies = assemblies self._raise_an_error_if_duplicate_assembly_names() self.assemblies_dict = {a.name: a for a in self.assemblies} self._compute_assemblies_levels() self.logger = default_bar_logger(logger) self.name = name
def iter_chunks(self, chunksize=None, chunk_duration=None, fps=None, quantize=False, nbytes=2, logger=None): """ Iterator that returns the whole sound array of the clip by chunks """ if fps is None: fps = self.fps logger = proglog.default_bar_logger(logger) if chunk_duration is not None: chunksize = int(chunk_duration*fps) totalsize = int(fps*self.duration) nchunks = totalsize // chunksize + 1 pospos = np.linspace(0, totalsize, nchunks + 1, endpoint=True, dtype=int) for i in logger.iter_bar(chunk=list(range(nchunks))): size = pospos[i+1] - pospos[i] assert(size <= chunksize) tt = (1.0/fps)*np.arange(pospos[i], pospos[i+1]) yield self.to_soundarray(tt, nbytes=nbytes, quantize=quantize, fps=fps, buffersize=chunksize)
def write_gif_with_image_io(clip, filename, fps=None, opt=0, loop=0, colors=None, verbose=True, logger='bar'): """ Writes the gif with the Python library ImageIO (calls FreeImage). Parameters ----------- opt """ if colors is None: colors = 256 logger = proglog.default_bar_logger(logger) if not IMAGEIO_FOUND: error = ImportError("Writing a gif with imageio requires ImageIO installed," " with e.g. 'pip install imageio'") logger.error(error) raise error if fps is None: fps = clip.fps quantizer = 0 if opt != 0 else 'nq' writer = imageio.save( filename, duration=1.0/fps, quantizer=quantizer, palettesize=colors, loop=loop ) logger.info(msg='MoviePy - Building file %s with imageio.' % filename) for frame in clip.iter_frames(fps=fps, logger=logger, dtype='uint8'): writer.append_data(frame)
def write_gif_with_image_io(clip, filename, fps=None, opt=0, loop=0, colors=None, verbose=True, logger='bar'): """ Writes the gif with the Python library ImageIO (calls FreeImage). Parameters ----------- opt """ if colors is None: colors = 256 logger = proglog.default_bar_logger(logger) if not IMAGEIO_FOUND: raise ImportError("Writing a gif with imageio requires ImageIO installed," " with e.g. 'pip install imageio'") if fps is None: fps = clip.fps quantizer = 0 if opt != 0 else 'nq' writer = imageio.save( filename, duration=1.0/fps, quantizer=quantizer, palettesize=colors, loop=loop ) logger(message='MoviePy - Building file %s with imageio.' % filename) for frame in clip.iter_frames(fps=fps, logger=logger, dtype='uint8'): writer.append_data(frame)
def write_gif_with_tempfiles( clip, filename, fps=None, program="ImageMagick", opt="OptimizeTransparency", fuzz=1, loop=0, dispose=True, colors=None, logger="bar", pix_fmt=None, ): """Write the VideoClip to a GIF file. Converts a VideoClip into an animated GIF using ImageMagick or ffmpeg. Does the same as write_gif (see this one for more docstring), but writes every frame to a file instead of passing them in the RAM. Useful on computers with little RAM. """ logger = proglog.default_bar_logger(logger) fileName, ext = os.path.splitext(filename) tt = np.arange(0, clip.duration, 1.0 / fps) tempfiles = [] logger(message="MoviePy - Building file %s\n" % filename) logger(message="MoviePy - - Generating GIF frames") for i, t in logger.iter_bar(t=list(enumerate(tt))): name = "%s_GIFTEMP%04d.png" % (fileName, i + 1) tempfiles.append(name) clip.save_frame(name, t, withmask=True) delay = int(100.0 / fps) if clip.mask is None: withmask = False if program == "ImageMagick": if not pix_fmt: pix_fmt = "RGBA" if withmask else "RGB" logger(message="MoviePy - - Optimizing GIF with ImageMagick...") cmd = ([ IMAGEMAGICK_BINARY, "-delay", "%d" % delay, "-dispose", "%d" % (2 if dispose else 1), "-loop", "%d" % loop, "%s_GIFTEMP*.png" % fileName, "-coalesce", "-fuzz", "%02d" % fuzz + "%", "-layers", "%s" % opt, "-set", "colorspace", pix_fmt, ] + (["-colors", "%d" % colors] if colors is not None else []) + [filename]) elif program == "ffmpeg": if not pix_fmt: pix_fmt = "rgba" if withmask else "rgb24" cmd = [ FFMPEG_BINARY, "-y", "-f", "image2", "-r", str(fps), "-i", fileName + "_GIFTEMP%04d.png", "-r", str(fps), filename, "-pix_fmt", (pix_fmt), ] try: subprocess_call(cmd, logger=logger) logger(message="MoviePy - GIF ready: %s." % filename) except (IOError, OSError) as err: error = ("MoviePy Error: creation of %s failed because " "of the following error:\n\n%s.\n\n." % (filename, str(err))) if program == "ImageMagick": error += ( "This error can be due to the fact that " "ImageMagick is not installed on your computer, or " "(for Windows users) that you didn't specify the " "path to the ImageMagick binary. Check the documentation.") raise IOError(error) for f in tempfiles: os.remove(f)
def write_gif( clip, filename, fps=None, program="ImageMagick", opt="OptimizeTransparency", fuzz=1, withmask=True, loop=0, dispose=True, colors=None, logger="bar", pix_fmt=None, ): """Write the VideoClip to a GIF file, without temporary files. Converts a VideoClip into an animated GIF using ImageMagick or ffmpeg. Parameters ----------- filename Name of the resulting gif file. fps Number of frames per second (see note below). If it isn't provided, then the function will look for the clip's ``fps`` attribute (VideoFileClip, for instance, have one). program Software to use for the conversion, either 'ImageMagick' or 'ffmpeg'. opt (ImageMagick only) optimalization to apply, either 'optimizeplus' or 'OptimizeTransparency'. fuzz (ImageMagick only) Compresses the GIF by considering that the colors that are less than fuzz% different are in fact the same. pix_fmt Pixel format for the output gif file. If is not specified 'rgb24' will be used as the default format unless ``clip.mask`` exist, then 'rgba' will be used. This option is going to be ignored if ``program=ImageMagick``. Notes ----- The gif will be playing the clip in real time (you can only change the frame rate). If you want the gif to be played slower than the clip you will use :: >>> # slow down clip 50% and make it a gif >>> myClip.speedx(0.5).write_gif('myClip.gif') """ # # We use processes chained with pipes. # # if program == 'ffmpeg' # frames --ffmpeg--> gif # # if program == 'ImageMagick' and optimize == (None, False) # frames --ffmpeg--> bmp frames --ImageMagick--> gif # # # if program == 'ImageMagick' and optimize != (None, False) # frames -ffmpeg-> bmp frames -ImagMag-> gif -ImagMag-> better gif # delay = 100.0 / fps logger = proglog.default_bar_logger(logger) if clip.mask is None: withmask = False if not pix_fmt: pix_fmt = "rgba" if withmask else "rgb24" cmd1 = [ FFMPEG_BINARY, "-y", "-loglevel", "error", "-f", "rawvideo", "-vcodec", "rawvideo", "-r", "%.02f" % fps, "-s", "%dx%d" % (clip.w, clip.h), "-pix_fmt", (pix_fmt), "-i", "-", ] popen_params = { "stdout": sp.DEVNULL, "stderr": sp.DEVNULL, "stdin": sp.DEVNULL } if os.name == "nt": popen_params["creationflags"] = 0x08000000 if program == "ffmpeg": popen_params["stdin"] = sp.PIPE popen_params["stdout"] = sp.DEVNULL proc1 = sp.Popen( cmd1 + [ "-pix_fmt", (pix_fmt), "-r", "%.02f" % fps, filename, ], **popen_params, ) else: popen_params["stdin"] = sp.PIPE popen_params["stdout"] = sp.PIPE proc1 = sp.Popen(cmd1 + ["-f", "image2pipe", "-vcodec", "bmp", "-"], **popen_params) if program == "ImageMagick": cmd2 = [ IMAGEMAGICK_BINARY, "-delay", "%.02f" % (delay), "-dispose", "%d" % (2 if dispose else 1), "-loop", "%d" % loop, "-", "-coalesce", ] if opt in [False, None]: popen_params["stdin"] = proc1.stdout popen_params["stdout"] = sp.DEVNULL proc2 = sp.Popen(cmd2 + [filename], **popen_params) else: popen_params["stdin"] = proc1.stdout popen_params["stdout"] = sp.PIPE proc2 = sp.Popen(cmd2 + ["gif:-"], **popen_params) if opt: cmd3 = ([ IMAGEMAGICK_BINARY, "-", "-fuzz", "%d" % fuzz + "%", "-layers", opt, ] + (["-colors", "%d" % colors] if colors is not None else []) + [filename]) popen_params["stdin"] = proc2.stdout popen_params["stdout"] = sp.DEVNULL proc3 = sp.Popen(cmd3, **popen_params) # We send all the frames to the first process logger(message="MoviePy - Building file %s" % filename) logger(message="MoviePy - - Generating GIF frames.") try: for t, frame in clip.iter_frames(fps=fps, logger=logger, with_times=True, dtype="uint8"): if withmask: mask = 255 * clip.mask.get_frame(t) frame = np.dstack([frame, mask]).astype("uint8") proc1.stdin.write(frame.tostring()) except IOError as err: error = ("[MoviePy] Error: creation of %s failed because " "of the following error:\n\n%s.\n\n." % (filename, str(err))) if program == "ImageMagick": error += ( "This can be due to the fact that " "ImageMagick is not installed on your computer, or " "(for Windows users) that you didn't specify the " "path to the ImageMagick binary. Check the documentation.") raise IOError(error) if program == "ImageMagick": logger(message="MoviePy - - Optimizing GIF with ImageMagick.") proc1.stdin.close() proc1.wait() if program == "ImageMagick": proc2.wait() if opt: proc3.wait() logger(message="MoviePy - - File ready: %s." % filename)
def stacked_sites_array( enzymes_names, forbidden_enzymes=(), unique_sites=True, tries=10, logger="bar", success_condition=None, ): """Generate a sequence. Parameters ---------- enzymes_names Names of enzyme sites which the algorithm should try to include in the sequence. forbidden_enzymes List of enzymes names whose sites should not be in the sequence. unique_sites If True all the enzymes in enzymes_names will have no more than one site in the final sequence. tries Number of tries. the sequence returned is the one with the best score, i.e. with the least enzymes left over, or the shortest sequence in case of equality. success_condition A function evaluated at the end of each try to validate the designed sequence. Should be of the form ``f(seq, inseq, notinseq) => True/False`` where ``seq`` is the final sequence, ``inseq`` the set of enzymes in the sequence, and ``notinseq`` the set of enzymes not in the sequence. logger Either "bar" for a progress bar, None for no progress logger, or any Proglog progress logger. Returns ------- A triplet (sequence, enzymes_in_sequence, enzymes_not_in_sequence). """ enzymes_names = sorted(set(enzymes_names)) logger = proglog.default_bar_logger(logger, min_time_interval=0.2) patterns = enzymes_to_dna_pattern( list(enzymes_names) + list(forbidden_enzymes)) graph, enzymes_sites, core_enzymes = _enzymes_names_to_distances_graph( enzymes_names) def one_try(): pickable_enzymes_not_in_seq = set(enzymes_names) enzymes_not_in_seq = set(enzymes_names) enzymes_in_seq = set() def add_enzyme(e, as_core=True): if e not in enzymes_in_seq: if e in pickable_enzymes_not_in_seq: pickable_enzymes_not_in_seq.remove(e) enzymes_not_in_seq.remove(e) enzymes_in_seq.add(e) if as_core: for enz in core_enzymes.get(e, []): add_enzyme(enz, as_core=False) list_pickable_enzymes_not_in_seq = list(pickable_enzymes_not_in_seq) path = [ list_pickable_enzymes_not_in_seq[np.random.randint( len(list_pickable_enzymes_not_in_seq))] ] seq = _enzyme_path_to_sequence(path, graph, enzymes_sites) add_enzyme(path[-1]) while len(pickable_enzymes_not_in_seq): nodes_distances = sorted( [(graph[(path[-1], n)]["dist"], n) for n in pickable_enzymes_not_in_seq], key=lambda dn: (dn[0], np.random.rand()), ) choices = [n for d, n in nodes_distances] for new_node in choices: new_path = path + [new_node] new_seq = _enzyme_path_to_sequence(new_path, graph, enzymes_sites) new_diff = len(new_seq) - len(seq) end_seq = new_seq[-(6 + new_diff):] matches = find_patterns_matches(end_seq, patterns) if unique_sites: new_matches = { e: [ m for m in matches[e] if m.end > len(end_seq) - new_diff ] for e in matches } forbidden = list(enzymes_in_seq) + list(forbidden_enzymes) if any([len(new_matches[e]) for e in forbidden]): continue if any( [len(new_matches[e]) > 1 for e in enzymes_not_in_seq]): continue seq = new_seq path = new_path add_enzyme(new_node) for e in list(enzymes_not_in_seq): if len(matches[e]) > 0: add_enzyme(e) break else: return seq, enzymes_in_seq, enzymes_not_in_seq return seq, enzymes_in_seq, enzymes_not_in_seq failure_score = (10000, 10000) def score(seq, in_seq, leftover): if unique_sites or len(forbidden_enzymes): matches = find_patterns_matches(seq, patterns) if unique_sites and any([len(matches[e]) != 1 for e in in_seq]): return failure_score if any([len(matches[e]) for e in forbidden_enzymes]): return failure_score if success_condition is not None: if not success_condition(seq, in_seq, leftover): return failure_score return (len(leftover), len(seq)) current_best = seq, in_seq, leftover = one_try() current_score = score(seq, in_seq, leftover) for _ in logger.iter_bar(tries=range(tries)): new_result = seq, in_seq, leftover = one_try() new_score = score(seq, in_seq, leftover) if new_score < current_score: current_score = new_score current_best = new_result if current_score == failure_score: raise NoSuitableSequenceFound("Could not find a suitable sequence.") return current_best
def write_gif( clip, filename, fps=None, with_mask=True, program="ImageMagick", opt="OptimizeTransparency", fuzz=1, loop=0, dispose=True, colors=None, pixel_format=None, logger="bar", ): """Write the VideoClip to a GIF file, without temporary files. Converts a VideoClip into an animated GIF using ImageMagick or ffmpeg. Parameters ---------- clip : moviepy.video.VideoClip.VideoClip The clip from which the frames will be extracted to create the GIF image. filename : str Name of the resulting gif file. fps : int, optional Number of frames per second. If it isn't provided, then the function will look for the clip's ``fps`` attribute. with_mask : bool, optional Includes tha mask of the clip in the output (the clip must have a mask if this argument is ``True``). program : str, optional Software to use for the conversion, either ``"ImageMagick"`` or ``"ffmpeg"``. opt : str, optional ImageMagick only optimalization to apply, either ``"optimizeplus"`` or ``"OptimizeTransparency"``. Doesn't takes effect if ``program="ffmpeg"``. fuzz : float, optional ImageMagick only compression option which compresses the GIF by considering that the colors that are less than ``fuzz`` different are in fact the same. loop : int, optional Repeat the clip using ``loop`` iterations in the resulting GIF. dispose : bool, optional ImageMagick only option which, when enabled, the ImageMagick binary will take the argument `-dispose 2`, clearing the frame area with the background color, otherwise it will be defined as ``-dispose 1`` which will not dispose, just overlays next frame image. colors : int, optional ImageMagick only option for color reduction. Defines the maximum number of colors that the output image will have. pixel_format : str, optional FFmpeg pixel format for the output gif file. If is not specified ``"rgb24"`` will be used as the default format unless ``clip.mask`` exist, then ``"rgba"`` will be used. Doesn't takes effect if ``program="ImageMagick"``. logger : str, optional Either ``"bar"`` for progress bar or ``None`` or any Proglog logger. Examples -------- The gif will be playing the clip in real time, you can only change the frame rate. If you want the gif to be played slower than the clip you will use: >>> # slow down clip 50% and make it a GIF >>> myClip.multiply_speed(0.5).write_gif('myClip.gif') """ # # We use processes chained with pipes. # # if program == 'ffmpeg' # frames --ffmpeg--> gif # # if program == 'ImageMagick' and optimize == (None, False) # frames --ffmpeg--> bmp frames --ImageMagick--> gif # # # if program == 'ImageMagick' and optimize != (None, False) # frames -ffmpeg-> bmp frames -ImagMag-> gif -ImagMag-> better gif # delay = 100.0 / fps logger = proglog.default_bar_logger(logger) if clip.mask is None: with_mask = False if not pixel_format: pixel_format = "rgba" if with_mask else "rgb24" cmd1 = [ FFMPEG_BINARY, "-y", "-loglevel", "error", "-f", "rawvideo", "-vcodec", "rawvideo", "-r", "%.02f" % fps, "-s", "%dx%d" % (clip.w, clip.h), "-pix_fmt", (pixel_format), "-i", "-", ] popen_params = cross_platform_popen_params({ "stdout": sp.DEVNULL, "stderr": sp.DEVNULL, "stdin": sp.DEVNULL }) if program == "ffmpeg": if loop: clip = loop_fx(clip, n=loop) popen_params["stdin"] = sp.PIPE popen_params["stdout"] = sp.DEVNULL proc1 = sp.Popen( cmd1 + [ "-pix_fmt", (pixel_format), "-r", "%.02f" % fps, filename, ], **popen_params, ) else: popen_params["stdin"] = sp.PIPE popen_params["stdout"] = sp.PIPE proc1 = sp.Popen(cmd1 + ["-f", "image2pipe", "-vcodec", "bmp", "-"], **popen_params) if program == "ImageMagick": cmd2 = [ IMAGEMAGICK_BINARY, "-delay", "%.02f" % (delay), "-dispose", "%d" % (2 if dispose else 1), "-loop", "%d" % loop, "-", "-coalesce", ] if opt in [False, None]: popen_params["stdin"] = proc1.stdout popen_params["stdout"] = sp.DEVNULL proc2 = sp.Popen(cmd2 + [filename], **popen_params) else: popen_params["stdin"] = proc1.stdout popen_params["stdout"] = sp.PIPE proc2 = sp.Popen(cmd2 + ["gif:-"], **popen_params) if opt: cmd3 = ([ IMAGEMAGICK_BINARY, "-", "-fuzz", "%d" % fuzz + "%", "-layers", opt, ] + (["-colors", "%d" % colors] if colors is not None else []) + [filename]) popen_params["stdin"] = proc2.stdout popen_params["stdout"] = sp.DEVNULL proc3 = sp.Popen(cmd3, **popen_params) # We send all the frames to the first process logger(message="MoviePy - Building file %s" % filename) logger(message="MoviePy - - Generating GIF frames.") try: for t, frame in clip.iter_frames(fps=fps, logger=logger, with_times=True, dtype="uint8"): if with_mask: mask = 255 * clip.mask.get_frame(t) frame = np.dstack([frame, mask]).astype("uint8") proc1.stdin.write(frame.tobytes()) except IOError as err: error = ("[MoviePy] Error: creation of %s failed because " "of the following error:\n\n%s.\n\n." % (filename, str(err))) if program == "ImageMagick": error += ( "This can be due to the fact that " "ImageMagick is not installed on your computer, or " "(for Windows users) that you didn't specify the " "path to the ImageMagick binary. Check the documentation.") raise IOError(error) if program == "ImageMagick": logger(message="MoviePy - - Optimizing GIF with ImageMagick.") proc1.stdin.close() proc1.wait() if program == "ImageMagick": proc2.wait() if opt: proc3.wait() logger(message="MoviePy - - File ready: %s." % filename)
def write_videofile( self, filename, fps=None, codec=None, bitrate=None, audio=True, audio_fps=44100, preset="medium", audio_nbytes=4, audio_codec=None, audio_bitrate=None, audio_bufsize=2000, temp_audiofile=None, temp_audiofile_path="", remove_temp=True, write_logfile=False, threads=None, ffmpeg_params=None, logger="bar", pixel_format=None, ): """Write the clip to a videofile. Parameters ---------- filename Name of the video file to write in, as a string or a path-like object. The extension must correspond to the "codec" used (see below), or simply be '.avi' (which will work with any codec). fps Number of frames per second in the resulting video file. If None is provided, and the clip has an fps attribute, this fps will be used. codec Codec to use for image encoding. Can be any codec supported by ffmpeg. If the filename is has extension '.mp4', '.ogv', '.webm', the codec will be set accordingly, but you can still set it if you don't like the default. For other extensions, the output filename must be set accordingly. Some examples of codecs are: - ``'libx264'`` (default codec for file extension ``.mp4``) makes well-compressed videos (quality tunable using 'bitrate'). - ``'mpeg4'`` (other codec for extension ``.mp4``) can be an alternative to ``'libx264'``, and produces higher quality videos by default. - ``'rawvideo'`` (use file extension ``.avi``) will produce a video of perfect quality, of possibly very huge size. - ``png`` (use file extension ``.avi``) will produce a video of perfect quality, of smaller size than with ``rawvideo``. - ``'libvorbis'`` (use file extension ``.ogv``) is a nice video format, which is completely free/ open source. However not everyone has the codecs installed by default on their machine. - ``'libvpx'`` (use file extension ``.webm``) is tiny a video format well indicated for web videos (with HTML5). Open source. audio Either ``True``, ``False``, or a file name. If ``True`` and the clip has an audio clip attached, this audio clip will be incorporated as a soundtrack in the movie. If ``audio`` is the name of an audio file, this audio file will be incorporated as a soundtrack in the movie. audio_fps frame rate to use when generating the sound. temp_audiofile the name of the temporary audiofile, as a string or path-like object, to be created and then used to write the complete video, if any. temp_audiofile_path the location that the temporary audiofile is placed, as a string or path-like object. Defaults to the current working directory. audio_codec Which audio codec should be used. Examples are 'libmp3lame' for '.mp3', 'libvorbis' for 'ogg', 'libfdk_aac':'m4a', 'pcm_s16le' for 16-bit wav and 'pcm_s32le' for 32-bit wav. Default is 'libmp3lame', unless the video extension is 'ogv' or 'webm', at which case the default is 'libvorbis'. audio_bitrate Audio bitrate, given as a string like '50k', '500k', '3000k'. Will determine the size/quality of audio in the output file. Note that it mainly an indicative goal, the bitrate won't necessarily be the this in the final file. preset Sets the time that FFMPEG will spend optimizing the compression. Choices are: ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow, placebo. Note that this does not impact the quality of the video, only the size of the video file. So choose ultrafast when you are in a hurry and file size does not matter. threads Number of threads to use for ffmpeg. Can speed up the writing of the video on multicore computers. ffmpeg_params Any additional ffmpeg parameters you would like to pass, as a list of terms, like ['-option1', 'value1', '-option2', 'value2']. write_logfile If true, will write log files for the audio and the video. These will be files ending with '.log' with the name of the output file in them. logger Either ``"bar"`` for progress bar or ``None`` or any Proglog logger. pixel_format Pixel format for the output video file. Examples -------- >>> from moviepy import VideoFileClip >>> clip = VideoFileClip("myvideo.mp4").subclip(100,120) >>> clip.write_videofile("my_new_video.mp4") >>> clip.close() """ name, ext = os.path.splitext(os.path.basename(filename)) ext = ext[1:].lower() logger = proglog.default_bar_logger(logger) if codec is None: try: codec = extensions_dict[ext]["codec"][0] except KeyError: raise ValueError("MoviePy couldn't find the codec associated " "with the filename. Provide the 'codec' " "parameter in write_videofile.") if audio_codec is None: if ext in ["ogv", "webm"]: audio_codec = "libvorbis" else: audio_codec = "libmp3lame" elif audio_codec == "raw16": audio_codec = "pcm_s16le" elif audio_codec == "raw32": audio_codec = "pcm_s32le" audiofile = audio if isinstance(audio, str) else None make_audio = ((audiofile is None) and (audio is True) and (self.audio is not None)) if make_audio and temp_audiofile: # The audio will be the clip's audio audiofile = temp_audiofile elif make_audio: audio_ext = find_extension(audio_codec) audiofile = os.path.join( temp_audiofile_path, name + Clip._TEMP_FILES_PREFIX + "wvf_snd.%s" % audio_ext, ) # enough cpu for multiprocessing ? USELESS RIGHT NOW, WILL COME AGAIN # enough_cpu = (multiprocessing.cpu_count() > 1) logger(message="Moviepy - Building video %s." % filename) if make_audio: self.audio.write_audiofile( audiofile, audio_fps, audio_nbytes, audio_bufsize, audio_codec, bitrate=audio_bitrate, write_logfile=write_logfile, logger=logger, ) ffmpeg_write_video( self, filename, fps, codec, bitrate=bitrate, preset=preset, write_logfile=write_logfile, audiofile=audiofile, threads=threads, ffmpeg_params=ffmpeg_params, logger=logger, pixel_format=pixel_format, ) if remove_temp and make_audio: if os.path.exists(audiofile): os.remove(audiofile) logger(message="Moviepy - video ready %s" % filename)
def __init__(self, data_dir="default", logger="bar"): if data_dir == "default": data_dir = self.default_dir self.data_dir = data_dir self._logger = proglog.default_bar_logger(logger) self._time_of_last_entrez_call = None
def write_report( self, target, folder_name="auto", assembly_report_writer="default", logger="bar", include_original_parts_records=True, ): """Write a comprehensive report to a folder or zip file. Parameters ---------- target Either a path to a folder, to a zip file, or ``"@memory"`` to write into a virtual zip file whose raw data is then returned. folder_name Name of the folder created inside the target to host the report (yes, it is a folder inside a folder, which can be very practical). assembly_report_writer Either the "default" or any AssemblyReportWriter instance. logger Either "bar" for a progress bar, or None, or any Proglog logger. include_original_parts_records If true, the original provided part records will be included in the report (creates larger file sizes, but better for traceability). """ if assembly_report_writer == "default": # We'll write all records into one folder for the whole plan assembly_report_writer = AssemblyReportWriter( include_part_records=False) logger = proglog.default_bar_logger(logger) if folder_name == "auto": folder_name = self.assembly_plan.name + "_simulation" report_root = file_tree(target)._dir(folder_name, replace=True) self._write_assembly_reports(report_root, assembly_report_writer, logger=logger) self._write_errors_spreadsheet(report_root, error_type="error") self._write_errors_spreadsheet(report_root, error_type="warning") self._write_all_required_parts(report_root) self._write_construct_summary_spreadsheet(report_root) self._write_assembly_plan_spreadsheets(report_root) self._write_summary_stats(report_root) if len(self.cancelled): self._write_cancelled_assemblies(report_root) if include_original_parts_records: self._write_all_required_parts_records(report_root) if not self.has_single_level: self._plot_assembly_graph(report_root) if assembly_report_writer.include_pdf_report: if not PDF_REPORTS_AVAILABLE: raise ImportError( "Could not load PDF Reports. Install with `pip install pdf_reports`" " to generate a PDF report.") simulation_info = self._calculate_simulation_info() write_simulation_pdf_report(report_root._file("Report.pdf"), simulation_info) if target == "@memory": return report_root._close()
def write_gif_with_tempfiles(clip, filename, fps=None, program= 'ImageMagick', opt="OptimizeTransparency", fuzz=1, verbose=True, loop=0, dispose=True, colors=None, logger='bar'): """ Write the VideoClip to a GIF file. Converts a VideoClip into an animated GIF using ImageMagick or ffmpeg. Does the same as write_gif (see this one for more docstring), but writes every frame to a file instead of passing them in the RAM. Useful on computers with little RAM. """ logger = proglog.default_bar_logger(logger) fileName, ext = os.path.splitext(filename) tt = np.arange(0,clip.duration, 1.0/fps) tempfiles = [] logger(message='MoviePy - Building file %s\n' % filename) logger(message='MoviePy - - Generating GIF frames') for i, t in logger.iter_bar(t=list(enumerate(tt))): name = "%s_GIFTEMP%04d.png"%(fileName, i+1) tempfiles.append(name) clip.save_frame(name, t, withmask=True) delay = int(100.0/fps) if program == "ImageMagick": logger(message='MoviePy - - Optimizing GIF with ImageMagick...') cmd = [get_setting("IMAGEMAGICK_BINARY"), '-delay' , '%d'%delay, "-dispose" ,"%d"%(2 if dispose else 1), "-loop" , "%d"%loop, "%s_GIFTEMP*.png"%fileName, "-coalesce", "-layers", "%s"%opt, "-fuzz", "%02d"%fuzz + "%", ]+(["-colors", "%d"%colors] if colors is not None else [])+[ filename] elif program == "ffmpeg": cmd = [get_setting("FFMPEG_BINARY"), '-y', '-f', 'image2', '-r',str(fps), '-i', fileName+'_GIFTEMP%04d.png', '-r',str(fps), filename] try: subprocess_call(cmd, logger=logger) logger(message='MoviePy - GIF ready: %s.' % filename) except (IOError,OSError) as err: error = ("MoviePy Error: creation of %s failed because " "of the following error:\n\n%s.\n\n."%(filename, str(err))) if program == "ImageMagick": error = error + ("This error can be due to the fact that " "ImageMagick is not installed on your computer, or " "(for Windows users) that you didn't specify the " "path to the ImageMagick binary in file conf.py." ) raise IOError(error) for f in tempfiles: os.remove(f)
def write_gif(clip, filename, fps=None, program='ImageMagick', opt="OptimizeTransparency", fuzz=1, verbose=True, withmask=True, loop=0, dispose=True, colors=None, logger='bar'): """ Write the VideoClip to a GIF file, without temporary files. Converts a VideoClip into an animated GIF using ImageMagick or ffmpeg. Parameters ----------- filename Name of the resulting gif file. fps Number of frames per second (see note below). If it isn't provided, then the function will look for the clip's ``fps`` attribute (VideoFileClip, for instance, have one). program Software to use for the conversion, either 'ImageMagick' or 'ffmpeg'. opt (ImageMagick only) optimalization to apply, either 'optimizeplus' or 'OptimizeTransparency'. fuzz (ImageMagick only) Compresses the GIF by considering that the colors that are less than fuzz% different are in fact the same. Notes ----- The gif will be playing the clip in real time (you can only change the frame rate). If you want the gif to be played slower than the clip you will use :: >>> # slow down clip 50% and make it a gif >>> myClip.speedx(0.5).write_gif('myClip.gif') """ # # We use processes chained with pipes. # # if program == 'ffmpeg' # frames --ffmpeg--> gif # # if program == 'ImageMagick' and optimize == (None, False) # frames --ffmpeg--> bmp frames --ImageMagick--> gif # # # if program == 'ImageMagick' and optimize != (None, False) # frames -ffmpeg-> bmp frames -ImagMag-> gif -ImagMag-> better gif # delay = 100.0 / fps logger = proglog.default_bar_logger(logger) if clip.mask is None: withmask = False cmd1 = [ get_setting("FFMPEG_BINARY"), '-y', '-loglevel', 'error', '-f', 'rawvideo', '-vcodec', 'rawvideo', '-r', "%.02f" % fps, '-s', "%dx%d" % (clip.w, clip.h), '-pix_fmt', ('rgba' if withmask else 'rgb24'), '-i', '-' ] popen_params = {"stdout": DEVNULL, "stderr": DEVNULL, "stdin": DEVNULL} if os.name == "nt": popen_params["creationflags"] = 0x08000000 if program == "ffmpeg": popen_params["stdin"] = sp.PIPE popen_params["stdout"] = DEVNULL proc1 = sp.Popen( cmd1 + [ '-pix_fmt', ('rgba' if withmask else 'rgb24'), '-r', "%.02f" % fps, filename ], **popen_params) else: popen_params["stdin"] = sp.PIPE popen_params["stdout"] = sp.PIPE proc1 = sp.Popen(cmd1 + ['-f', 'image2pipe', '-vcodec', 'bmp', '-'], **popen_params) if program == 'ImageMagick': cmd2 = [ get_setting("IMAGEMAGICK_BINARY"), '-delay', "%.02f" % (delay), "-dispose", "%d" % (2 if dispose else 1), '-loop', '%d' % loop, '-', '-coalesce' ] if (opt in [False, None]): popen_params["stdin"] = proc1.stdout popen_params["stdout"] = DEVNULL proc2 = sp.Popen(cmd2 + [filename], **popen_params) else: popen_params["stdin"] = proc1.stdout popen_params["stdout"] = sp.PIPE proc2 = sp.Popen(cmd2 + ['gif:-'], **popen_params) if opt: cmd3 = [ get_setting("IMAGEMAGICK_BINARY"), '-', '-layers', opt, '-fuzz', '%d' % fuzz + '%' ] + (["-colors", "%d" % colors] if colors is not None else []) + [filename] popen_params["stdin"] = proc2.stdout popen_params["stdout"] = DEVNULL proc3 = sp.Popen(cmd3, **popen_params) # We send all the frames to the first process logger(message='MoviePy - Building file %s' % filename) logger(message='MoviePy - - Generating GIF frames.') try: for t, frame in clip.iter_frames(fps=fps, logger=logger, with_times=True, dtype="uint8"): if withmask: mask = 255 * clip.mask.get_frame(t) frame = np.dstack([frame, mask]).astype('uint8') proc1.stdin.write(frame.tostring()) except IOError as err: error = ("[MoviePy] Error: creation of %s failed because " "of the following error:\n\n%s.\n\n." % (filename, str(err))) if program == "ImageMagick": error = error + ( "This can be due to the fact that " "ImageMagick is not installed on your computer, or " "(for Windows users) that you didn't specify the " "path to the ImageMagick binary in file conf.py.") raise IOError(error) if program == 'ImageMagick': logger(message='MoviePy - - Optimizing GIF with ImageMagick.') proc1.stdin.close() proc1.wait() if program == 'ImageMagick': proc2.wait() if opt: proc3.wait() logger(message='MoviePy - - File ready: %s.' % filename)
def write_gif(clip, filename, fps=None, program= 'ImageMagick', opt="OptimizeTransparency", fuzz=1, verbose=True, withmask=True, loop=0, dispose=True, colors=None, logger='bar'): """ Write the VideoClip to a GIF file, without temporary files. Converts a VideoClip into an animated GIF using ImageMagick or ffmpeg. Parameters ----------- filename Name of the resulting gif file. fps Number of frames per second (see note below). If it isn't provided, then the function will look for the clip's ``fps`` attribute (VideoFileClip, for instance, have one). program Software to use for the conversion, either 'ImageMagick' or 'ffmpeg'. opt (ImageMagick only) optimalization to apply, either 'optimizeplus' or 'OptimizeTransparency'. fuzz (ImageMagick only) Compresses the GIF by considering that the colors that are less than fuzz% different are in fact the same. Notes ----- The gif will be playing the clip in real time (you can only change the frame rate). If you want the gif to be played slower than the clip you will use :: >>> # slow down clip 50% and make it a gif >>> myClip.speedx(0.5).write_gif('myClip.gif') """ # # We use processes chained with pipes. # # if program == 'ffmpeg' # frames --ffmpeg--> gif # # if program == 'ImageMagick' and optimize == (None, False) # frames --ffmpeg--> bmp frames --ImageMagick--> gif # # # if program == 'ImageMagick' and optimize != (None, False) # frames -ffmpeg-> bmp frames -ImagMag-> gif -ImagMag-> better gif # delay= 100.0/fps logger = proglog.default_bar_logger(logger) if clip.mask is None: withmask = False cmd1 = [get_setting("FFMPEG_BINARY"), '-y', '-loglevel', 'error', '-f', 'rawvideo', '-vcodec','rawvideo', '-r', "%.02f"%fps, '-s', "%dx%d"%(clip.w, clip.h), '-pix_fmt', ('rgba' if withmask else 'rgb24'), '-i', '-'] popen_params = {"stdout": DEVNULL, "stderr": DEVNULL, "stdin": DEVNULL} if os.name == "nt": popen_params["creationflags"] = 0x08000000 if program == "ffmpeg": popen_params["stdin"] = sp.PIPE popen_params["stdout"] = DEVNULL proc1 = sp.Popen(cmd1+[ '-pix_fmt', ('rgba' if withmask else 'rgb24'), '-r', "%.02f"%fps, filename], **popen_params) else: popen_params["stdin"] = sp.PIPE popen_params["stdout"] = sp.PIPE proc1 = sp.Popen(cmd1+ ['-f', 'image2pipe', '-vcodec', 'bmp', '-'], **popen_params) if program == 'ImageMagick': cmd2 = [get_setting("IMAGEMAGICK_BINARY"), '-delay', "%.02f"%(delay), "-dispose" ,"%d"%(2 if dispose else 1), '-loop', '%d'%loop, '-', '-coalesce'] if (opt in [False, None]): popen_params["stdin"] = proc1.stdout popen_params["stdout"] = DEVNULL proc2 = sp.Popen(cmd2+[filename], **popen_params) else: popen_params["stdin"] = proc1.stdout popen_params["stdout"] = sp.PIPE proc2 = sp.Popen(cmd2+['gif:-'], **popen_params) if opt: cmd3 = [get_setting("IMAGEMAGICK_BINARY"), '-', '-layers', opt, '-fuzz', '%d'%fuzz+'%' ]+(["-colors", "%d"%colors] if colors is not None else [])+[ filename] popen_params["stdin"] = proc2.stdout popen_params["stdout"] = DEVNULL proc3 = sp.Popen(cmd3, **popen_params) # We send all the frames to the first process logger(message='MoviePy - Building file %s' % filename) logger(message='MoviePy - - Generating GIF frames.') try: for t,frame in clip.iter_frames(fps=fps, logger=logger, with_times=True, dtype="uint8"): if withmask: mask = 255 * clip.mask.get_frame(t) frame = np.dstack([frame, mask]).astype('uint8') proc1.stdin.write(frame.tostring()) except IOError as err: error = ("[MoviePy] Error: creation of %s failed because " "of the following error:\n\n%s.\n\n."%(filename, str(err))) if program == "ImageMagick": error = error + ("This can be due to the fact that " "ImageMagick is not installed on your computer, or " "(for Windows users) that you didn't specify the " "path to the ImageMagick binary in file conf.py." ) raise IOError(error) if program == 'ImageMagick': logger(message='MoviePy - - Optimizing GIF with ImageMagick.') proc1.stdin.close() proc1.wait() if program == 'ImageMagick': proc2.wait() if opt: proc3.wait() logger(message='MoviePy - - File ready: %s.' % filename)
def full_assembly_plan_report(assembly_plan, target, part_records=None, enzyme="autoselect", assert_single_assemblies=True, logger="bar", connector_records=(), fail_silently=True, errors_with_traceback=False, **report_kwargs): """Makes a full report for a plan (list of single assemblies) Parameters ---------- assembly_plan A list ``[('name', [parts])...]`` or a dict ``{name: [parts]}`` where the parts are either records, or simply part names (in that case you must provide the records in ``parts_records``) parts_records A dict {part_name: part_record}. target Either a path to a folder, or to a zip file, or ``@memory`` to return a string representing zip data (the latter is particularly useful for website backends). enzyme Name of the enzyme to be used in the assembly max_assemblies Maximal number of assemblies to consider. If there are more than this the additional ones won't be returned. fragments_filters Fragments filters to be used to filter out fragments before looking for assemblies. If left to auto, fragments containing the enzyme site will be filtered out. connector_records List of connector records (a connector is a part that can bridge a gap between two other parts), from which only the essential elements to form an assembly will be automatically selected and added to the other parts. **report_kwargs Any other parameter of ``full_assembly_report``. For instance: include_fragments_plots, include_parts_plot, include_assembly_plots Returns ------- errored_assemblies,zip_data list of errored assemblies with errors, and binary zip data (or None if the target is not "@memory") """ logger = default_bar_logger(logger) if isinstance(assembly_plan, list): assembly_plan = OrderedDict(assembly_plan) if isinstance(list(assembly_plan.values())[0][0], str): if not hasattr(part_records, "items"): part_records = {r.name: r for r in part_records} for part in list(part_records): part_records[part] = deepcopy(part_records[part]) part_records[part].name = part_records[part].id = part assembly_plan = OrderedDict([(name, [part_records[p] for p in parts]) for name, parts in assembly_plan.items()]) root = file_tree(target, replace=True) all_records_folder = root._dir("all_records") errored_assemblies = [] assemblies = list(assembly_plan.items()) selected_enzymes = [] # Used to keep track of autoselected enzymes for asm_name, parts in logger.iter_bar(assembly=assemblies): if enzyme == "autoselect": selected_enzyme = autoselect_enzyme(parts) selected_enzymes.append((asm_name, selected_enzyme)) else: selected_enzyme = enzyme asm_folder = root._dir(asm_name) try: n = full_assembly_report( parts, target=asm_folder, assemblies_prefix=asm_name, enzyme=selected_enzyme, connector_records=connector_records, n_expected_assemblies=1 if assert_single_assemblies else None, **report_kwargs) if assert_single_assemblies and (n != 1): raise ValueError("%s assemblies found instead of 1 for %s." % (n, asm_name)) for f in asm_folder.assemblies._all_files: if f._extension == "gb": f.copy(all_records_folder) except Exception as err: if fail_silently: err_string = str(err) if errors_with_traceback: err_string += str(err.__traceback__) errored_assemblies.append((asm_name, str(err))) else: raise err if len(errored_assemblies): root._file("errored_assemblies.txt").write("\n\n".join( ["%s: %s" % (name, error) for name, error in errored_assemblies])) f = root._file("assembly_plan.csv") f.write("construct, parts") all_parts = [] for f_ in root._all_files: if f_._name_no_extension == "report": first_row = f_.read("r").split("\n")[1].split(",") if len(first_row) == 4: name, _, _, parts = first_row parts = parts.split(" & ") all_parts += parts f.write("\n" + ",".join([name] + parts)) all_parts = sorted(set(all_parts)) root._file("all_parts.csv").write(",\n".join(all_parts)) if enzyme == "autoselect": root._file("selected_enzymes_per_construct.csv").write(",\n".join( [",".join(selection) for selection in selected_enzymes])) return errored_assemblies, root._close()
def write_gif_with_image_io(clip, filename, fps=None, opt=0, loop=0, colors=None, verbose=True, logger="bar"): """ Writes the gif with the Python library ImageIO (calls FreeImage). Parameters ----------- opt """ if colors is None: colors = 256 logger = proglog.default_bar_logger(logger) if not IMAGEIO_FOUND: raise ImportError( "Writing a gif with imageio requires ImageIO installed," " with e.g. 'pip install imageio'") if fps is None: fps = clip.fps quantizer = 0 if opt != 0 else "nq" writer = imageio.save("temp.gif", duration=1.0 / fps, quantizer=quantizer, palettesize=colors, loop=loop) logger(message="MoviePy - Building file %s with imageio." % filename) for frame in clip.iter_frames(fps=fps, logger=logger, dtype="uint8"): writer.append_data(frame) # Optimize file here # cmd3 = ( # [ # # "convert", # get_setting("IMAGEMAGICK_BINARY"), # filename, # "-layers", # "optimize-plus", # "-fuzz", # "1%", # filename # ] # ) cmd3 = ([ # "convert", get_setting("IMAGEMAGICK_BINARY"), "temp.gif", "-layers", "optimize-plus", "-fuzz", "1%", filename ]) popen_params = {"stdout": DEVNULL, "stderr": DEVNULL, "stdin": DEVNULL} # popen_params["stdin"] = proc2.stdout popen_params["stdout"] = DEVNULL proc3 = sp.Popen(cmd3, **popen_params) print("we used cmd3", cmd3) proc3.wait() os.remove("temp.gif")
def write_gif_with_tempfiles( clip, filename, fps=None, program="ImageMagick", opt="OptimizeTransparency", fuzz=1, loop=0, dispose=True, colors=None, pixel_format=None, logger="bar", ): """Write the VideoClip to a GIF file. Converts a VideoClip into an animated GIF using ImageMagick or ffmpeg. Does the same as write_gif (see this one for more docstring), but writes every frame to a file instead of passing them in the RAM. Useful on computers with little RAM. Parameters ---------- clip : moviepy.video.VideoClip.VideoClip The clip from which the frames will be extracted to create the GIF image. filename : str Name of the resulting gif file. fps : int, optional Number of frames per second. If it isn't provided, then the function will look for the clip's ``fps`` attribute. program : str, optional Software to use for the conversion, either ``"ImageMagick"`` or ``"ffmpeg"``. opt : str, optional ImageMagick only optimalization to apply, either ``"optimizeplus"`` or ``"OptimizeTransparency"``. Doesn't takes effect if ``program="ffmpeg"``. fuzz : float, optional ImageMagick only compression option which compresses the GIF by considering that the colors that are less than ``fuzz`` different are in fact the same. loop : int, optional Repeat the clip using ``loop`` iterations in the resulting GIF. dispose : bool, optional ImageMagick only option which, when enabled, the ImageMagick binary will take the argument `-dispose 2`, clearing the frame area with the background color, otherwise it will be defined as ``-dispose 1`` which will not dispose, just overlays next frame image. colors : int, optional ImageMagick only option for color reduction. Defines the maximum number of colors that the output image will have. pixel_format : str, optional FFmpeg pixel format for the output gif file. If is not specified ``"rgb24"`` will be used as the default format unless ``clip.mask`` exist, then ``"rgba"`` will be used. Doesn't takes effect if ``program="ImageMagick"``. logger : str, optional Either ``"bar"`` for progress bar or ``None`` or any Proglog logger. """ logger = proglog.default_bar_logger(logger) file_root, ext = os.path.splitext(filename) tt = np.arange(0, clip.duration, 1.0 / fps) tempfiles = [] logger(message="MoviePy - Building file %s\n" % filename) logger(message="MoviePy - - Generating GIF frames") for i, t in logger.iter_bar(t=list(enumerate(tt))): name = "%s_GIFTEMP%04d.png" % (file_root, i + 1) tempfiles.append(name) clip.save_frame(name, t, with_mask=True) delay = int(100.0 / fps) if clip.mask is None: with_mask = False if program == "ImageMagick": if not pixel_format: pixel_format = "RGBA" if with_mask else "RGB" logger(message="MoviePy - - Optimizing GIF with ImageMagick...") cmd = ([ IMAGEMAGICK_BINARY, "-delay", "%d" % delay, "-dispose", "%d" % (2 if dispose else 1), "-loop", "%d" % loop, "%s_GIFTEMP*.png" % file_root, "-coalesce", "-fuzz", "%02d" % fuzz + "%", "-layers", "%s" % opt, "-set", "colorspace", pixel_format, ] + (["-colors", "%d" % colors] if colors is not None else []) + [filename]) elif program == "ffmpeg": if loop: clip = loop_fx(clip, n=loop) if not pixel_format: pixel_format = "rgba" if with_mask else "rgb24" cmd = [ FFMPEG_BINARY, "-y", "-f", "image2", "-r", str(fps), "-i", file_root + "_GIFTEMP%04d.png", "-r", str(fps), filename, "-pix_fmt", (pixel_format), ] try: subprocess_call(cmd, logger=logger) logger(message="MoviePy - GIF ready: %s." % filename) except (IOError, OSError) as err: error = ("MoviePy Error: creation of %s failed because " "of the following error:\n\n%s.\n\n." % (filename, str(err))) if program == "ImageMagick": error += ( "This error can be due to the fact that " "ImageMagick is not installed on your computer, or " "(for Windows users) that you didn't specify the " "path to the ImageMagick binary. Check the documentation.") raise IOError(error) for file in tempfiles: os.remove(file)
def compute_all_construct_quotes( construct_sequences, part_sequences, assembly_method, logger="bar", max_constructs=None, ): """Compute the quotes for all the constructs in the assembly plan. The constructs are considered one after the other and every primer and fragment used in a construct are considered as available for free in the next construct assembly. Parameters ---------- construct_sequences A dict of the form ``{construct_id: "ATGCCC..."}`` of all constructs to be built. parts_sequences A dictionary {part_id: "ATGCGC..."} of the base genetic parts, which will be considered as available for free. assembly_method Either "gibson", "golden_gate", or "any_method" (each construct will then be assembled using any method, with a preference for Golden Gate Assembly) logger="bar" A proglog logger Returns ------- (quotes_dict, ordered_primers, amplified_fragments_quotes, errors) Data on the optimized DNA manufacturing plan - quotes_dict is a dict of the form {quote_id: quote} (where "quote" is a DNA Weaver Quote) - ordered_primers is a dict {primer_id: "ATGTGC..."} of all primers ordered in the whole construction plan. - amplified_fragments_quotes is a dict {fragment_id: quote} of DNA Weaver quotes for each PCR-created fragment in the construction plan. - errored is a dict {construct_id: "Error message"} for all failed assemblies """ logger = proglog.default_bar_logger(logger) ordered_primers = OrderedDict() amplified_fragments = OrderedDict() amplified_fragments_quotes = OrderedDict() quotes_dict = OrderedDict() errors = OrderedDict() iterator = list(enumerate(construct_sequences.items())) if max_constructs is not None: iterator = iterator[:max_constructs] for i, (construct, sequence) in logger.iter_bar(construct=iterator): # CREATE THE SUPPLY NETWORK main_station = generate_supply_network( parts_sequences=part_sequences, already_amplified_fragments=amplified_fragments, already_ordered_primers=ordered_primers, assembly_method=assembly_method, ) # FIND AN ASSEMBLY PLAN, ABORT IF ERRORS OR REJECTION try: for shift in range(5): # In DNA weaver, the sequence's 0 position is always considered # a cut site. In the unlucky case where this cut site is # invalid (e.g. it has a palyndromic sequence preventing # Golden Gate assembly), we rotate the sequence a bit to find # a better position 0 rotated_sequence = sequence[shift:] + sequence[:shift] rotated_sequence = SequenceString( rotated_sequence, metadata={"topology": "circular"}) main_station.prepare_network_on_sequence(rotated_sequence) quote = main_station.get_quote(rotated_sequence) if quote.accepted: break except Exception as err: logger(message="Construct %s errored." % construct) errors[construct] = str(err) continue if not quote.accepted: logger(message="Construct %s: no valid plan found." % construct) errors[construct] = "No assembly plan found: %s" % quote.message continue logger(message="Construct %s processed succesfully." % construct) # IF SUCCESS, LOG THE QUOTE AND ITS PRODUCTS id_prefix = "ID_%s" % (i + 1) quote.compute_full_assembly_plan(id_prefix=id_prefix, id_digits=3) for _quote in quote.tree_as_list(): if _quote.source.operation_type == "PCR": amplified_fragments[_quote.id] = _quote.sequence amplified_fragments_quotes[_quote.id] = _quote if _quote.source.name == "oligo_supplier": ordered_primers[_quote.id] = _quote.sequence quotes_dict[construct] = quote # RETURN THE COMPILED DATA return (quotes_dict, ordered_primers, amplified_fragments_quotes, errors)
def write_gif_with_tempfiles(clip, filename, fps=None, program='ImageMagick', opt="OptimizeTransparency", fuzz=1, verbose=True, loop=0, dispose=True, colors=None, logger='bar'): """ Write the VideoClip to a GIF file. Converts a VideoClip into an animated GIF using ImageMagick or ffmpeg. Does the same as write_gif (see this one for more docstring), but writes every frame to a file instead of passing them in the RAM. Useful on computers with little RAM. """ logger = proglog.default_bar_logger(logger) fileName, ext = os.path.splitext(filename) tt = np.arange(0, clip.duration, 1.0 / fps) tempfiles = [] logger(message='MoviePy - Building file %s\n' % filename) logger(message='MoviePy - - Generating GIF frames') for i, t in logger.iter_bar(t=list(enumerate(tt))): name = "%s_GIFTEMP%04d.png" % (fileName, i + 1) tempfiles.append(name) clip.save_frame(name, t, withmask=True) delay = int(100.0 / fps) if program == "ImageMagick": logger(message='MoviePy - - Optimizing GIF with ImageMagick...') cmd = [ get_setting("IMAGEMAGICK_BINARY"), '-delay', '%d' % delay, "-dispose", "%d" % (2 if dispose else 1), "-loop", "%d" % loop, "%s_GIFTEMP*.png" % fileName, "-coalesce", "-layers", "%s" % opt, "-fuzz", "%02d" % fuzz + "%", ] + (["-colors", "%d" % colors] if colors is not None else []) + [filename] elif program == "ffmpeg": cmd = [ get_setting("FFMPEG_BINARY"), '-y', '-f', 'image2', '-r', str(fps), '-i', fileName + '_GIFTEMP%04d.png', '-r', str(fps), filename ] try: subprocess_call(cmd, logger=logger) logger(message='MoviePy - GIF ready: %s.' % filename) except (IOError, OSError) as err: error = ("MoviePy Error: creation of %s failed because " "of the following error:\n\n%s.\n\n." % (filename, str(err))) if program == "ImageMagick": error = error + ( "This error can be due to the fact that " "ImageMagick is not installed on your computer, or " "(for Windows users) that you didn't specify the " "path to the ImageMagick binary in file conf.py.") raise IOError(error) for f in tempfiles: os.remove(f)
>>> dnacauldron multi_assembly.xlsx part_sequences output --connectors=connector_sequences at the command line. """ import dnacauldron as dc import proglog import os connectors_path = "connector_sequences" sequences_path = "part_sequences" assembly_plan_path = "multi_assembly.xlsx" target_path = "output" verbose = True logger = proglog.default_bar_logger("bar" if verbose else None) logger(message="Importing the sequences...") sequence_repository = dc.SequenceRepository() sequence_repository.import_records(folder=sequences_path) for subfolder_name in os.listdir(connectors_path): subfolder_path = os.path.join(connectors_path, subfolder_name) sequence_repository.import_records(folder=subfolder_path, collection=subfolder_name) logger(message="Simulating the assembly plan...") assembly_plan = dc.AssemblyPlan.from_spreadsheet(assembly_plan_path, logger=logger) simulation = assembly_plan.simulate(sequence_repository=sequence_repository) logger(message="Simulation finished. Here are the stats:")