Instruction:
Can you write a function in Python 3 where it
gets all the paths of non - hidden files in a directory and returns a list of those paths.

Response:
def get_paths(directory):
    '''Gets all the paths of non-hidden files in a directory
       and returns a list of those paths.

    Parameters
    ----------
    directory : str
        The directory whose contents you wish to grab.

    Returns
    -------
    paths : List[str]
    '''
    fnames = [os.path.join(directory, f)
              for f in os.listdir(directory)
              if os.path.isfile(os.path.join(directory, f))
              and not f.startswith('.')]
    return fnames


Instruction:
Can you generate a brief explanation for the following Python 3 code
def image_resize(file_paths, new_dir, width, height):
    '''Resizes all images with given paths to new dimensions.
        Uses up/downscaling with antialiasing.

    Parameters
    ----------
    file_paths : List[str]
        List of path strings for image to resize.
    new_dir : str
        Directory to place resized images.
    width : int
        Target width of new resized images.
    height : int
        Target height of new resized images.
    '''
    if new_dir[-1] != '/':
        new_dir += '/'

    if not os.path.exists(os.path.dirname(new_dir)):
        os.makedirs(os.path.dirname(new_dir))

    for f in tqdm.tqdm(file_paths):
        img = Image.open(f).resize((width, height), Image.ANTIALIAS).convert('RGB')
        new = os.path.join(new_dir, os.path.basename(f))
        img.save(new)

Response: Resizes all images with given paths to new dimensions.


Instruction:
Here you have a function in Python 3, explain what it does
def inverse_transform(self, data, test=False):
        '''Transform latent vectors into images.

        Parameters
        ----------
        data : array-like shape (n_images, latent_width)
            Input numpy array of images.
        test [optional] : bool
            Controls the test boolean for batch normalization.

        Returns
        -------
        images : array-like shape (n_images, image_width, image_height,
                                   n_colors)
        '''
        if not type(data) == Variable:
            if len(data.shape) < 2:
                data = data[np.newaxis]
            if len(data.shape) != 2:
                raise TypeError("Invalid dimensions for latent data. Dim = %s.\
                     Must be a 2d array." % str(data.shape))
            data = Variable(data)

        else:
            if len(data.data.shape) < 2:
                data.data = data.data[np.newaxis]
            if len(data.data.shape) != 2:
                raise TypeError("Invalid dimensions for latent data. Dim = %s.\
                     Must be a 2d array." % str(data.data.shape))
        assert data.data.shape[-1] == self.latent_width,\
            "Latent shape %d != %d" % (data.data.shape[-1], self.latent_width)

        if self.flag_gpu:
            data.to_gpu()
        out = self.model.decode(data, test=test)

        out.to_cpu()

        if self.mode == 'linear':
            final = out.data
        else:
            final = out.data.transpose(0, 2, 3, 1)

        return final

Response: Transform latent vectors into images.


Instruction:
Create a Python 3 function to
load in image files from list of filepaths.

Response:
def load_images(self, filepaths):
        '''Load in image files from list of paths.

        Parameters
        ----------

        filepaths : List[str]
            List of file paths of images to be loaded.

        Returns
        -------
        images : array-like shape (n_images, n_colors, image_width, image_height)
            Images normalized to have pixel data range [0,1].

        '''
        def read(fname):
            im = Image.open(fname)
            im = np.float32(im)
            return im/255.
        x_all = np.array([read(fname) for fname in tqdm.tqdm(filepaths)])
        x_all = x_all.astype('float32')
        if self.mode == 'convolution':
            x_all = x_all.transpose(0, 3, 1, 2)
        print("Image Files Loaded!")
        return x_all


Instruction:
Can you generate the documentation for the following Python 3 function
def fit(
        self,
        img_data,
        save_freq=-1,
        pic_freq=-1,

        n_epochs=100,
        batch_size=50,
        weight_decay=True,
        model_path='./VAE_training_model/',
        img_path='./VAE_training_images/',
        img_out_width=10
    ):

        '''Fit the VAE model to the image data.

        Parameters
        ----------

        img_data : array-like shape (n_images, n_colors, image_width, image_height)
            Images used to fit VAE model.
        save_freq [optional] : int
            Sets the number of epochs to wait before saving the model and optimizer states.
            Also saves image files of randomly generated images using those states in a
            separate directory. Does not save if negative valued.
        pic_freq [optional] : int
            Sets the number of batches to wait before displaying a picture or randomly
            generated images using the current model state.
            Does not display if negative valued.
        n_epochs [optional] : int
            Gives the number of training epochs to run through for the fitting
            process.
        batch_size [optional] : int
            The size of the batch to use when training. Note: generally larger
            batch sizes will result in fater epoch iteration, but at the const
            of lower granulatity when updating the layer weights.
        weight_decay [optional] : bool
            Flag that controls adding weight decay hooks to the optimizer.
        model_path [optional] : str
            Directory where the model and optimizer state files will be saved.
        img_path [optional] : str
            Directory where the end of epoch training image files will be saved.
        img_out_width : int
            Controls the number of randomly genreated images per row in the output
            saved imags.
        '''
        width = img_out_width
        self.opt.setup(self.model)

        if weight_decay:
            self.opt.add_hook(chainer.optimizer.WeightDecay(0.00001))

        n_data = img_data.shape[0]

        batch_iter = list(range(0, n_data, batch_size))
        n_batches = len(batch_iter)
        save_counter = 0
        for epoch in range(1, n_epochs + 1):
            print('epoch: %i' % epoch)
            t1 = time.time()
            indexes = np.random.permutation(n_data)
            last_loss_kl = 0.
            last_loss_rec = 0.
            count = 0
            for i in tqdm.tqdm(batch_iter):

                x_batch = Variable(img_data[indexes[i: i + batch_size]])

                if self.flag_gpu:
                    x_batch.to_gpu()

                out, kl_loss, rec_loss = self.model.forward(x_batch)
                total_loss = rec_loss + kl_loss*self.kl_ratio

                self.opt.zero_grads()
                total_loss.backward()
                self.opt.update()

                last_loss_kl += kl_loss.data
                last_loss_rec += rec_loss.data
                plot_pics = Variable(img_data[indexes[:width]])
                count += 1
                if pic_freq > 0:
                    assert type(pic_freq) == int, "pic_freq must be an integer."
                    if count % pic_freq == 0:
                        fig = self._plot_img(
                            plot_pics,
                            img_path=img_path,
                            epoch=epoch
                        )
                        display(fig)

            if save_freq > 0:
                save_counter += 1
                assert type(save_freq) == int, "save_freq must be an integer."
                if epoch % save_freq == 0:
                    name = "vae_epoch%s" % str(epoch)
                    if save_counter == 1:
                        save_meta = True
                    else:
                        save_meta = False
                    self.save(model_path, name, save_meta=save_meta)
                    fig = self._plot_img(
                        plot_pics,
                        img_path=img_path,
                        epoch=epoch,
                        batch=n_batches,
                        save=True
                        )

            msg = "rec_loss = {0} , kl_loss = {1}"
            print(msg.format(last_loss_rec/n_batches, last_loss_kl/n_batches))
            t_diff = time.time()-t1
            print("time: %f\n\n" % t_diff)

Response: Fit the VAE model to the image data.


Instruction:
Write a Python 3 function that can
save the current state of the class to a sequence of files in the format : . h5 .

Response:
def save(self, path, name, save_meta=True):
        '''Saves model as a sequence of files in the format:
            {path}/{name}_{'model', 'opt', 'meta'}.h5

        Parameters
        ----------
        path : str
            The directory of the file you wish to save the model to.
        name : str
            The name prefix of the model and optimizer files you wish
            to save.
        save_meta [optional] : bool
            Flag that controls whether to save the class metadata along with
            the encoder, decoder, and respective optimizer states.
        '''
        _save_model(self.model, str(path), "%s_model" % str(name))
        _save_model(self.opt, str(path), "%s_opt" % str(name))
        if save_meta:
            self._save_meta(os.path.join(path, "%s_meta" % str(name)))


Instruction:
How would you implement a function in Python 3 that
loads in model as a class instance with the specified model and optimizer states.

Response:
def load(cls, model, opt, meta, flag_gpu=None):
        '''Loads in model as a class instance with with the specified
           model and optimizer states.

        Parameters
        ----------
        model : str
            Path to the model state file.
        opt : str
            Path to the optimizer state file.
        meta : str
            Path to the class metadata state file.
        flag_gpu : bool
            Specifies whether to load the model to use gpu capabilities.

        Returns
        -------

        class instance of self.
        '''
        mess = "Model file {0} does not exist. Please check the file path."
        assert os.path.exists(model), mess.format(model)
        assert os.path.exists(opt), mess.format(opt)
        assert os.path.exists(meta), mess.format(meta)
        with open(meta, 'r') as f:
            meta = json.load(f)
        if flag_gpu is not None:
            meta['flag_gpu'] = flag_gpu

        loaded_class = cls(**meta)

        serializers.load_hdf5(model, loaded_class.model)
        loaded_class.opt.setup(loaded_class.model)
        serializers.load_hdf5(opt, loaded_class.opt)

        if meta['flag_gpu']:
            loaded_class.model = loaded_class.model.to_gpu()

        return loaded_class


Instruction:
Create a Python 3 function to
fit the GAN model to the image data.

Response:
def fit(
        self,
        img_data,
        save_freq=-1,
        pic_freq=-1,
        n_epochs=100,
        batch_size=50,
        weight_decay=True,
        model_path='./GAN_training_model/',
        img_path='./GAN_training_images/',
        img_out_width=10,
        mirroring=False
    ):
        '''Fit the GAN model to the image data.

        Parameters
        ----------

        img_data : array-like shape (n_images, n_colors, image_width, image_height)
            Images used to fit VAE model.
        save_freq [optional] : int
            Sets the number of epochs to wait before saving the model and optimizer states.
            Also saves image files of randomly generated images using those states in a
            separate directory. Does not save if negative valued.
        pic_freq [optional] : int
            Sets the number of batches to wait before displaying a picture or randomly
            generated images using the current model state.
            Does not display if negative valued.
        n_epochs [optional] : int
            Gives the number of training epochs to run through for the fitting
            process.
        batch_size [optional] : int
            The size of the batch to use when training. Note: generally larger
            batch sizes will result in fater epoch iteration, but at the const
            of lower granulatity when updating the layer weights.
        weight_decay [optional] : bool
            Flag that controls adding weight decay hooks to the optimizer.
        model_path [optional] : str
            Directory where the model and optimizer state files will be saved.
        img_path [optional] : str
            Directory where the end of epoch training image files will be saved.
        img_out_width : int
            Controls the number of randomly genreated images per row in the output
            saved imags.
        mirroring [optional] : bool
            Controls whether images are randomly mirrored along the verical axis with
            a .5 probability. Artificially increases images variance for training set.
        '''
        width = img_out_width
        self.dec_opt.setup(self.dec)
        self.disc_opt.setup(self.disc)

        if weight_decay:
            self.dec_opt.add_hook(chainer.optimizer.WeightDecay(0.00001))
            self.disc_opt.add_hook(chainer.optimizer.WeightDecay(0.00001))

        n_data = img_data.shape[0]

        batch_iter = list(range(0, n_data, batch_size))
        n_batches = len(batch_iter)

        c_samples = np.random.standard_normal((width, self.latent_width)).astype(np.float32)
        save_counter = 0

        for epoch in range(1, n_epochs + 1):
            print('epoch: %i' % epoch)
            t1 = time.time()
            indexes = np.random.permutation(n_data)
            last_loss_dec = 0.
            last_loss_disc = 0.
            count = 0
            for i in tqdm.tqdm(batch_iter):
                x = img_data[indexes[i: i + batch_size]]
                size = x.shape[0]
                if mirroring:
                    for j in range(size):
                        if np.random.randint(2):
                            x[j, :, :, :] = x[j, :, :, ::-1]
                x_batch = Variable(x)
                zeros = Variable(np.zeros(size, dtype=np.int32))
                ones = Variable(np.ones(size, dtype=np.int32))

                if self.flag_gpu:
                    x_batch.to_gpu()
                    zeros.to_gpu()
                    ones.to_gpu()

                disc_samp, disc_batch = self._forward(x_batch)

                L_dec = F.softmax_cross_entropy(disc_samp, ones)

                L_disc = F.softmax_cross_entropy(disc_samp, zeros)
                L_disc += F.softmax_cross_entropy(disc_batch, ones)
                L_disc /= 2.

                self.dec_opt.zero_grads()
                L_dec.backward()
                self.dec_opt.update()

                self.disc_opt.zero_grads()
                L_disc.backward()
                self.disc_opt.update()

                last_loss_dec += L_dec.data
                last_loss_disc += L_disc.data
                count += 1
                if pic_freq > 0:
                    assert type(pic_freq) == int, "pic_freq must be an integer."
                    if count % pic_freq == 0:
                        fig = self._plot_img(
                            c_samples,
                            img_path=img_path,
                            epoch=epoch
                        )
                        display(fig)

            if save_freq > 0:
                save_counter += 1
                assert type(save_freq) == int, "save_freq must be an integer."
                if epoch % save_freq == 0:
                    name = "gan_epoch%s" % str(epoch)
                    if save_counter == 1:
                        save_meta = True
                    else:
                        save_meta = False
                    self.save(model_path, name, save_meta=save_meta)
                    fig = self._plot_img(
                        c_samples,
                        img_path=img_path,
                        epoch=epoch,
                        batch=n_batches,
                        save_pic=True
                        )

            msg = "dec_loss = {0} , disc_loss = {1}"
            print(msg.format(last_loss_dec/n_batches, last_loss_disc/n_batches))
            t_diff = time.time()-t1
            print("time: %f\n\n" % t_diff)


Instruction:
Can you generate the documentation for the following Python 3 function
def save(self, path, name, save_meta=True):
        '''Saves model as a sequence of files in the format:
            {path}/{name}_{'dec', 'disc', 'dec_opt',
            'disc_opt', 'meta'}.h5

        Parameters
        ----------
        path : str
            The directory of the file you wish to save the model to.
        name : str
            The name prefix of the model and optimizer files you wish
            to save.
        save_meta [optional] : bool
            Flag that controls whether to save the class metadata along with
            the generator, discriminator, and respective optimizer states.
        '''
        _save_model(self.dec, str(path), "%s_dec" % str(name))
        _save_model(self.disc, str(path), "%s_disc" % str(name))
        _save_model(self.dec_opt, str(path), "%s_dec_opt" % str(name))
        _save_model(self.disc_opt, str(path), "%s_disc_opt" % str(name))
        if save_meta:
            self._save_meta(os.path.join(path, "%s_meta" % str(name)))

Response: Saves the current state of the class to a sequence of files in the format dec_opt meta. h5


Instruction:
Given the following Python 3 function, write the documentation
def transform(self, data, test=False):
        '''Transform image data to latent space.

        Parameters
        ----------
        data : array-like shape (n_images, image_width, image_height,
                                   n_colors)
            Input numpy array of images.
        test [optional] : bool
            Controls the test boolean for batch normalization.

        Returns
        -------
        latent_vec : array-like shape (n_images, latent_width)
        '''
        #make sure that data has the right shape.
        if not type(data) == Variable:
            if len(data.shape) < 4:
                data = data[np.newaxis]
            if len(data.shape) != 4:
                raise TypeError("Invalid dimensions for image data. Dim = %s.\
                     Must be 4d array." % str(data.shape))
            if data.shape[1] != self.color_channels:
                if data.shape[-1] == self.color_channels:
                    data = data.transpose(0, 3, 1, 2)
                else:
                    raise TypeError("Invalid dimensions for image data. Dim = %s"
                                    % str(data.shape))
            data = Variable(data)
        else:
            if len(data.data.shape) < 4:
                data.data = data.data[np.newaxis]
            if len(data.data.shape) != 4:
                raise TypeError("Invalid dimensions for image data. Dim = %s.\
                     Must be 4d array." % str(data.data.shape))
            if data.data.shape[1] != self.color_channels:
                if data.data.shape[-1] == self.color_channels:
                    data.data = data.data.transpose(0, 3, 1, 2)
                else:
                    raise TypeError("Invalid dimensions for image data. Dim = %s"
                                    % str(data.shape))

        # Actual transformation.
        if self.flag_gpu:
            data.to_gpu()
        z = self._encode(data, test=test)[0]

        z.to_cpu()

        return z.data

Response: Transform image data to latent space.


Instruction:
How would you code a function in Python 3 to
fit the VAE model to the image data.

Response:
def fit(
        self,
        img_data,
        gamma=1.0,
        save_freq=-1,
        pic_freq=-1,
        n_epochs=100,
        batch_size=50,
        weight_decay=True,
        model_path='./VAEGAN_training_model/',
        img_path='./VAEGAN_training_images/',
        img_out_width=10,
        mirroring=False
    ):
        '''Fit the VAE/GAN model to the image data.

        Parameters
        ----------

        img_data : array-like shape (n_images, n_colors, image_width, image_height)
            Images used to fit VAE model.
        gamma [optional] : float
            Sets the multiplicative factor that weights the relative importance of
            reconstruction loss vs. ability to fool the discriminator. Higher weight
            means greater focus on faithful reconstruction.
        save_freq [optional] : int
            Sets the number of epochs to wait before saving the model and optimizer states.
            Also saves image files of randomly generated images using those states in a
            separate directory. Does not save if negative valued.
        pic_freq [optional] : int
            Sets the number of batches to wait before displaying a picture or randomly
            generated images using the current model state.
            Does not display if negative valued.
        n_epochs [optional] : int
            Gives the number of training epochs to run through for the fitting
            process.
        batch_size [optional] : int
            The size of the batch to use when training. Note: generally larger
            batch sizes will result in fater epoch iteration, but at the const
            of lower granulatity when updating the layer weights.
        weight_decay [optional] : bool
            Flag that controls adding weight decay hooks to the optimizer.
        model_path [optional] : str
            Directory where the model and optimizer state files will be saved.
        img_path [optional] : str
            Directory where the end of epoch training image files will be saved.
        img_out_width : int
            Controls the number of randomly genreated images per row in the output
            saved imags.
        mirroring [optional] : bool
            Controls whether images are randomly mirrored along the verical axis with
            a .5 probability. Artificially increases images variance for training set.
        '''
        width = img_out_width
        self.enc_opt.setup(self.enc)
        self.dec_opt.setup(self.dec)
        self.disc_opt.setup(self.disc)

        if weight_decay:
            self.enc_opt.add_hook(chainer.optimizer.WeightDecay(0.00001))
            self.dec_opt.add_hook(chainer.optimizer.WeightDecay(0.00001))
            self.disc_opt.add_hook(chainer.optimizer.WeightDecay(0.00001))

        n_data = img_data.shape[0]

        batch_iter = list(range(0, n_data, batch_size))
        n_batches = len(batch_iter)

        c_samples = np.random.standard_normal((width, self.latent_width)).astype(np.float32)
        save_counter = 0

        for epoch in range(1, n_epochs + 1):
            print('epoch: %i' % epoch)
            t1 = time.time()
            indexes = np.random.permutation(n_data)
            sum_l_enc = 0.
            sum_l_dec = 0.
            sum_l_disc = 0.

            sum_l_gan = 0.
            sum_l_like = 0.
            sum_l_prior = 0.
            count = 0
            for i in tqdm.tqdm(batch_iter):
                x = img_data[indexes[i: i + batch_size]]
                size = x.shape[0]
                if mirroring:
                    for j in range(size):
                        if np.random.randint(2):
                            x[j, :, :, :] = x[j, :, :, ::-1]
                x_batch = Variable(x)
                zeros = Variable(np.zeros(size, dtype=np.int32))
                ones = Variable(np.ones(size, dtype=np.int32))

                if self.flag_gpu:
                    x_batch.to_gpu()
                    zeros.to_gpu()
                    ones.to_gpu()

                kl_loss, dif_l, disc_rec, disc_batch, disc_samp = self._forward(x_batch)

                L_batch_GAN = F.softmax_cross_entropy(disc_batch, ones)
                L_rec_GAN = F.softmax_cross_entropy(disc_rec, zeros)
                L_samp_GAN = F.softmax_cross_entropy(disc_samp, zeros)

                l_gan = (L_batch_GAN + L_rec_GAN + L_samp_GAN)/3.
                l_like = dif_l
                l_prior = kl_loss

                enc_loss = self.kl_ratio*l_prior + l_like
                dec_loss = gamma*l_like - l_gan
                disc_loss = l_gan

                self.enc_opt.zero_grads()
                enc_loss.backward()
                self.enc_opt.update()

                self.dec_opt.zero_grads()
                dec_loss.backward()
                self.dec_opt.update()

                self.disc_opt.zero_grads()
                disc_loss.backward()
                self.disc_opt.update()

                sum_l_enc += enc_loss.data
                sum_l_dec += dec_loss.data
                sum_l_disc += disc_loss.data

                sum_l_gan += l_gan.data
                sum_l_like += l_like.data
                sum_l_prior += l_prior.data
                count += 1

                plot_data = img_data[indexes[:width]]
                if pic_freq > 0:
                    assert type(pic_freq) == int, "pic_freq must be an integer."
                    if count % pic_freq == 0:
                        fig = self._plot_img(
                            plot_data,
                            c_samples,
                            img_path=img_path,
                            epoch=epoch
                        )
                        display(fig)

            if save_freq > 0:
                save_counter += 1
                assert type(save_freq) == int, "save_freq must be an integer."
                if epoch % save_freq == 0:
                    name = "vaegan_epoch%s" % str(epoch)
                    if save_counter == 1:
                        save_meta = True
                    else:
                        save_meta = False
                    self.save(model_path, name, save_meta=save_meta)
                    fig = self._plot_img(
                        plot_data,
                        c_samples,
                        img_path=img_path,
                        epoch=epoch,
                        batch=n_batches,
                        save_pic=True
                        )
            sum_l_enc /= n_batches
            sum_l_dec /= n_batches
            sum_l_disc /= n_batches
            sum_l_gan /= n_batches
            sum_l_like /= n_batches
            sum_l_prior /= n_batches
            msg = "enc_loss = {0}, dec_loss = {1} , disc_loss = {2}"
            msg2 = "gan_loss = {0}, sim_loss = {1}, kl_loss = {2}"
            print(msg.format(sum_l_enc, sum_l_dec, sum_l_disc))
            print(msg2.format(sum_l_gan, sum_l_like, sum_l_prior))
            t_diff = time.time()-t1
            print("time: %f\n\n" % t_diff)


Instruction:
Here you have a function in Python 3, explain what it does
def load(cls, enc, dec, disc, enc_opt, dec_opt, disc_opt, meta, flag_gpu=None):
        '''Loads in model as a class instance with with the specified
           model and optimizer states.

        Parameters
        ----------
        enc : str
            Path to the encoder state file.
        dec : str
            Path to the decoder/generator state file.
        disc : str
            Path to the discriminator state file.
        enc_opt : str
            Path to the encoder optimizer state file.
        dec_opt : str
            Path to the decoder/generator optimizer state file.
        disc_opt : str
            Path to the discriminator optimizer state file.
        meta : str
            Path to the class metadata state file.
        flag_gpu : bool
            Specifies whether to load the model to use gpu capabilities.

        Returns
        -------

        class instance of self.
        '''
        mess = "Model file {0} does not exist. Please check the file path."
        assert os.path.exists(enc), mess.format(enc)
        assert os.path.exists(dec), mess.format(dec)
        assert os.path.exists(disc), mess.format(disc)
        assert os.path.exists(dec_opt), mess.format(dec_opt)
        assert os.path.exists(disc_opt), mess.format(disc_opt)
        assert os.path.exists(meta), mess.format(meta)
        with open(meta, 'r') as f:
            meta = json.load(f)
        if flag_gpu is not None:
            meta['flag_gpu'] = flag_gpu

        loaded_class = cls(**meta)

        serializers.load_hdf5(enc, loaded_class.enc)
        serializers.load_hdf5(dec, loaded_class.dec)
        serializers.load_hdf5(disc, loaded_class.disc)
        loaded_class.enc_opt.setup(loaded_class.enc)
        loaded_class.dec_opt.setup(loaded_class.dec)
        loaded_class.disc_opt.setup(loaded_class.disc)
        serializers.load_hdf5(enc_opt, loaded_class.enc_opt)
        serializers.load_hdf5(dec_opt, loaded_class.dec_opt)
        serializers.load_hdf5(disc_opt, loaded_class.disc_opt)

        if meta['flag_gpu']:
            loaded_class.enc.to_gpu()
            loaded_class.dec.to_gpu()
            loaded_class.disc.to_gpu()

        return loaded_class

Response:
Loads in model as a class instance with the specified
 model and optimizer states.


Instruction:
Can you tell what is the following Python 3 function doing
def quadratic_jacobian_polynomial(nodes):
    # First evaluate the Jacobian at each of the 6 nodes.
    jac_parts = _helpers.matrix_product(nodes, _QUADRATIC_JACOBIAN_HELPER)
    jac_at_nodes = np.empty((1, 6), order="F")
    jac_at_nodes[0, 0] = two_by_two_det(jac_parts[:, :2])
    jac_at_nodes[0, 1] = two_by_two_det(jac_parts[:, 2:4])
    jac_at_nodes[0, 2] = two_by_two_det(jac_parts[:, 4:6])
    jac_at_nodes[0, 3] = two_by_two_det(jac_parts[:, 6:8])
    jac_at_nodes[0, 4] = two_by_two_det(jac_parts[:, 8:10])
    jac_at_nodes[0, 5] = two_by_two_det(jac_parts[:, 10:])
    # Convert the nodal values to the Bernstein basis...
    bernstein = _helpers.matrix_product(jac_at_nodes, _QUADRATIC_TO_BERNSTEIN)
    return bernstein

Response: r Compute the Jacobian determinant of a quadratic surface.


Instruction:
Explain what the following Python 3 code does
def cubic_jacobian_polynomial(nodes):
    # First evaluate the Jacobian at each of the 15 nodes
    # in the quartic triangle.
    jac_parts = _helpers.matrix_product(nodes, _CUBIC_JACOBIAN_HELPER)
    jac_at_nodes = np.empty((1, 15), order="F")
    jac_at_nodes[0, 0] = two_by_two_det(jac_parts[:, :2])
    jac_at_nodes[0, 1] = two_by_two_det(jac_parts[:, 2:4])
    jac_at_nodes[0, 2] = two_by_two_det(jac_parts[:, 4:6])
    jac_at_nodes[0, 3] = two_by_two_det(jac_parts[:, 6:8])
    jac_at_nodes[0, 4] = two_by_two_det(jac_parts[:, 8:10])
    jac_at_nodes[0, 5] = two_by_two_det(jac_parts[:, 10:12])
    jac_at_nodes[0, 6] = two_by_two_det(jac_parts[:, 12:14])
    jac_at_nodes[0, 7] = two_by_two_det(jac_parts[:, 14:16])
    jac_at_nodes[0, 8] = two_by_two_det(jac_parts[:, 16:18])
    jac_at_nodes[0, 9] = two_by_two_det(jac_parts[:, 18:20])
    jac_at_nodes[0, 10] = two_by_two_det(jac_parts[:, 20:22])
    jac_at_nodes[0, 11] = two_by_two_det(jac_parts[:, 22:24])
    jac_at_nodes[0, 12] = two_by_two_det(jac_parts[:, 24:26])
    jac_at_nodes[0, 13] = two_by_two_det(jac_parts[:, 26:28])
    jac_at_nodes[0, 14] = two_by_two_det(jac_parts[:, 28:])
    # Convert the nodal values to the Bernstein basis...
    bernstein = _helpers.matrix_product(jac_at_nodes, _QUARTIC_TO_BERNSTEIN)
    bernstein /= _QUARTIC_BERNSTEIN_FACTOR
    return bernstein

Response: r Compute the Jacobian determinant of a cubic surface.


Instruction:
Explain what the following Python 3 code does
def _de_casteljau_one_round(nodes, degree, lambda1, lambda2, lambda3):
    dimension, num_nodes = nodes.shape
    num_new_nodes = num_nodes - degree - 1
    new_nodes = np.empty((dimension, num_new_nodes), order="F")
    index = 0
    # parent_i1 = index + k
    # parent_i2 = index + k + 1
    # parent_i3 = index + degree + 1
    parent_i1 = 0
    parent_i2 = 1
    parent_i3 = degree + 1
    for k in six.moves.xrange(degree):
        for unused_j in six.moves.xrange(degree - k):
            # NOTE: i = (degree - 1) - j - k
            new_nodes[:, index] = (
                lambda1 * nodes[:, parent_i1]
                + lambda2 * nodes[:, parent_i2]
                + lambda3 * nodes[:, parent_i3]
            )
            # Update all the indices.
            parent_i1 += 1
            parent_i2 += 1
            parent_i3 += 1
            index += 1
        # Update the indices that depend on k.
        parent_i1 += 1
        parent_i2 += 1
    return new_nodes

Response: r Performs one round of the de Casteljau algorithm for surfaces.


Instruction:
Can you tell what is the following Python 3 function doing
def make_transform(degree, weights_a, weights_b, weights_c):
    num_nodes = ((degree + 1) * (degree + 2)) // 2
    id_mat = np.eye(num_nodes, order="F")
    # Pre-compute the matrices that do the reduction so we don't
    # have to **actually** perform the de Casteljau algorithm
    # every time.
    transform = {
        0: de_casteljau_one_round(id_mat, degree, *weights_a),
        1: de_casteljau_one_round(id_mat, degree, *weights_b),
        2: de_casteljau_one_round(id_mat, degree, *weights_c),
    }
    return transform

Response: Compute the matrix that computes the de Casteljau algorithm for the given degree.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def reduced_to_matrix(shape, degree, vals_by_weight):
    result = np.empty(shape, order="F")
    index = 0
    for k in six.moves.xrange(degree + 1):
        for j in six.moves.xrange(degree + 1 - k):
            i = degree - j - k
            key = (0,) * i + (1,) * j + (2,) * k
            result[:, index] = vals_by_weight[key][:, 0]
            index += 1
    return result

Response: r Converts a reduced values dictionary into a matrix.


Instruction:
Make a summary of the following Python 3 code
def _specialize_surface(nodes, degree, weights_a, weights_b, weights_c):
    # Uses A-->0, B-->1, C-->2 to represent the specialization used.
    partial_vals = {
        (0,): de_casteljau_one_round(nodes, degree, *weights_a),
        (1,): de_casteljau_one_round(nodes, degree, *weights_b),
        (2,): de_casteljau_one_round(nodes, degree, *weights_c),
    }
    for reduced_deg in six.moves.xrange(degree - 1, 0, -1):
        new_partial = {}
        transform = make_transform(
            reduced_deg, weights_a, weights_b, weights_c
        )
        for key, sub_nodes in six.iteritems(partial_vals):
            # Our keys are ascending so we increment from the last value.
            for next_id in six.moves.xrange(key[-1], 2 + 1):
                new_key = key + (next_id,)
                new_partial[new_key] = _helpers.matrix_product(
                    sub_nodes, transform[next_id]
                )
        partial_vals = new_partial
    return reduced_to_matrix(nodes.shape, degree, partial_vals)

Response: Specialize a surface to a specialization.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _subdivide_nodes(nodes, degree):
    if degree == 1:
        nodes_a = _helpers.matrix_product(nodes, LINEAR_SUBDIVIDE_A)
        nodes_b = _helpers.matrix_product(nodes, LINEAR_SUBDIVIDE_B)
        nodes_c = _helpers.matrix_product(nodes, LINEAR_SUBDIVIDE_C)
        nodes_d = _helpers.matrix_product(nodes, LINEAR_SUBDIVIDE_D)
    elif degree == 2:
        nodes_a = _helpers.matrix_product(nodes, QUADRATIC_SUBDIVIDE_A)
        nodes_b = _helpers.matrix_product(nodes, QUADRATIC_SUBDIVIDE_B)
        nodes_c = _helpers.matrix_product(nodes, QUADRATIC_SUBDIVIDE_C)
        nodes_d = _helpers.matrix_product(nodes, QUADRATIC_SUBDIVIDE_D)
    elif degree == 3:
        nodes_a = _helpers.matrix_product(nodes, CUBIC_SUBDIVIDE_A)
        nodes_b = _helpers.matrix_product(nodes, CUBIC_SUBDIVIDE_B)
        nodes_c = _helpers.matrix_product(nodes, CUBIC_SUBDIVIDE_C)
        nodes_d = _helpers.matrix_product(nodes, CUBIC_SUBDIVIDE_D)
    elif degree == 4:
        nodes_a = _helpers.matrix_product(nodes, QUARTIC_SUBDIVIDE_A)
        nodes_b = _helpers.matrix_product(nodes, QUARTIC_SUBDIVIDE_B)
        nodes_c = _helpers.matrix_product(nodes, QUARTIC_SUBDIVIDE_C)
        nodes_d = _helpers.matrix_product(nodes, QUARTIC_SUBDIVIDE_D)
    else:
        nodes_a = specialize_surface(
            nodes,
            degree,
            _WEIGHTS_SUBDIVIDE0,
            _WEIGHTS_SUBDIVIDE1,
            _WEIGHTS_SUBDIVIDE2,
        )
        nodes_b = specialize_surface(
            nodes,
            degree,
            _WEIGHTS_SUBDIVIDE3,
            _WEIGHTS_SUBDIVIDE2,
            _WEIGHTS_SUBDIVIDE1,
        )
        nodes_c = specialize_surface(
            nodes,
            degree,
            _WEIGHTS_SUBDIVIDE1,
            _WEIGHTS_SUBDIVIDE4,
            _WEIGHTS_SUBDIVIDE3,
        )
        nodes_d = specialize_surface(
            nodes,
            degree,
            _WEIGHTS_SUBDIVIDE2,
            _WEIGHTS_SUBDIVIDE3,
            _WEIGHTS_SUBDIVIDE5,
        )
    return nodes_a, nodes_b, nodes_c, nodes_d

Response: Subdivides a surface into four sub - surfaces.


Instruction:
Here you have a function in Python 3, explain what it does
def _jacobian_both(nodes, degree, dimension):
    _, num_nodes = nodes.shape
    result = np.empty((2 * dimension, num_nodes - degree - 1), order="F")
    result[:dimension, :] = jacobian_s(nodes, degree, dimension)
    result[dimension:, :] = jacobian_t(nodes, degree, dimension)
    return result

Response: r Compute s and t partial of a Jacobian surfaces in a resource set.


Instruction:
Here you have a function in Python 3, explain what it does
def classify_tangent_intersection(
    intersection, nodes1, tangent1, nodes2, tangent2
):
    """Helper for func:`classify_intersection` at tangencies.

    .. note::

       This is a helper used only by :func:`classify_intersection`.

    Args:
        intersection (.Intersection): An intersection object.
        nodes1 (numpy.ndarray): Control points for the first curve at
            the intersection.
        tangent1 (numpy.ndarray): The tangent vector to the first curve
            at the intersection (``2 x 1`` array).
        nodes2 (numpy.ndarray): Control points for the second curve at
            the intersection.
        tangent2 (numpy.ndarray): The tangent vector to the second curve
            at the intersection (``2 x 1`` array).

    Returns:
        IntersectionClassification: The "inside" curve type, based on
        the classification enum. Will either be ``opposed`` or one
        of the ``tangent`` values.

    Raises:
        NotImplementedError: If the curves are tangent at the intersection
            and have the same curvature.
    """
    # Each array is 2 x 1 (i.e. a column vector), we want the vector
    # dot product.
    dot_prod = np.vdot(tangent1[:, 0], tangent2[:, 0])
    # NOTE: When computing curvatures we assume that we don't have lines
    #       here, because lines that are tangent at an intersection are
    #       parallel and we don't handle that case.
    curvature1 = _curve_helpers.get_curvature(nodes1, tangent1, intersection.s)
    curvature2 = _curve_helpers.get_curvature(nodes2, tangent2, intersection.t)
    if dot_prod < 0:
        # If the tangent vectors are pointing in the opposite direction,
        # then the curves are facing opposite directions.
        sign1, sign2 = _SIGN([curvature1, curvature2])
        if sign1 == sign2:
            # If both curvatures are positive, since the curves are
            # moving in opposite directions, the tangency isn't part of
            # the surface intersection.
            if sign1 == 1.0:
                return CLASSIFICATION_T.OPPOSED

            else:
                return CLASSIFICATION_T.TANGENT_BOTH

        else:
            delta_c = abs(curvature1) - abs(curvature2)
            if delta_c == 0.0:
                raise NotImplementedError(_SAME_CURVATURE)

            elif sign1 == _SIGN(delta_c):
                return CLASSIFICATION_T.OPPOSED

            else:
                return CLASSIFICATION_T.TANGENT_BOTH

    else:
        if curvature1 > curvature2:
            return CLASSIFICATION_T.TANGENT_FIRST

        elif curvature1 < curvature2:
            return CLASSIFICATION_T.TANGENT_SECOND

        else:
            raise NotImplementedError(_SAME_CURVATURE)

Response: This function returns the intersection class for the tangent curves at the given tangent vectors.


Instruction:
How would you explain what the following Python 3 function does
def ignored_edge_corner(edge_tangent, corner_tangent, corner_previous_edge):
    cross_prod = _helpers.cross_product(
        edge_tangent.ravel(order="F"), corner_tangent.ravel(order="F")
    )
    # A negative cross product indicates that ``edge_tangent`` is
    # "inside" / "to the left" of ``corner_tangent`` (due to right-hand rule).
    if cross_prod > 0.0:
        return False

    # Do the same for the **other** tangent at the corner.
    alt_corner_tangent = _curve_helpers.evaluate_hodograph(
        1.0, corner_previous_edge
    )
    # Change the direction of the "in" tangent so that it points "out".
    alt_corner_tangent *= -1.0
    cross_prod = _helpers.cross_product(
        edge_tangent.ravel(order="F"), alt_corner_tangent.ravel(order="F")
    )
    return cross_prod <= 0.0

Response: Check if an edge lies inside another edge.


Instruction:
How would you code a function in Python 3 to
check if an intersection is an ignored double corner.

Response:
def ignored_double_corner(
    intersection, tangent_s, tangent_t, edge_nodes1, edge_nodes2
):
    """Check if an intersection is an "ignored" double corner.

    .. note::

       This is a helper used only by :func:`ignored_corner`, which in turn is
       only used by :func:`classify_intersection`.

    Helper for :func:`ignored_corner` where both ``s`` and
    ``t`` are ``0``.

    Does so by checking if either edge through the ``t`` corner goes
    through the interior of the other surface. An interior check
    is done by checking that a few cross products are positive.

    Args:
        intersection (.Intersection): An intersection to "diagnose".
        tangent_s (numpy.ndarray): The tangent vector (``2 x 1`` array) to
            the first curve at the intersection.
        tangent_t (numpy.ndarray): The tangent vector (``2 x 1`` array) to
            the second curve at the intersection.
        edge_nodes1 (Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]): The
            nodes of the three edges of the first surface being intersected.
        edge_nodes2 (Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]): The
            nodes of the three edges of the second surface being intersected.

    Returns:
        bool: Indicates if the corner is to be ignored.
    """
    # Compute the other edge for the ``s`` surface.
    prev_index = (intersection.index_first - 1) % 3
    prev_edge = edge_nodes1[prev_index]
    alt_tangent_s = _curve_helpers.evaluate_hodograph(1.0, prev_edge)
    # First check if ``tangent_t`` is interior to the ``s`` surface.
    cross_prod1 = _helpers.cross_product(
        tangent_s.ravel(order="F"), tangent_t.ravel(order="F")
    )
    # A positive cross product indicates that ``tangent_t`` is
    # interior to ``tangent_s``. Similar for ``alt_tangent_s``.
    # If ``tangent_t`` is interior to both, then the surfaces
    # do more than just "kiss" at the corner, so the corner should
    # not be ignored.
    if cross_prod1 >= 0.0:
        # Only compute ``cross_prod2`` if we need to.
        cross_prod2 = _helpers.cross_product(
            alt_tangent_s.ravel(order="F"), tangent_t.ravel(order="F")
        )
        if cross_prod2 >= 0.0:
            return False

    # If ``tangent_t`` is not interior, we check the other ``t``
    # edge that ends at the corner.
    prev_index = (intersection.index_second - 1) % 3
    prev_edge = edge_nodes2[prev_index]
    alt_tangent_t = _curve_helpers.evaluate_hodograph(1.0, prev_edge)
    # Change the direction of the "in" tangent so that it points "out".
    alt_tangent_t *= -1.0
    cross_prod3 = _helpers.cross_product(
        tangent_s.ravel(order="F"), alt_tangent_t.ravel(order="F")
    )
    if cross_prod3 >= 0.0:
        # Only compute ``cross_prod4`` if we need to.
        cross_prod4 = _helpers.cross_product(
            alt_tangent_s.ravel(order="F"), alt_tangent_t.ravel(order="F")
        )
        if cross_prod4 >= 0.0:
            return False

    # If neither of ``tangent_t`` or ``alt_tangent_t`` are interior
    # to the ``s`` surface, one of two things is true. Either
    # the two surfaces have no interior intersection (1) or the
    # ``s`` surface is bounded by both edges of the ``t`` surface
    # at the corner intersection (2). To detect (2), we only need
    # check if ``tangent_s`` is interior to both ``tangent_t``
    # and ``alt_tangent_t``. ``cross_prod1`` contains
    # (tangent_s) x (tangent_t), so it's negative will tell if
    # ``tangent_s`` is interior. Similarly, ``cross_prod3``
    # contains (tangent_s) x (alt_tangent_t), but we also reversed
    # the sign on ``alt_tangent_t`` so switching the sign back
    # and reversing the arguments in the cross product cancel out.
    return cross_prod1 > 0.0 or cross_prod3 < 0.0


Instruction:
Make a summary of the following Python 3 code
def ignored_corner(
    intersection, tangent_s, tangent_t, edge_nodes1, edge_nodes2
):
    """Check if an intersection is an "ignored" corner.

    .. note::

       This is a helper used only by :func:`classify_intersection`.

    An "ignored" corner is one where the surfaces just "kiss" at
    the point of intersection but their interiors do not meet.

    We can determine this by comparing the tangent lines from
    the point of intersection.

    .. note::

       This assumes the ``intersection`` has been shifted to the
       beginning of a curve so only checks if ``s == 0.0`` or ``t == 0.0``
       (rather than also checking for ``1.0``).

    Args:
        intersection (.Intersection): An intersection to "diagnose".
        tangent_s (numpy.ndarray): The tangent vector (``2 x 1`` array) to
            the first curve at the intersection.
        tangent_t (numpy.ndarray): The tangent vector (``2 x 1`` array) to
            the second curve at the intersection.
        edge_nodes1 (Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]): The
            nodes of the three edges of the first surface being intersected.
        edge_nodes2 (Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]): The
            nodes of the three edges of the second surface being intersected.

    Returns:
        bool: Indicates if the corner is to be ignored.
    """
    if intersection.s == 0.0:
        if intersection.t == 0.0:
            # Double corner.
            return ignored_double_corner(
                intersection, tangent_s, tangent_t, edge_nodes1, edge_nodes2
            )

        else:
            # s-only corner.
            prev_index = (intersection.index_first - 1) % 3
            prev_edge = edge_nodes1[prev_index]
            return ignored_edge_corner(tangent_t, tangent_s, prev_edge)

    elif intersection.t == 0.0:
        # t-only corner.
        prev_index = (intersection.index_second - 1) % 3
        prev_edge = edge_nodes2[prev_index]
        return ignored_edge_corner(tangent_s, tangent_t, prev_edge)

    else:
        # Not a corner.
        return False

Response: Check if an intersection is an ignored corner.


Instruction:
Given the following Python 3 function, write the documentation
def handle_ends(index1, s, index2, t):
    edge_end = False
    if s == 1.0:
        s = 0.0
        index1 = (index1 + 1) % 3
        edge_end = True
    # NOTE: This is not a typo, the values can be updated twice if both ``s``
    #       and ``t`` are ``1.0``
    if t == 1.0:
        t = 0.0
        index2 = (index2 + 1) % 3
        edge_end = True
    is_corner = s == 0.0 or t == 0.0
    return edge_end, is_corner, (index1, s, index2, t)

Response: This function handles the end of an intersection between two nodes.


Instruction:
Can you generate the documentation for the following Python 3 function
def to_front(intersection, intersections, unused):
    if intersection.s == 1.0:
        next_index = (intersection.index_first + 1) % 3
        # Make sure we haven't accidentally ignored an existing intersection.
        for other_int in intersections:
            if other_int.s == 0.0 and other_int.index_first == next_index:
                if other_int in unused:
                    unused.remove(other_int)
                return other_int

        # If we haven't already returned, create **another** artificial
        # intersection.
        return _intersection_helpers.Intersection(
            next_index, 0.0, None, None, interior_curve=CLASSIFICATION_T.FIRST
        )

    elif intersection.t == 1.0:
        # NOTE: We assume, but do not check, that ``s == 1.0`` and ``t == 1.0``
        #       are mutually exclusive.
        next_index = (intersection.index_second + 1) % 3
        # Make sure we haven't accidentally ignored an existing intersection.
        for other_int in intersections:
            if other_int.t == 0.0 and other_int.index_second == next_index:
                if other_int in unused:
                    unused.remove(other_int)
                return other_int

        # If we haven't already returned, create **another** artificial
        # intersection.
        return _intersection_helpers.Intersection(
            None, None, next_index, 0.0, interior_curve=CLASSIFICATION_T.SECOND
        )

    else:
        return intersection

Response: Rotates a node to the front.


Instruction:
Explain what the following Python 3 code does
def get_next_first(intersection, intersections, to_end=True):
    along_edge = None
    index_first = intersection.index_first
    s = intersection.s
    for other_int in intersections:
        other_s = other_int.s
        if other_int.index_first == index_first and other_s > s:
            if along_edge is None or other_s < along_edge.s:
                along_edge = other_int
    if along_edge is None:
        if to_end:
            # If there is no other intersection on the edge, just return
            # the segment end.
            return _intersection_helpers.Intersection(
                index_first,
                1.0,
                None,
                None,
                interior_curve=CLASSIFICATION_T.FIRST,
            )

        else:
            return None

    else:
        return along_edge

Response: Gets the next node along the current edge.


Instruction:
Implement a function in Python 3 to
get the next node along the current edge.

Response:
def get_next_second(intersection, intersections, to_end=True):
    """Gets the next node along the current (second) edge.

    .. note::

       This is a helper used only by :func:`get_next`, which in
       turn is only used by :func:`basic_interior_combine`, which itself
       is only used by :func:`combine_intersections`.

    Along with :func:`get_next_first`, this function does the majority of the
    heavy lifting in :func:`get_next`. **Very** similar to
    :func:`get_next_first`, but this works with the second curve while the
    other function works with the first.

    Args:
        intersection (.Intersection): The current intersection.
        intersections (List[.Intersection]): List of all detected
            intersections, provided as a reference for potential
            points to arrive at.
        to_end (Optional[bool]): Indicates if the next node should just be
            the end of the first edge or :data:`None`.

    Returns:
        Optional[.Intersection]: The "next" point along a surface of
        intersection. This will produce the next intersection along the
        current (second) edge or the end of the same edge. If ``to_end`` is
        :data:`False` and there are no other intersections along the current
        edge, will return :data:`None` (rather than the end of the same edge).
    """
    along_edge = None
    index_second = intersection.index_second
    t = intersection.t
    for other_int in intersections:
        other_t = other_int.t
        if other_int.index_second == index_second and other_t > t:
            if along_edge is None or other_t < along_edge.t:
                along_edge = other_int
    if along_edge is None:
        if to_end:
            # If there is no other intersection on the edge, just return
            # the segment end.
            return _intersection_helpers.Intersection(
                None,
                None,
                index_second,
                1.0,
                interior_curve=CLASSIFICATION_T.SECOND,
            )

        else:
            return None

    else:
        return along_edge


Instruction:
Can you implement a function in Python 3 that
gets the next node along the current edge.

Response:
def get_next_coincident(intersection, intersections):
    """Gets the next node along the current (coincident) edge.

    .. note::

       This is a helper used only by :func:`get_next`, which in
       turn is only used by :func:`basic_interior_combine`, which itself
       is only used by :func:`combine_intersections`.

    Along with :func:`get_next_first` and :func:`get_next_second`, this
    function does the majority of the heavy lifting in :func:`get_next`.

    This function moves immediately to the "next" intersection along the
    "current" edge. An intersection labeled as ``COINCIDENT`` can only occur
    at the beginning of a segment. The end will correspond to the ``s`` or
    ``t`` parameter being equal to ``1.0`` and so it will get "rotated"
    to the front of the next edge, where it will be classified according
    to a different edge pair.

    It's also worth noting that some coincident segments will correspond
    to curves moving in opposite directions. In that case, there is
    no "interior" intersection (the curves are facing away) and so that
    segment won't be part of an intersection.

    Args:
        intersection (.Intersection): The current intersection.
        intersections (List[.Intersection]): List of all detected
            intersections, provided as a reference for potential
            points to arrive at.

    Returns:
        .Intersection: The "next" point along a surface of intersection.
        This will produce the next intersection along the current (second)
        edge or the end of the same edge.
    """
    # Moving along the first or second edge will produce the same result, but
    # since we "rotate" all intersections to the beginning of an edge, the
    # index may not match the first or second (or both).
    along_first = get_next_first(intersection, intersections, to_end=False)
    if along_first is None:
        along_second = get_next_second(
            intersection, intersections, to_end=False
        )
    else:
        return along_first

    if along_second is None:
        return _intersection_helpers.Intersection(
            intersection.index_first,
            1.0,
            intersection.index_second,
            1.0,
            interior_curve=CLASSIFICATION_T.COINCIDENT,
        )

    else:
        return along_second


Instruction:
Given the following Python 3 function, write the documentation
def get_next(intersection, intersections, unused):
    result = None
    if is_first(intersection.interior_curve):
        result = get_next_first(intersection, intersections)
    elif is_second(intersection.interior_curve):
        result = get_next_second(intersection, intersections)
    elif intersection.interior_curve == CLASSIFICATION_T.COINCIDENT:
        result = get_next_coincident(intersection, intersections)
    else:
        raise ValueError(
            'Cannot get next node if not starting from "FIRST", '
            '"TANGENT_FIRST", "SECOND", "TANGENT_SECOND" or "COINCIDENT".'
        )

    if result in unused:
        unused.remove(result)
    return result

Response: Gets the next node along a given edge.


Instruction:
Can you write a function in Python 3 where it
converts a pair of intersection nodes to a base curve segment.

Response:
def ends_to_curve(start_node, end_node):
    """Convert a "pair" of intersection nodes to a curve segment.

    .. note::

       This is a helper used only by :func:`basic_interior_combine`, which in
       turn is only used by :func:`combine_intersections`.

    .. note::

       This function could specialize to the first or second segment
       attached to ``start_node`` and ``end_node``. We determine
       first / second based on the classification of ``start_node``,
       but the callers of this function could provide that information /
       isolate the base curve and the two parameters for us.

    .. note::

       This only checks the classification of the ``start_node``.

    Args:
        start_node (.Intersection): The beginning of a segment.
        end_node (.Intersection): The end of (the same) segment.

    Returns:
        Tuple[int, float, float]: The 3-tuple of:

        * The edge index along the first surface (if in ``{0, 1, 2}``)
          or the edge index along the second surface shifted to the right by
          3 (if in ``{3, 4, 5}``)
        * The start parameter along the edge
        * The end parameter along the edge

    Raises:
        ValueError: If the ``start_node`` and ``end_node`` disagree on
            the first curve when classified as "FIRST".
        ValueError: If the ``start_node`` and ``end_node`` disagree on
            the second curve when classified as "SECOND".
        ValueError: If the ``start_node`` and ``end_node`` disagree on
            the both curves when classified as "COINCIDENT".
        ValueError: If the ``start_node`` is not classified as
            :attr:`~.IntersectionClassification.FIRST`,
            :attr:`~.IntersectionClassification.TANGENT_FIRST`,
            :attr:`~.IntersectionClassification.SECOND`,
            :attr:`~.IntersectionClassification.TANGENT_SECOND` or
            :attr:`~.IntersectionClassification.COINCIDENT`.
    """
    if is_first(start_node.interior_curve):
        if end_node.index_first != start_node.index_first:
            raise ValueError(_WRONG_CURVE)

        return start_node.index_first, start_node.s, end_node.s

    elif is_second(start_node.interior_curve):
        if end_node.index_second != start_node.index_second:
            raise ValueError(_WRONG_CURVE)

        return start_node.index_second + 3, start_node.t, end_node.t

    elif start_node.interior_curve == CLASSIFICATION_T.COINCIDENT:
        if end_node.index_first == start_node.index_first:
            return start_node.index_first, start_node.s, end_node.s

        elif end_node.index_second == start_node.index_second:
            return start_node.index_second + 3, start_node.t, end_node.t

        else:
            raise ValueError(_WRONG_CURVE)

    else:
        raise ValueError(
            'Segment start must be classified as "FIRST", "TANGENT_FIRST", '
            '"SECOND", "TANGENT_SECOND" or "COINCIDENT".'
        )


Instruction:
Can you generate a brief explanation for the following Python 3 code
def no_intersections(nodes1, degree1, nodes2, degree2):
    # NOTE: This is a circular import.
    from bezier import _surface_intersection

    located = _surface_intersection.locate_point(
        nodes2, degree2, nodes1[0, 0], nodes1[1, 0]
    )
    if located is not None:
        return None, True

    located = _surface_intersection.locate_point(
        nodes1, degree1, nodes2[0, 0], nodes2[1, 0]
    )
    if located is not None:
        return None, False

    return [], None

Response: r Determine if one surface is in the other.


Instruction:
Make a summary of the following Python 3 code
def tangent_only_intersections(all_types):
    if len(all_types) != 1:
        raise ValueError("Unexpected value, types should all match", all_types)

    point_type = all_types.pop()
    if point_type == CLASSIFICATION_T.OPPOSED:
        return [], None

    elif point_type == CLASSIFICATION_T.IGNORED_CORNER:
        return [], None

    elif point_type == CLASSIFICATION_T.TANGENT_FIRST:
        return None, True

    elif point_type == CLASSIFICATION_T.TANGENT_SECOND:
        return None, False

    elif point_type == CLASSIFICATION_T.COINCIDENT_UNUSED:
        return [], None

    else:
        raise ValueError("Point type not for tangency", point_type)

Response: Determine intersection in the case of only - tangent intersections.


Instruction:
Can you tell what is the following Python 3 function doing
def basic_interior_combine(intersections, max_edges=10):
    unused = intersections[:]
    result = []
    while unused:
        start = unused.pop()
        curr_node = start
        next_node = get_next(curr_node, intersections, unused)
        edge_ends = [(curr_node, next_node)]
        while next_node is not start:
            curr_node = to_front(next_node, intersections, unused)
            # NOTE: We also check to break when moving a corner node
            #       to the front. This is because ``intersections``
            #       de-duplicates corners by selecting the one
            #       (of 2 or 4 choices) at the front of segment(s).
            if curr_node is start:
                break

            next_node = get_next(curr_node, intersections, unused)
            edge_ends.append((curr_node, next_node))
            if len(edge_ends) > max_edges:
                raise RuntimeError(
                    "Unexpected number of edges", len(edge_ends)
                )

        edge_info = tuple(
            ends_to_curve(start_node, end_node)
            for start_node, end_node in edge_ends
        )
        result.append(edge_info)
    if len(result) == 1:
        if result[0] in FIRST_SURFACE_INFO:
            return None, True

        elif result[0] in SECOND_SURFACE_INFO:
            return None, False

    return result, None

Response: Combine intersections that don t involve tangencies.


Instruction:
Here you have a function in Python 3, explain what it does
def combine_intersections(
    intersections, nodes1, degree1, nodes2, degree2, all_types
):
    r"""Combine curve-curve intersections into curved polygon(s).

    .. note::

       This is a helper used only by :meth:`.Surface.intersect`.

    Does so assuming each intersection lies on an edge of one of
    two :class:`.Surface`-s.

    .. note ::

       This assumes that each ``intersection`` has been classified via
       :func:`classify_intersection` and only the intersections classified
       as ``FIRST`` and ``SECOND`` were kept.

    Args:
        intersections (List[.Intersection]): Intersections from each of the
            9 edge-edge pairs from a surface-surface pairing.
        nodes1 (numpy.ndarray): The nodes defining the first surface in
            the intersection (assumed in :math:\mathbf{R}^2`).
        degree1 (int): The degree of the surface given by ``nodes1``.
        nodes2 (numpy.ndarray): The nodes defining the second surface in
            the intersection (assumed in :math:\mathbf{R}^2`).
        degree2 (int): The degree of the surface given by ``nodes2``.
        all_types (Set[.IntersectionClassification]): The set of all
            intersection classifications encountered among the intersections
            for the given surface-surface pair.

    Returns:
        Tuple[Optional[list], Optional[bool]]: Pair (2-tuple) of

        * List of "edge info" lists. Each list represents a curved polygon
          and contains 3-tuples of edge index, start and end (see the
          output of :func:`ends_to_curve`).
        * "Contained" boolean. If not :data:`None`, indicates
          that one of the surfaces is contained in the other.
    """
    if intersections:
        return basic_interior_combine(intersections)

    elif all_types:
        return tangent_only_intersections(all_types)

    else:
        return no_intersections(nodes1, degree1, nodes2, degree2)

Response: r Combine two curved polygons into one.


Instruction:
Can you tell what is the following Python 3 function doing
def _evaluate_barycentric(nodes, degree, lambda1, lambda2, lambda3):
    dimension, num_nodes = nodes.shape
    binom_val = 1.0
    result = np.zeros((dimension, 1), order="F")
    index = num_nodes - 1
    result[:, 0] += nodes[:, index]
    # curve evaluate_multi_barycentric() takes arrays.
    lambda1 = np.asfortranarray([lambda1])
    lambda2 = np.asfortranarray([lambda2])
    for k in six.moves.xrange(degree - 1, -1, -1):
        # We want to go from (d C (k + 1)) to (d C k).
        binom_val = (binom_val * (k + 1)) / (degree - k)
        index -= 1  # Step to last element in column.
        #     k = d - 1, d - 2, ...
        # d - k =     1,     2, ...
        # We know column k has (d - k + 1) elements.
        new_index = index - degree + k  # First element in column.
        col_nodes = nodes[:, new_index : index + 1]  # noqa: E203
        col_nodes = np.asfortranarray(col_nodes)
        col_result = _curve_helpers.evaluate_multi_barycentric(
            col_nodes, lambda1, lambda2
        )
        result *= lambda3
        result += binom_val * col_result
        # Update index for next iteration.
        index = new_index
    return result

Response: r Evaluates a point on a single barycentric surface.


Instruction:
Write a Python 3 script to
compute the nodes of each edge of a base class.

Response:
def _compute_edge_nodes(nodes, degree):
    """Compute the nodes of each edges of a surface.

    .. note::

       There is also a Fortran implementation of this function, which
       will be used if it can be built.

    Args:
        nodes (numpy.ndarray): Control point nodes that define the surface.
        degree (int): The degree of the surface define by ``nodes``.

    Returns:
        Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]: The nodes in
        the edges of the surface.
    """
    dimension, _ = np.shape(nodes)
    nodes1 = np.empty((dimension, degree + 1), order="F")
    nodes2 = np.empty((dimension, degree + 1), order="F")
    nodes3 = np.empty((dimension, degree + 1), order="F")
    curr2 = degree
    curr3 = -1
    for i in six.moves.xrange(degree + 1):
        nodes1[:, i] = nodes[:, i]
        nodes2[:, i] = nodes[:, curr2]
        nodes3[:, i] = nodes[:, curr3]
        # Update the indices.
        curr2 += degree - i
        curr3 -= i + 2
    return nodes1, nodes2, nodes3


Instruction:
Here you have a function in Python 3, explain what it does
def shoelace_for_area(nodes):
    _, num_nodes = nodes.shape
    if num_nodes == 2:
        shoelace = SHOELACE_LINEAR
        scale_factor = 2.0
    elif num_nodes == 3:
        shoelace = SHOELACE_QUADRATIC
        scale_factor = 6.0
    elif num_nodes == 4:
        shoelace = SHOELACE_CUBIC
        scale_factor = 20.0
    elif num_nodes == 5:
        shoelace = SHOELACE_QUARTIC
        scale_factor = 70.0
    else:
        raise _helpers.UnsupportedDegree(num_nodes - 1, supported=(1, 2, 3, 4))

    result = 0.0
    for multiplier, index1, index2 in shoelace:
        result += multiplier * (
            nodes[0, index1] * nodes[1, index2]
            - nodes[1, index1] * nodes[0, index2]
        )

    return result / scale_factor

Response: r Compute an auxiliary shoelace sum used to compute area.


Instruction:
Implement a function in Python 3 to
save an image to the docs images directory.

Response:
def save_image(figure, filename):
    """Save an image to the docs images directory.

    Args:
        filename (str): The name of the file (not containing
            directory info).
    """
    path = os.path.join(IMAGES_DIR, filename)
    figure.savefig(path, bbox_inches="tight")
    plt.close(figure)


Instruction:
Write a Python 3 function that can
fill out the columns of matrix with a series of points.

Response:
def stack1d(*points):
    """Fill out the columns of matrix with a series of points.

    This is because ``np.hstack()`` will just make another 1D vector
    out of them and ``np.vstack()`` will put them in the rows.

    Args:
        points (Tuple[numpy.ndarray, ...]): Tuple of 1D points (i.e.
            arrays with shape ``(2,)``.

    Returns:
        numpy.ndarray: The array with each point in ``points`` as its
        columns.
    """
    result = np.empty((2, len(points)), order="F")
    for index, point in enumerate(points):
        result[:, index] = point
    return result


Instruction:
Can you tell what is the following Python 3 function doing
def linearization_error(nodes):
    if NO_IMAGES:
        return

    curve = bezier.Curve.from_nodes(nodes)
    line = bezier.Curve.from_nodes(nodes[:, (0, -1)])
    midpoints = np.hstack([curve.evaluate(0.5), line.evaluate(0.5)])
    ax = curve.plot(256)
    line.plot(256, ax=ax)
    ax.plot(
        midpoints[0, :], midpoints[1, :], color="black", linestyle="dashed"
    )
    ax.axis("scaled")
    save_image(ax.figure, "linearization_error.png")

Response: Image for : func :. linearization_error docstring.


Instruction:
Write a Python 3 script to
image for : func :. newton_refine

Response:
def newton_refine1(s, new_s, curve1, t, new_t, curve2):
    """Image for :func:`.newton_refine` docstring."""
    if NO_IMAGES:
        return

    points = np.hstack([curve1.evaluate(s), curve2.evaluate(t)])
    points_new = np.hstack([curve1.evaluate(new_s), curve2.evaluate(new_t)])
    ax = curve1.plot(256)
    curve2.plot(256, ax=ax)
    ax.plot(
        points[0, :],
        points[1, :],
        color="black",
        linestyle="None",
        marker="o",
        markeredgewidth=1,
        markerfacecolor="None",
    )
    ax.plot(
        points_new[0, :],
        points_new[1, :],
        color="black",
        linestyle="None",
        marker="o",
    )
    ax.axis("scaled")
    save_image(ax.figure, "newton_refine1.png")


Instruction:
How would you explain what the following Python 3 function does
def newton_refine2(s_vals, curve1, curve2):
    if NO_IMAGES:
        return

    ax = curve1.plot(256)
    ax.lines[-1].zorder = 1
    curve2.plot(256, ax=ax)
    ax.lines[-1].zorder = 1
    points = curve1.evaluate_multi(np.asfortranarray(s_vals))
    colors = seaborn.dark_palette("blue", 5)
    ax.scatter(
        points[0, :], points[1, :], c=colors, s=20, alpha=0.75, zorder=2
    )
    ax.axis("scaled")
    ax.set_xlim(0.0, 1.0)
    ax.set_ylim(0.0, 1.0)
    save_image(ax.figure, "newton_refine2.png")

Response: Image for : func :. newton_refine


Instruction:
Can you generate the documentation for the following Python 3 function
def segment_intersection1(start0, end0, start1, end1, s):
    if NO_IMAGES:
        return

    line0 = bezier.Curve.from_nodes(stack1d(start0, end0))
    line1 = bezier.Curve.from_nodes(stack1d(start1, end1))
    ax = line0.plot(2)
    line1.plot(256, ax=ax)
    (x_val,), (y_val,) = line0.evaluate(s)
    ax.plot([x_val], [y_val], color="black", marker="o")
    ax.axis("scaled")
    save_image(ax.figure, "segment_intersection1.png")

Response: Image for : func :. segment_intersection


Instruction:
Given the following Python 3 function, write the documentation
def segment_intersection2(start0, end0, start1, end1):
    if NO_IMAGES:
        return

    line0 = bezier.Curve.from_nodes(stack1d(start0, end0))
    line1 = bezier.Curve.from_nodes(stack1d(start1, end1))
    ax = line0.plot(2)
    line1.plot(2, ax=ax)
    ax.axis("scaled")
    save_image(ax.figure, "segment_intersection2.png")

Response: Image for : func :. segment_intersection docstring.


Instruction:
Can you generate the documentation for the following Python 3 function
def helper_parallel_lines(start0, end0, start1, end1, filename):
    if NO_IMAGES:
        return

    figure = plt.figure()
    ax = figure.gca()
    points = stack1d(start0, end0, start1, end1)
    ax.plot(points[0, :2], points[1, :2], marker="o")
    ax.plot(points[0, 2:], points[1, 2:], marker="o")
    ax.axis("scaled")
    _plot_helpers.add_plot_boundary(ax)
    save_image(figure, filename)

Response: Image for parallel lines parameters docstring.


Instruction:
Can you implement a function in Python 3 that
images for : class. Curve docstring.

Response:
def curve_constructor(curve):
    """Image for :class`.Curve` docstring."""
    if NO_IMAGES:
        return

    ax = curve.plot(256)
    line = ax.lines[0]
    nodes = curve._nodes
    ax.plot(
        nodes[0, :], nodes[1, :], color="black", linestyle="None", marker="o"
    )
    add_patch(ax, nodes, line.get_color())
    ax.axis("scaled")
    ax.set_xlim(-0.125, 1.125)
    ax.set_ylim(-0.0625, 0.5625)
    save_image(ax.figure, "curve_constructor.png")


Instruction:
Given the following Python 3 function, write the documentation
def curve_evaluate(curve):
    if NO_IMAGES:
        return

    ax = curve.plot(256)
    points = curve.evaluate_multi(np.asfortranarray([0.75]))
    ax.plot(
        points[0, :], points[1, :], color="black", linestyle="None", marker="o"
    )
    ax.axis("scaled")
    ax.set_xlim(-0.125, 1.125)
    ax.set_ylim(-0.0625, 0.5625)
    save_image(ax.figure, "curve_evaluate.png")

Response: Image for : meth. Curve. evaluate docstring.


Instruction:
Explain what the following Python 3 code does
def curve_subdivide(curve, left, right):
    if NO_IMAGES:
        return

    figure = plt.figure()
    ax = figure.gca()
    add_patch(ax, curve._nodes, "gray")
    ax = left.plot(256, ax=ax)
    line = ax.lines[-1]
    add_patch(ax, left._nodes, line.get_color())
    right.plot(256, ax=ax)
    line = ax.lines[-1]
    add_patch(ax, right._nodes, line.get_color())
    ax.axis("scaled")
    ax.set_xlim(-0.125, 2.125)
    ax.set_ylim(-0.125, 3.125)
    save_image(ax.figure, "curve_subdivide.png")

Response: Image for : meth. Curve. subdivide docstring.


Instruction:
Can you write a function in Python 3 where it
images for : meth. Curve. intersect docstring.

Response:
def curve_intersect(curve1, curve2, s_vals):
    """Image for :meth`.Curve.intersect` docstring."""
    if NO_IMAGES:
        return

    ax = curve1.plot(256)
    curve2.plot(256, ax=ax)
    intersections = curve1.evaluate_multi(s_vals)
    ax.plot(
        intersections[0, :],
        intersections[1, :],
        color="black",
        linestyle="None",
        marker="o",
    )
    ax.axis("scaled")
    ax.set_xlim(0.0, 0.75)
    ax.set_ylim(0.0, 0.75)
    save_image(ax.figure, "curve_intersect.png")


Instruction:
Make a summary of the following Python 3 code
def surface_constructor(surface):
    if NO_IMAGES:
        return

    ax = surface.plot(256, with_nodes=True)
    line = ax.lines[0]
    nodes = surface._nodes
    add_patch(ax, nodes[:, (0, 1, 2, 5)], line.get_color())
    delta = 1.0 / 32.0
    ax.text(
        nodes[0, 0],
        nodes[1, 0],
        r"$v_0$",
        fontsize=20,
        verticalalignment="top",
        horizontalalignment="right",
    )
    ax.text(
        nodes[0, 1],
        nodes[1, 1],
        r"$v_1$",
        fontsize=20,
        verticalalignment="top",
        horizontalalignment="center",
    )
    ax.text(
        nodes[0, 2],
        nodes[1, 2],
        r"$v_2$",
        fontsize=20,
        verticalalignment="top",
        horizontalalignment="left",
    )
    ax.text(
        nodes[0, 3] - delta,
        nodes[1, 3],
        r"$v_3$",
        fontsize=20,
        verticalalignment="center",
        horizontalalignment="right",
    )
    ax.text(
        nodes[0, 4] + delta,
        nodes[1, 4],
        r"$v_4$",
        fontsize=20,
        verticalalignment="center",
        horizontalalignment="left",
    )
    ax.text(
        nodes[0, 5],
        nodes[1, 5] + delta,
        r"$v_5$",
        fontsize=20,
        verticalalignment="bottom",
        horizontalalignment="center",
    )
    ax.axis("scaled")
    ax.set_xlim(-0.125, 1.125)
    ax.set_ylim(-0.125, 1.125)
    save_image(ax.figure, "surface_constructor.png")

Response: Image for : class. Surface docstring.


Instruction:
Can you implement a function in Python 3 that
images for : meth. Surface. evaluate_barycentric docstring.

Response:
def surface_evaluate_barycentric(surface, point):
    """Image for :meth`.Surface.evaluate_barycentric` docstring."""
    if NO_IMAGES:
        return

    ax = surface.plot(256)
    ax.plot(
        point[0, :], point[1, :], color="black", linestyle="None", marker="o"
    )
    ax.axis("scaled")
    ax.set_xlim(-0.125, 1.125)
    ax.set_ylim(-0.125, 1.125)
    save_image(ax.figure, "surface_evaluate_barycentric.png")


Instruction:
Can you implement a function in Python 3 that
images for : meth. Surface. evaluate_cartesian_multi docstring.

Response:
def surface_evaluate_cartesian_multi(surface, points):
    """Image for :meth`.Surface.evaluate_cartesian_multi` docstring."""
    if NO_IMAGES:
        return

    ax = surface.plot(256)
    ax.plot(
        points[0, :], points[1, :], color="black", linestyle="None", marker="o"
    )
    delta = 1.0 / 32.0
    font_size = 18
    ax.text(
        points[0, 0],
        points[1, 0],
        r"$w_0$",
        fontsize=font_size,
        verticalalignment="top",
        horizontalalignment="right",
    )
    ax.text(
        points[0, 1] + 2 * delta,
        points[1, 1],
        r"$w_1$",
        fontsize=font_size,
        verticalalignment="center",
        horizontalalignment="left",
    )
    ax.text(
        points[0, 2],
        points[1, 2] + delta,
        r"$w_2$",
        fontsize=font_size,
        verticalalignment="bottom",
        horizontalalignment="left",
    )
    ax.axis("scaled")
    ax.set_xlim(-3.125, 2.375)
    ax.set_ylim(-0.25, 2.125)
    save_image(ax.figure, "surface_evaluate_cartesian_multi.png")


Instruction:
Write a Python 3 script to
image for : meth. Surface. is_valid docstring.

Response:
def surface_is_valid1(surface):
    """Image for :meth`.Surface.is_valid` docstring."""
    if NO_IMAGES:
        return

    ax = surface.plot(256)
    ax.axis("scaled")
    ax.set_xlim(-0.125, 2.125)
    ax.set_ylim(-0.125, 2.125)
    save_image(ax.figure, "surface_is_valid1.png")


Instruction:
How would you code a function in Python 3 to
image for : meth. Surface. is_valid

Response:
def surface_is_valid3(surface):
    """Image for :meth`.Surface.is_valid` docstring."""
    if NO_IMAGES:
        return

    edge1, edge2, edge3 = surface.edges
    N = 128
    # Compute points on each edge.
    std_s = np.linspace(0.0, 1.0, N + 1)
    points1 = edge1.evaluate_multi(std_s)
    points2 = edge2.evaluate_multi(std_s)
    points3 = edge3.evaluate_multi(std_s)
    # Compute the actual boundary where the Jacobian is 0.
    s_vals = np.linspace(0.0, 0.2, N)
    t_discrim = np.sqrt((1.0 - s_vals) * (1.0 - 5.0 * s_vals))
    t_top = 0.5 * (1.0 - s_vals + t_discrim)
    t_bottom = 0.5 * (1.0 - s_vals - t_discrim)
    jacobian_zero_params = np.zeros((2 * N - 1, 2), order="F")
    jacobian_zero_params[:N, 0] = s_vals
    jacobian_zero_params[:N, 1] = t_top
    jacobian_zero_params[N:, 0] = s_vals[-2::-1]
    jacobian_zero_params[N:, 1] = t_bottom[-2::-1]
    jac_edge = surface.evaluate_cartesian_multi(jacobian_zero_params)
    # Add the surface to the plot and add a dashed line
    # for each "true" edge.
    figure = plt.figure()
    ax = figure.gca()
    line, = ax.plot(jac_edge[0, :], jac_edge[1, :])
    color = line.get_color()
    ax.plot(points1[0, :], points1[1, :], color="black", linestyle="dashed")
    ax.plot(points2[0, :], points2[1, :], color="black", linestyle="dashed")
    ax.plot(points3[0, :], points3[1, :], color="black", linestyle="dashed")
    polygon = np.hstack([points1[:, 1:], points2[:, 1:], jac_edge[:, 1:]])
    add_patch(ax, polygon, color, with_nodes=False)
    ax.axis("scaled")
    ax.set_xlim(-0.0625, 1.0625)
    ax.set_ylim(-0.0625, 1.0625)
    save_image(ax.figure, "surface_is_valid3.png")


Instruction:
Write a Python 3 script for
imaging for : meth. Surface. subdivide docstring.

Response:
def surface_subdivide1():
    """Image for :meth`.Surface.subdivide` docstring."""
    if NO_IMAGES:
        return

    surface = bezier.Surface.from_nodes(
        np.asfortranarray([[0.0, 1.0, 0.0], [0.0, 0.0, 1.0]])
    )
    surf_a, surf_b, surf_c, surf_d = surface.subdivide()
    figure, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2)
    for ax in (ax1, ax2, ax3, ax4):
        surface.plot(2, ax=ax)
    surf_a.plot(2, ax=ax1)
    ax1.text(
        1.0 / 6.0,
        1.0 / 6.0,
        r"$A$",
        fontsize=20,
        verticalalignment="center",
        horizontalalignment="center",
    )
    surf_b.plot(2, ax=ax2)
    ax2.text(
        1.0 / 3.0,
        1.0 / 3.0,
        r"$B$",
        fontsize=20,
        verticalalignment="center",
        horizontalalignment="center",
    )
    surf_c.plot(2, ax=ax3)
    ax3.text(
        2.0 / 3.0,
        1.0 / 6.0,
        r"$C$",
        fontsize=20,
        verticalalignment="center",
        horizontalalignment="center",
    )
    surf_d.plot(2, ax=ax4)
    ax4.text(
        1.0 / 6.0,
        2.0 / 3.0,
        r"$D$",
        fontsize=20,
        verticalalignment="center",
        horizontalalignment="center",
    )
    for ax in (ax1, ax2, ax3, ax4):
        ax.axis("scaled")
    save_image(figure, "surface_subdivide1")


Instruction:
Given the following Python 3 function, write the documentation
def surface_subdivide2(surface, sub_surface_b):
    if NO_IMAGES:
        return

    # Plot set-up.
    figure = plt.figure()
    ax = figure.gca()
    colors = seaborn.husl_palette(6)
    N = 128
    s_vals = np.linspace(0.0, 1.0, N + 1)
    # Add edges from surface.
    add_edges(ax, surface, s_vals, colors[4])
    # Now do the same for surface B.
    add_edges(ax, sub_surface_b, s_vals, colors[0])
    # Add the control points polygon for the original surface.
    nodes = surface._nodes[:, (0, 2, 4, 5, 0)]
    add_patch(ax, nodes, colors[2], with_nodes=False)
    # Add the control points polygon for the sub-surface.
    nodes = sub_surface_b._nodes[:, (0, 1, 2, 5, 3, 0)]
    add_patch(ax, nodes, colors[1], with_nodes=False)
    # Plot **all** the nodes.
    sub_nodes = sub_surface_b._nodes
    ax.plot(
        sub_nodes[0, :],
        sub_nodes[1, :],
        color="black",
        linestyle="None",
        marker="o",
    )
    # Take those same points and add the boundary.
    ax.plot(nodes[0, :], nodes[1, :], color="black", linestyle="dashed")
    ax.axis("scaled")
    ax.set_xlim(-1.125, 2.125)
    ax.set_ylim(-0.125, 4.125)
    save_image(ax.figure, "surface_subdivide2")

Response: Image for : meth. Surface. subdivide docstring.


Instruction:
Make a summary of the following Python 3 code
def curved_polygon_constructor1(curved_poly):
    if NO_IMAGES:
        return

    ax = curved_poly.plot(256)
    ax.axis("scaled")
    ax.set_xlim(-0.125, 2.125)
    ax.set_ylim(-0.625, 1.625)
    save_image(ax.figure, "curved_polygon_constructor1.png")

Response: Image for : class. CurvedPolygon docstring.


Instruction:
Make a summary of the following Python 3 code
def curve_specialize(curve, new_curve):
    if NO_IMAGES:
        return

    ax = curve.plot(256)
    interval = r"$\left[0, 1\right]$"
    line = ax.lines[-1]
    line.set_label(interval)
    color1 = line.get_color()
    new_curve.plot(256, ax=ax)
    interval = r"$\left[-\frac{1}{4}, \frac{3}{4}\right]$"
    line = ax.lines[-1]
    line.set_label(interval)
    ax.plot(
        curve._nodes[0, (0, -1)],
        curve._nodes[1, (0, -1)],
        color=color1,
        linestyle="None",
        marker="o",
    )
    ax.plot(
        new_curve._nodes[0, (0, -1)],
        new_curve._nodes[1, (0, -1)],
        color=line.get_color(),
        linestyle="None",
        marker="o",
    )
    ax.legend(loc="lower right", fontsize=12)
    ax.axis("scaled")
    ax.set_xlim(-0.375, 1.125)
    ax.set_ylim(-0.75, 0.625)
    save_image(ax.figure, "curve_specialize.png")

Response: Image for : meth. Curve. specialize docstring.


Instruction:
Can you create a Python 3 function that
images for the Newton - Refine surface.

Response:
def newton_refine_surface(surface, x_val, y_val, s, t, new_s, new_t):
    """Image for :func:`._surface_helpers.newton_refine` docstring."""
    if NO_IMAGES:
        return

    figure, (ax1, ax2) = plt.subplots(1, 2)
    # Plot features of the parameter space in ax1.
    tri_surf = bezier.Surface.from_nodes(
        np.asfortranarray([[0.0, 1.0, 0.0], [0.0, 0.0, 1.0]])
    )
    tri_surf.plot(2, ax=ax1)
    ax1.plot([0.25], [0.5], marker="H")
    ax1.plot([s], [t], color="black", linestyle="None", marker="o")
    ax1.plot(
        [new_s],
        [new_t],
        color="black",
        linestyle="None",
        marker="o",
        markeredgewidth=1,
        markerfacecolor="None",
    )
    # Plot the equivalent output in ax2.
    surface.plot(256, ax=ax2)
    points = surface.evaluate_cartesian_multi(
        np.asfortranarray([[s, t], [new_s, new_t]])
    )
    ax2.plot([x_val], [y_val], marker="H")
    ax2.plot(
        points[0, [0]],
        points[1, [0]],
        color="black",
        linestyle="None",
        marker="o",
    )
    ax2.plot(
        points[0, [1]],
        points[1, [1]],
        color="black",
        linestyle="None",
        marker="o",
        markeredgewidth=1,
        markerfacecolor="None",
    )
    # Set the axis bounds / scaling.
    ax1.axis("scaled")
    ax1.set_xlim(-0.0625, 1.0625)
    ax1.set_ylim(-0.0625, 1.0625)
    ax2.axis("scaled")
    ax2.set_xlim(-0.125, 2.125)
    ax2.set_ylim(-0.125, 2.125)
    save_image(figure, "newton_refine_surface.png")


Instruction:
Create a Python 3 function for
imaging for :func:`._surface_helpers.classify_intersection` docstring.

Response:
def classify_intersection1(s, curve1, tangent1, curve2, tangent2):
    """Image for :func:`._surface_helpers.classify_intersection` docstring."""
    if NO_IMAGES:
        return

    surface1 = bezier.Surface.from_nodes(
        np.asfortranarray(
            [[1.0, 1.75, 2.0, 1.0, 1.5, 1.0], [0.0, 0.25, 1.0, 1.0, 1.5, 2.0]]
        )
    )
    surface2 = bezier.Surface.from_nodes(
        np.asfortranarray(
            [
                [0.0, 1.6875, 2.0, 0.25, 1.25, 0.5],
                [0.0, 0.0625, 0.5, 1.0, 1.25, 2.0],
            ]
        )
    )
    ax = classify_help(s, curve1, surface1, curve2, surface2, 0)
    (int_x,), (int_y,) = curve1.evaluate(s)
    # Remove the alpha from the color
    color1 = ax.patches[0].get_facecolor()[:3]
    color2 = ax.patches[1].get_facecolor()[:3]
    ax.plot(
        [int_x, int_x + tangent1[0, 0]],
        [int_y, int_y + tangent1[1, 0]],
        color=color1,
        linestyle="dashed",
    )
    ax.plot(
        [int_x, int_x + tangent2[0, 0]],
        [int_y, int_y + tangent2[1, 0]],
        color=color2,
        linestyle="dashed",
    )
    ax.plot([int_x], [int_y], color=color1, linestyle="None", marker="o")
    ax.axis("scaled")
    ax.set_xlim(-0.125, 2.125)
    ax.set_ylim(-0.125, 1.125)
    save_image(ax.figure, "classify_intersection1.png")


Instruction:
How would you explain what the following Python 3 function does
def classify_intersection2(s, curve1, curve2):
    if NO_IMAGES:
        return

    surface1 = bezier.Surface.from_nodes(
        np.asfortranarray(
            [[1.0, 1.5, 2.0, 1.25, 1.75, 1.5], [0.0, 1.0, 0.0, 1.0, 1.0, 2.0]]
        )
    )
    surface2 = bezier.Surface.from_nodes(
        np.asfortranarray(
            [[0.0, 1.5, 3.0, 0.75, 2.25, 1.5], [0.0, 1.0, 0.0, 2.0, 2.0, 4.0]]
        )
    )
    ax = classify_help(s, curve1, surface1, curve2, surface2, 1)
    ax.set_xlim(-0.0625, 3.0625)
    ax.set_ylim(-0.0625, 0.5625)
    save_image(ax.figure, "classify_intersection2.png")

Response: Image for _surface_helpers. classify_intersection docstring.


Instruction:
Write a Python 3 script for
imaging for _surface_helpers. classify_intersection docstring.

Response:
def classify_intersection5(s, curve1, curve2):
    """Image for :func:`._surface_helpers.classify_intersection` docstring."""
    if NO_IMAGES:
        return

    surface1 = bezier.Surface.from_nodes(
        np.asfortranarray(
            [
                [1.0, 1.5, 2.0, 1.25, 1.75, 1.5],
                [0.0, 1.0, 0.0, 0.9375, 0.9375, 1.875],
            ]
        )
    )
    surface2 = bezier.Surface.from_nodes(
        np.asfortranarray(
            [
                [3.0, 1.5, 0.0, 2.25, 0.75, 1.5],
                [0.0, 1.0, 0.0, -2.0, -2.0, -4.0],
            ]
        )
    )
    figure, (ax1, ax2) = plt.subplots(2, 1)
    classify_help(s, curve1, surface1, curve2, surface2, 0, ax=ax1)
    classify_help(s, curve1, surface1, curve2, surface2, 1, ax=ax2)
    # Remove the alpha from the color
    color1 = ax1.patches[0].get_facecolor()[:3]
    color2 = ax1.patches[1].get_facecolor()[:3]
    # Now add the "degenerate" intersection polygons. The first
    # comes from specializing to
    # left1(0.5, 1.0)-left2(0.0, 0.25)-right1(0.375, 0.5)
    surface3 = bezier.Surface.from_nodes(
        np.asfortranarray(
            [
                [1.5, 1.75, 2.0, 1.6875, 1.9375, 1.875],
                [0.5, 0.5, 0.0, 0.5, 0.234375, 0.46875],
            ]
        )
    )
    # NOTE: We don't require the intersection polygon be valid.
    surface3.plot(256, ax=ax1)
    # The second comes from specializing to
    # left1(0.0, 0.5)-right1(0.5, 0.625)-left3(0.75, 1.0)
    surface4 = bezier.Surface.from_nodes(
        np.asfortranarray(
            [
                [1.0, 1.25, 1.5, 1.0625, 1.3125, 1.125],
                [0.0, 0.5, 0.5, 0.234375, 0.5, 0.46875],
            ]
        )
    )
    # NOTE: We don't require the intersection polygon be valid.
    surface4.plot(256, ax=ax2)
    (int_x,), (int_y,) = curve1.evaluate(s)
    ax1.plot([int_x], [int_y], color=color1, linestyle="None", marker="o")
    ax2.plot([int_x], [int_y], color=color2, linestyle="None", marker="o")
    for ax in (ax1, ax2):
        ax.axis("scaled")
        ax.set_xlim(-0.0625, 3.0625)
        ax.set_ylim(-0.0625, 0.5625)
    plt.setp(ax1.get_xticklabels(), visible=False)
    figure.tight_layout(h_pad=-7.0)
    save_image(figure, "classify_intersection5.png")


Instruction:
Can you generate the documentation for the following Python 3 function
def classify_intersection7(s, curve1a, curve1b, curve2):
    if NO_IMAGES:
        return

    surface1 = bezier.Surface.from_nodes(
        np.asfortranarray(
            [
                [0.0, 4.5, 9.0, 0.0, 4.5, 0.0],
                [0.0, 0.0, 2.25, 1.25, 2.375, 2.5],
            ]
        )
    )
    surface2 = bezier.Surface.from_nodes(
        np.asfortranarray(
            [
                [11.25, 9.0, 2.75, 8.125, 3.875, 5.0],
                [0.0, 4.5, 1.0, -0.75, -0.25, -1.5],
            ]
        )
    )
    figure, (ax1, ax2) = plt.subplots(2, 1)
    classify_help(s, curve1a, surface1, curve2, surface2, None, ax=ax1)
    surface1._nodes = np.asfortranarray(surface1._nodes[:, (2, 4, 5, 1, 3, 0)])
    surface1._edges = None
    classify_help(0.0, curve1b, surface1, curve2, surface2, 0, ax=ax2)
    for ax in (ax1, ax2):
        ax.set_xlim(-0.125, 11.5)
        ax.set_ylim(-0.125, 2.625)
    plt.setp(ax1.get_xticklabels(), visible=False)
    figure.tight_layout(h_pad=-5.0)
    save_image(figure, "classify_intersection7.png")

Response: Image for _surface_helpers. classify_intersection7 docstring.


Instruction:
Can you generate the documentation for the following Python 3 function
def get_curvature(nodes, s, tangent_vec, curvature):
    if NO_IMAGES:
        return

    curve = bezier.Curve.from_nodes(nodes)
    # Find the center of the circle along the direction
    # perpendicular to the tangent vector (90 degree left turn).
    radius_dir = np.asfortranarray([[-tangent_vec[1, 0]], [tangent_vec[0, 0]]])
    radius_dir /= np.linalg.norm(radius_dir, ord=2)
    point = curve.evaluate(s)
    circle_center = point + radius_dir / curvature
    # Add the curve.
    ax = curve.plot(256)
    # Add the circle.
    circle_center = circle_center.ravel(order="F")
    circle = plt.Circle(circle_center, 1.0 / abs(curvature), alpha=0.25)
    ax.add_artist(circle)
    # Add the point.
    ax.plot(
        point[0, :], point[1, :], color="black", marker="o", linestyle="None"
    )
    ax.axis("scaled")
    ax.set_xlim(-0.0625, 1.0625)
    ax.set_ylim(-0.0625, 0.625)
    save_image(ax.figure, "get_curvature.png")

Response: Image for getting the curvature of a node.


Instruction:
Implement a Python 3 function for
imaging for : meth. Curve. locate docstring.

Response:
def curve_locate(curve, point1, point2, point3):
    """Image for :meth`.Curve.locate` docstring."""
    if NO_IMAGES:
        return

    ax = curve.plot(256)
    points = np.hstack([point1, point2, point3])
    ax.plot(
        points[0, :], points[1, :], color="black", linestyle="None", marker="o"
    )
    ax.axis("scaled")
    ax.set_xlim(-0.8125, 0.0625)
    ax.set_ylim(0.75, 2.0625)
    save_image(ax.figure, "curve_locate.png")


Instruction:
Given the following Python 3 function, write the documentation
def newton_refine_curve(curve, point, s, new_s):
    if NO_IMAGES:
        return

    ax = curve.plot(256)
    ax.plot(point[0, :], point[1, :], marker="H")
    wrong_points = curve.evaluate_multi(np.asfortranarray([s, new_s]))
    ax.plot(
        wrong_points[0, [0]],
        wrong_points[1, [0]],
        color="black",
        linestyle="None",
        marker="o",
    )
    ax.plot(
        wrong_points[0, [1]],
        wrong_points[1, [1]],
        color="black",
        linestyle="None",
        marker="o",
        markeredgewidth=1,
        markerfacecolor="None",
    )
    # Set the axis bounds / scaling.
    ax.axis("scaled")
    ax.set_xlim(-0.125, 3.125)
    ax.set_ylim(-0.125, 1.375)
    save_image(ax.figure, "newton_refine_curve.png")

Response: Image for the Newton - Refine curve.


Instruction:
Can you tell what is the following Python 3 function doing
def newton_refine_curve_cusp(curve, s_vals):
    if NO_IMAGES:
        return

    ax = curve.plot(256)
    ax.lines[-1].zorder = 1
    points = curve.evaluate_multi(np.asfortranarray(s_vals))
    colors = seaborn.dark_palette("blue", 6)
    ax.scatter(
        points[0, :], points[1, :], c=colors, s=20, alpha=0.75, zorder=2
    )
    # Set the axis bounds / scaling.
    ax.axis("scaled")
    ax.set_xlim(-0.125, 6.125)
    ax.set_ylim(-3.125, 3.125)
    save_image(ax.figure, "newton_refine_curve_cusp.png")

Response: Image for the Newton Reine curve.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def classify_intersection8(s, curve1, surface1, curve2, surface2):
    if NO_IMAGES:
        return

    ax = classify_help(s, curve1, surface1, curve2, surface2, None)
    ax.set_xlim(-1.125, 1.125)
    ax.set_ylim(-0.125, 1.125)
    save_image(ax.figure, "classify_intersection8.png")

Response: Image for classify_intersection8 docstring.


Instruction:
Can you tell what is the following Python 3 function doing
def _edges_classify_intersection9():
    edges1 = (
        bezier.Curve.from_nodes(
            np.asfortranarray([[32.0, 30.0], [20.0, 25.0]])
        ),
        bezier.Curve.from_nodes(
            np.asfortranarray([[30.0, 25.0, 20.0], [25.0, 20.0, 20.0]])
        ),
        bezier.Curve.from_nodes(
            np.asfortranarray([[20.0, 25.0, 30.0], [20.0, 20.0, 15.0]])
        ),
        bezier.Curve.from_nodes(
            np.asfortranarray([[30.0, 32.0], [15.0, 20.0]])
        ),
    )
    edges2 = (
        bezier.Curve.from_nodes(
            np.asfortranarray([[8.0, 10.0], [20.0, 15.0]])
        ),
        bezier.Curve.from_nodes(
            np.asfortranarray([[10.0, 15.0, 20.0], [15.0, 20.0, 20.0]])
        ),
        bezier.Curve.from_nodes(
            np.asfortranarray([[20.0, 15.0, 10.0], [20.0, 20.0, 25.0]])
        ),
        bezier.Curve.from_nodes(
            np.asfortranarray([[10.0, 8.0], [25.0, 20.0]])
        ),
    )
    return edges1, edges2

Response: The edges for the curved polygon intersection used below.


Instruction:
How would you implement a function in Python 3 that
images for _surface_helpers. classify_intersection docstring.

Response:
def classify_intersection9(s, curve1, curve2):
    """Image for :func:`._surface_helpers.classify_intersection` docstring."""
    if NO_IMAGES:
        return

    surface1 = bezier.Surface.from_nodes(
        np.asfortranarray(
            [
                [0.0, 20.0, 40.0, 10.0, 30.0, 20.0],
                [0.0, 40.0, 0.0, 25.0, 25.0, 50.0],
            ]
        )
    )
    surface2 = bezier.Surface.from_nodes(
        np.asfortranarray(
            [
                [40.0, 20.0, 0.0, 30.0, 10.0, 20.0],
                [40.0, 0.0, 40.0, 15.0, 15.0, -10.0],
            ]
        )
    )
    figure, (ax1, ax2) = plt.subplots(1, 2)
    classify_help(s, curve1, surface1, curve2, surface2, 0, ax=ax1)
    classify_help(s, curve1, surface1, curve2, surface2, 1, ax=ax2)
    # Remove the alpha from the color
    color1 = ax1.patches[0].get_facecolor()[:3]
    color2 = ax1.patches[1].get_facecolor()[:3]
    # Now add the "degenerate" intersection polygons.
    cp_edges1, cp_edges2 = _edges_classify_intersection9()
    curved_polygon1 = bezier.CurvedPolygon(*cp_edges1)
    curved_polygon1.plot(256, ax=ax1)
    curved_polygon2 = bezier.CurvedPolygon(*cp_edges2)
    curved_polygon2.plot(256, ax=ax2)
    (int_x,), (int_y,) = curve1.evaluate(s)
    ax1.plot([int_x], [int_y], color=color1, linestyle="None", marker="o")
    ax2.plot([int_x], [int_y], color=color2, linestyle="None", marker="o")
    for ax in (ax1, ax2):
        ax.axis("scaled")
        ax.set_xlim(-2.0, 42.0)
        ax.set_ylim(-12.0, 52.0)
    plt.setp(ax2.get_yticklabels(), visible=False)
    figure.tight_layout(w_pad=1.0)
    save_image(figure, "classify_intersection9.png")


Instruction:
Here you have a function in Python 3, explain what it does
def curve_elevate(curve, elevated):
    if NO_IMAGES:
        return

    figure, (ax1, ax2) = plt.subplots(1, 2)
    curve.plot(256, ax=ax1)
    color = ax1.lines[-1].get_color()
    add_patch(ax1, curve._nodes, color)
    elevated.plot(256, ax=ax2)
    color = ax2.lines[-1].get_color()
    add_patch(ax2, elevated._nodes, color)
    ax1.axis("scaled")
    ax2.axis("scaled")
    _plot_helpers.add_plot_boundary(ax1)
    ax2.set_xlim(*ax1.get_xlim())
    ax2.set_ylim(*ax1.get_ylim())
    save_image(figure, "curve_elevate.png")

Response: Image for : meth :. curve. Curve. elevate docstring.


Instruction:
Here you have a function in Python 3, explain what it does
def unit_triangle():
    if NO_IMAGES:
        return

    nodes = np.asfortranarray([[0.0, 1.0, 0.0], [0.0, 0.0, 1.0]])
    surface = bezier.Surface(nodes, degree=1)
    ax = surface.plot(256)
    ax.axis("scaled")
    _plot_helpers.add_plot_boundary(ax)
    save_image(ax.figure, "unit_triangle.png")

Response: Image for : class :. surface. Surface docstring.