Instruction:
How would you implement a function in Python 3 that
creates a new instance of the specified instance.

Response:
def makeInstance(self, instanceDescriptor,
            doRules=False,
            glyphNames=None,
            pairs=None,
            bend=False):
        """ Generate a font object for this instance """
        font = self._instantiateFont(None)
        # make fonty things here
        loc = Location(instanceDescriptor.location)
        anisotropic = False
        locHorizontal = locVertical = loc
        if self.isAnisotropic(loc):
            anisotropic = True
            locHorizontal, locVertical = self.splitAnisotropic(loc)
        # groups
        renameMap = getattr(self.fonts[self.default.name], "kerningGroupConversionRenameMaps", None)
        font.kerningGroupConversionRenameMaps = renameMap if renameMap is not None else {'side1': {}, 'side2': {}}
        # make the kerning
        # this kerning is always horizontal. We can take the horizontal location
        # filter the available pairs?
        if instanceDescriptor.kerning:
            if pairs:
                try:
                    kerningMutator = self.getKerningMutator(pairs=pairs)
                    kerningObject = kerningMutator.makeInstance(locHorizontal, bend=bend)
                    kerningObject.extractKerning(font)
                except:
                    self.problems.append("Could not make kerning for %s. %s" % (loc, traceback.format_exc()))
            else:
                kerningMutator = self.getKerningMutator()
                kerningObject = kerningMutator.makeInstance(locHorizontal, bend=bend)
                kerningObject.extractKerning(font)
        # make the info
        try:
            infoMutator = self.getInfoMutator()
            if not anisotropic:
                infoInstanceObject = infoMutator.makeInstance(loc, bend=bend)
            else:
                horizontalInfoInstanceObject = infoMutator.makeInstance(locHorizontal, bend=bend)
                verticalInfoInstanceObject = infoMutator.makeInstance(locVertical, bend=bend)
                # merge them again
                infoInstanceObject = (1,0)*horizontalInfoInstanceObject + (0,1)*verticalInfoInstanceObject
            if self.roundGeometry:
                try:
                    infoInstanceObject = infoInstanceObject.round()
                except AttributeError:
                    pass
            infoInstanceObject.extractInfo(font.info)
            font.info.familyName = instanceDescriptor.familyName
            font.info.styleName = instanceDescriptor.styleName
            font.info.postscriptFontName = instanceDescriptor.postScriptFontName # yikes, note the differences in capitalisation..
            font.info.styleMapFamilyName = instanceDescriptor.styleMapFamilyName
            font.info.styleMapStyleName = instanceDescriptor.styleMapStyleName
            # NEED SOME HELP WITH THIS
            # localised names need to go to the right openTypeNameRecords
            # records = []
            # nameID = 1
            # platformID =
            # for languageCode, name in instanceDescriptor.localisedStyleMapFamilyName.items():
            #    # Name ID 1 (font family name) is found at the generic styleMapFamily attribute.
            #    records.append((nameID, ))
        except:
            self.problems.append("Could not make fontinfo for %s. %s" % (loc, traceback.format_exc()))
        for sourceDescriptor in self.sources:
            if sourceDescriptor.copyInfo:
                # this is the source
                if self.fonts[sourceDescriptor.name] is not None:
                    self._copyFontInfo(self.fonts[sourceDescriptor.name].info, font.info)
            if sourceDescriptor.copyLib:
                # excplicitly copy the font.lib items
                if self.fonts[sourceDescriptor.name] is not None:
                    for key, value in self.fonts[sourceDescriptor.name].lib.items():
                        font.lib[key] = value
            if sourceDescriptor.copyGroups:
                if self.fonts[sourceDescriptor.name] is not None:
                    sides = font.kerningGroupConversionRenameMaps.get('side1', {})
                    sides.update(font.kerningGroupConversionRenameMaps.get('side2', {}))
                    for key, value in self.fonts[sourceDescriptor.name].groups.items():
                        if key not in sides:
                            font.groups[key] = value
            if sourceDescriptor.copyFeatures:
                if self.fonts[sourceDescriptor.name] is not None:
                    featuresText = self.fonts[sourceDescriptor.name].features.text
                    font.features.text = featuresText
        # glyphs
        if glyphNames:
            selectedGlyphNames = glyphNames
        else:
            selectedGlyphNames = self.glyphNames
        # add the glyphnames to the font.lib['public.glyphOrder']
        if not 'public.glyphOrder' in font.lib.keys():
            font.lib['public.glyphOrder'] = selectedGlyphNames
        for glyphName in selectedGlyphNames:
            try:
                glyphMutator = self.getGlyphMutator(glyphName)
                if glyphMutator is None:
                    continue
            except:
                self.problems.append("Could not make mutator for glyph %s %s" % (glyphName, traceback.format_exc()))
                continue
            if glyphName in instanceDescriptor.glyphs.keys():
                # XXX this should be able to go now that we have full rule support.
                # reminder: this is what the glyphData can look like
                # {'instanceLocation': {'custom': 0.0, 'weight': 824.0},
                #  'masters': [{'font': 'master.Adobe VF Prototype.Master_0.0',
                #               'glyphName': 'dollar.nostroke',
                #               'location': {'custom': 0.0, 'weight': 0.0}},
                #              {'font': 'master.Adobe VF Prototype.Master_1.1',
                #               'glyphName': 'dollar.nostroke',
                #               'location': {'custom': 0.0, 'weight': 368.0}},
                #              {'font': 'master.Adobe VF Prototype.Master_2.2',
                #               'glyphName': 'dollar.nostroke',
                #               'location': {'custom': 0.0, 'weight': 1000.0}},
                #              {'font': 'master.Adobe VF Prototype.Master_3.3',
                #               'glyphName': 'dollar.nostroke',
                #               'location': {'custom': 100.0, 'weight': 1000.0}},
                #              {'font': 'master.Adobe VF Prototype.Master_0.4',
                #               'glyphName': 'dollar.nostroke',
                #               'location': {'custom': 100.0, 'weight': 0.0}},
                #              {'font': 'master.Adobe VF Prototype.Master_4.5',
                #               'glyphName': 'dollar.nostroke',
                #               'location': {'custom': 100.0, 'weight': 368.0}}],
                #  'unicodes': [36]}
                glyphData = instanceDescriptor.glyphs[glyphName]
            else:
                glyphData = {}
            font.newGlyph(glyphName)
            font[glyphName].clear()
            if glyphData.get('mute', False):
                # mute this glyph, skip
                continue
            glyphInstanceLocation = glyphData.get("instanceLocation", instanceDescriptor.location)
            glyphInstanceLocation = Location(glyphInstanceLocation)
            uniValues = []
            neutral = glyphMutator.get(())
            if neutral is not None:
                uniValues = neutral[0].unicodes
            else:
                neutralFont = self.getNeutralFont()
                if glyphName in neutralFont:
                    uniValues = neutralFont[glyphName].unicodes
            glyphInstanceUnicodes = glyphData.get("unicodes", uniValues)
            note = glyphData.get("note")
            if note:
                font[glyphName] = note
            # XXXX phase out support for instance-specific masters
            # this should be handled by the rules system.
            masters = glyphData.get("masters", None)
            if masters is not None:
                items = []
                for glyphMaster in masters:
                    sourceGlyphFont = glyphMaster.get("font")
                    sourceGlyphName = glyphMaster.get("glyphName", glyphName)
                    m = self.fonts.get(sourceGlyphFont)
                    if not sourceGlyphName in m:
                        continue
                    if hasattr(m[sourceGlyphName], "toMathGlyph"):
                        sourceGlyph = m[sourceGlyphName].toMathGlyph()
                    else:
                        sourceGlyph = MathGlyph(m[sourceGlyphName])
                    sourceGlyphLocation = glyphMaster.get("location")
                    items.append((Location(sourceGlyphLocation), sourceGlyph))
                bias, glyphMutator = self.getVariationModel(items, axes=self.serializedAxes, bias=self.newDefaultLocation())
            try:
                if not self.isAnisotropic(glyphInstanceLocation):
                    glyphInstanceObject = glyphMutator.makeInstance(glyphInstanceLocation, bend=bend)
                else:
                    # split anisotropic location into horizontal and vertical components
                    horizontal, vertical = self.splitAnisotropic(glyphInstanceLocation)
                    horizontalGlyphInstanceObject = glyphMutator.makeInstance(horizontal, bend=bend)
                    verticalGlyphInstanceObject = glyphMutator.makeInstance(vertical, bend=bend)
                    # merge them again
                    glyphInstanceObject = (1,0)*horizontalGlyphInstanceObject + (0,1)*verticalGlyphInstanceObject
            except IndexError:
                # alignment problem with the data?
                continue
            font.newGlyph(glyphName)
            font[glyphName].clear()
            if self.roundGeometry:
                try:
                    glyphInstanceObject = glyphInstanceObject.round()
                except AttributeError:
                    pass
            try:
                # File "/Users/erik/code/ufoProcessor/Lib/ufoProcessor/__init__.py", line 649, in makeInstance
                #   glyphInstanceObject.extractGlyph(font[glyphName], onlyGeometry=True)
                # File "/Applications/RoboFont.app/Contents/Resources/lib/python3.6/fontMath/mathGlyph.py", line 315, in extractGlyph
                #   glyph.anchors = [dict(anchor) for anchor in self.anchors]
                # File "/Applications/RoboFont.app/Contents/Resources/lib/python3.6/fontParts/base/base.py", line 103, in __set__
                #   raise FontPartsError("no setter for %r" % self.name)
                #   fontParts.base.errors.FontPartsError: no setter for 'anchors'
                if hasattr(font[glyphName], "fromMathGlyph"):
                    font[glyphName].fromMathGlyph(glyphInstanceObject)
                else:
                    glyphInstanceObject.extractGlyph(font[glyphName], onlyGeometry=True)
            except TypeError:
                # this causes ruled glyphs to end up in the wrong glyphname
                # but defcon2 objects don't support it
                pPen = font[glyphName].getPointPen()
                font[glyphName].clear()
                glyphInstanceObject.drawPoints(pPen)
            font[glyphName].width = glyphInstanceObject.width
            font[glyphName].unicodes = glyphInstanceUnicodes
        if doRules:
            resultNames = processRules(self.rules, loc, self.glyphNames)
            for oldName, newName in zip(self.glyphNames, resultNames):
                if oldName != newName:
                    swapGlyphNames(font, oldName, newName)
        # copy the glyph lib?
        #for sourceDescriptor in self.sources:
        #    if sourceDescriptor.copyLib:
        #        pass
        #    pass
        # store designspace location in the font.lib
        font.lib['designspace.location'] = list(instanceDescriptor.location.items())
        return font


Instruction:
Write a Python 3 function that can
return a instance of a font object with all the given subclasses

Response:
def _instantiateFont(self, path):
        """ Return a instance of a font object with all the given subclasses"""
        try:
            return self.fontClass(path,
                layerClass=self.layerClass,
                libClass=self.libClass,
                kerningClass=self.kerningClass,
                groupsClass=self.groupsClass,
                infoClass=self.infoClass,
                featuresClass=self.featuresClass,
                glyphClass=self.glyphClass,
                glyphContourClass=self.glyphContourClass,
                glyphPointClass=self.glyphPointClass,
                glyphComponentClass=self.glyphComponentClass,
                glyphAnchorClass=self.glyphAnchorClass)
        except TypeError:
            # if our fontClass doesnt support all the additional classes
            return self.fontClass(path)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def checkGlyphIsEmpty(glyph, allowWhiteSpace=True):
    whiteSpace = [  0x9,    # horizontal tab
                    0xa,    # line feed
                    0xb,    # vertical tab
                    0xc,    # form feed
                    0xd,    # carriage return
                    0x20,   # space
                    0x85,   # next line
                    0xa0,   # nobreak space
                    0x1680, # ogham space mark
                    0x180e, # mongolian vowel separator
                    0x2000, # en quad
                    0x2001, # em quad
                    0x2003, # en space
                    0x2004, # three per em space
                    0x2005, # four per em space
                    0x2006, # six per em space
                    0x2007, # figure space
                    0x2008, # punctuation space
                    0x2009, # thin space
                    0x200a, # hair space
                    0x2028, # line separator
                    0x2029, # paragraph separator
                    0x202f, # narrow no break space
                    0x205f, # medium mathematical space
                    0x3000, # ideographic space
                    ]
    emptyPen = EmptyPen()
    glyph.drawPoints(emptyPen)
    if emptyPen.isEmpty():
        # we're empty?
        if glyph.unicode in whiteSpace and allowWhiteSpace:
            # are we allowed to be?
            return False
        return True
    return False

Response: Checks if a glyph is completely empty.


Instruction:
Write a Python 3 function for
configuring and build the ns - 3 code.

Response:
def configure_and_build(self, show_progress=True, optimized=True,
                            skip_configuration=False):
        """
        Configure and build the ns-3 code.

        Args:
            show_progress (bool): whether or not to display a progress bar
                during compilation.
            optimized (bool): whether to use an optimized build. If False, use
                a standard ./waf configure.
            skip_configuration (bool): whether to skip the configuration step,
                and only perform compilation.
        """

        # Only configure if necessary
        if not skip_configuration:
            configuration_command = ['python', 'waf', 'configure', '--enable-examples',
                                     '--disable-gtk', '--disable-python']

            if optimized:
                configuration_command += ['--build-profile=optimized',
                                          '--out=build/optimized']

            # Check whether path points to a valid installation
            subprocess.call(configuration_command, cwd=self.path,
                            stdout=subprocess.PIPE, stderr=subprocess.PIPE)

        # Build ns-3
        build_process = subprocess.Popen(['python', 'waf', 'build'], cwd=self.path,
                                         stdout=subprocess.PIPE,
                                         stderr=subprocess.PIPE)

        # Show a progress bar
        if show_progress:
            line_iterator = self.get_build_output(build_process)
            pbar = None
            try:
                [initial, total] = next(line_iterator)
                pbar = tqdm(line_iterator, initial=initial, total=total,
                            unit='file', desc='Building ns-3', smoothing=0)
                for current, total in pbar:
                    pbar.n = current
            except (StopIteration):
                if pbar is not None:
                    pbar.n = pbar.total
        else:  # Wait for the build to finish anyway
            build_process.communicate()


Instruction:
Write a Python 3 script for
parsing the output of the ns - 3 build process and yield the information that is needed to draw the progress bar.

Response:
def get_build_output(self, process):
        """
        Parse the output of the ns-3 build process to extract the information
        that is needed to draw the progress bar.

        Args:
            process: the subprocess instance to listen to.
        """

        while True:
            output = process.stdout.readline()
            if output == b'' and process.poll() is not None:
                if process.returncode > 0:
                    raise Exception("Compilation ended with an error"
                                    ".\nSTDERR\n%s\nSTDOUT\n%s" %
                                    (process.stderr.read(),
                                     process.stdout.read()))
                return
            if output:
                # Parse the output to get current and total tasks
                # This assumes the progress displayed by waf is in the form
                # [current/total]
                matches = re.search(r'\[\s*(\d+?)/(\d+)\].*',
                                    output.strip().decode('utf-8'))
                if matches is not None:
                    yield [int(matches.group(1)), int(matches.group(2))]


Instruction:
Make a summary of the following Python 3 code
def get_available_parameters(self):

        # At the moment, we rely on regex to extract the list of available
        # parameters. This solution will break if the format of the output
        # changes, but this is the best option that is currently available.

        result = subprocess.check_output([self.script_executable,
                                          '--PrintHelp'], env=self.environment,
                                         cwd=self.path).decode('utf-8')

        # Isolate the list of parameters
        options = re.findall('.*Program\s(?:Options|Arguments):'
                             '(.*)General\sArguments.*',
                             result, re.DOTALL)

        global_options = subprocess.check_output([self.script_executable,
                                                  '--PrintGlobals'],
                                                 env=self.environment,
                                                 cwd=self.path).decode('utf-8')

        # Get the single parameter names
        args = []
        if len(options):
            args += re.findall('.*--(.*?)[?::|=].*', options[0], re.MULTILINE)
        if len(global_options):
            args += [k for k in re.findall('.*--(.*?)[?::|=].*',
                                           global_options, re.MULTILINE) if k
                     not in ['RngRun', 'RngSeed', 'SchedulerType',
                             'SimulatorImplementationType', 'ChecksumEnabled']]
        return sorted(args)

Response: Get the list of parameters that are available by the script.


Instruction:
Given the following Python 3 function, write the documentation
def run_simulations(self, parameter_list, data_folder):

        for idx, parameter in enumerate(parameter_list):

            current_result = {
                'params': {},
                'meta': {}
                }
            current_result['params'].update(parameter)

            command = [self.script_executable] + ['--%s=%s' % (param, value)
                                                  for param, value in
                                                  parameter.items()]

            # Run from dedicated temporary folder
            current_result['meta']['id'] = str(uuid.uuid4())
            temp_dir = os.path.join(data_folder, current_result['meta']['id'])
            os.makedirs(temp_dir)

            start = time.time()  # Time execution
            stdout_file_path = os.path.join(temp_dir, 'stdout')
            stderr_file_path = os.path.join(temp_dir, 'stderr')
            with open(stdout_file_path, 'w') as stdout_file, open(
                    stderr_file_path, 'w') as stderr_file:
                return_code = subprocess.call(command, cwd=temp_dir,
                                              env=self.environment,
                                              stdout=stdout_file,
                                              stderr=stderr_file)
            end = time.time()  # Time execution

            if return_code > 0:
                complete_command = [self.script]
                complete_command.extend(command[1:])
                complete_command = "python waf --run \"%s\"" % (
                    ' '.join(complete_command))

                with open(stdout_file_path, 'r') as stdout_file, open(
                        stderr_file_path, 'r') as stderr_file:
                    raise Exception(('Simulation exited with an error.\n'
                                     'Params: %s\n'
                                     '\nStderr: %s\n'
                                     'Stdout: %s\n'
                                     'Use this command to reproduce:\n'
                                     '%s'
                                     % (parameter, stderr_file.read(),
                                        stdout_file.read(), complete_command)))

            current_result['meta']['elapsed_time'] = end-start

            yield current_result

Response: Runs several simulations using a certain combination of parameters. Yields results as simulations are completed.


Instruction:
Write a Python 3 script for
creating a list of all parameter combinations from a dictionary specifying the desired parameter values as lists.

Response:
def list_param_combinations(param_ranges):
    """
    Create a list of all parameter combinations from a dictionary specifying
    desired parameter values as lists.

    Example:

        >>> param_ranges = {'a': [1], 'b': [2, 3]}
        >>> list_param_combinations(param_ranges)
        [{'a': 1, 'b': 2}, {'a': 1, 'b': 3}]

    Additionally, this function is robust in case values are not lists:

        >>> param_ranges = {'a': 1, 'b': [2, 3]}
        >>> list_param_combinations(param_ranges)
        [{'a': 1, 'b': 2}, {'a': 1, 'b': 3}]

    """
    # Convert non-list values to single-element lists
    # This is required to make sure product work.
    for key in param_ranges:
        if not isinstance(param_ranges[key], list):
            param_ranges[key] = [param_ranges[key]]

    return [dict(zip(param_ranges, v)) for v in
            product(*param_ranges.values())]


Instruction:
Can you generate the documentation for the following Python 3 function
def get_command_from_result(script, result, debug=False):
    if not debug:
        command = "python waf --run \"" + script + " " + " ".join(
            ['--%s=%s' % (param, value) for param, value in
             result['params'].items()]) + "\""
    else:
        command = "python waf --run " + script + " --command-template=\"" +\
            "gdb --args %s " + " ".join(['--%s=%s' % (param, value) for
                                         param, value in
                                         result['params'].items()]) + "\""
    return command

Response: Returns the command that is needed to obtain a certain result.


Instruction:
Write a Python 3 function that can
try and automatically convert strings formatted as tables into nested objects.

Response:
def automatic_parser(result, dtypes={}, converters={}):
    """
    Try and automatically convert strings formatted as tables into nested
    list structures.

    Under the hood, this function essentially applies the genfromtxt function
    to all files in the output, and passes it the additional kwargs.

    Args:
      result (dict): the result to parse.
      dtypes (dict): a dictionary containing the dtype specification to perform
        parsing for each available filename. See the numpy genfromtxt
        documentation for more details on how to format these.
    """
    np.seterr(all='raise')
    parsed = {}

    for filename, contents in result['output'].items():
        if dtypes.get(filename) is None:
            dtypes[filename] = None
        if converters.get(filename) is None:
            converters[filename] = None

        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            parsed[filename] = np.genfromtxt(io.StringIO(contents),
                                             dtype=dtypes[filename],
                                             converters=converters[filename]
                                             ).tolist()

    return parsed


Instruction:
Can you generate the documentation for the following Python 3 function
def new(cls, ns_path, script, campaign_dir, runner_type='Auto',
            overwrite=False, optimized=True, check_repo=True):
        """
        Create a new campaign from an ns-3 installation and a campaign
        directory.

        This method will create a DatabaseManager, which will install a
        database in the specified campaign_dir. If a database is already
        available at the ns_path described in the specified campaign_dir and
        its configuration matches config, this instance is used instead. If the
        overwrite argument is set to True instead, the specified directory is
        wiped and a new campaign is created in its place.

        Furthermore, this method will initialize a SimulationRunner, of type
        specified by the runner_type parameter, which will be locked on the
        ns-3 installation at ns_path and set up to run the desired script.

        Finally, note that creation of a campaign requires a git repository to
        be initialized at the specified ns_path. This will allow SEM to save
        the commit at which the simulations are run, enforce reproducibility
        and avoid mixing results coming from different versions of ns-3 and its
        libraries.

        Args:
            ns_path (str): path to the ns-3 installation to employ in this
                campaign.
            script (str): ns-3 script that will be executed to run simulations.
            campaign_dir (str): path to the directory in which to save the
                simulation campaign database.
            runner_type (str): implementation of the SimulationRunner to use.
                Value can be: SimulationRunner (for running sequential
                simulations locally), ParallelRunner (for running parallel
                simulations locally), GridRunner (for running simulations using
                a DRMAA-compatible parallel task scheduler). Use Auto to
                automatically pick the best runner.
            overwrite (bool): whether to overwrite already existing
                campaign_dir folders. This deletes the directory if and only if
                it only contains files that were detected to be created by sem.
            optimized (bool): whether to configure the runner to employ an
                optimized ns-3 build.
        """
        # Convert paths to be absolute
        ns_path = os.path.abspath(ns_path)
        campaign_dir = os.path.abspath(campaign_dir)

        # Verify if the specified campaign is already available
        if Path(campaign_dir).exists() and not overwrite:
            # Try loading
            manager = CampaignManager.load(campaign_dir, ns_path,
                                           runner_type=runner_type,
                                           optimized=optimized,
                                           check_repo=check_repo)

            if manager.db.get_script() == script:
                return manager
            else:
                del manager

        # Initialize runner
        runner = CampaignManager.create_runner(ns_path, script,
                                               runner_type=runner_type,
                                               optimized=optimized)

        # Get list of parameters to save in the DB
        params = runner.get_available_parameters()

        # Get current commit
        commit = ""
        if check_repo:
            from git import Repo, exc
            commit = Repo(ns_path).head.commit.hexsha

        # Create a database manager from the configuration
        db = DatabaseManager.new(script=script,
                                 params=params,
                                 commit=commit,
                                 campaign_dir=campaign_dir,
                                 overwrite=overwrite)

        return cls(db, runner, check_repo)

Response:
Creates a new instance of the type
            with the given ns - path script and campaign_dir.


Instruction:
How would you code a function in Python 3 to
load an existing simulation campaign from a directory containing a ns - 3 installation.

Response:
def load(cls, campaign_dir, ns_path=None, runner_type='Auto',
             optimized=True, check_repo=True):
        """
        Load an existing simulation campaign.

        Note that specifying an ns-3 installation is not compulsory when using
        this method: existing results will be available, but in order to run
        additional simulations it will be necessary to specify a
        SimulationRunner object, and assign it to the CampaignManager.

        Args:
            campaign_dir (str): path to the directory in which to save the
                simulation campaign database.
            ns_path (str): path to the ns-3 installation to employ in this
                campaign.
            runner_type (str): implementation of the SimulationRunner to use.
                Value can be: SimulationRunner (for running sequential
                simulations locally), ParallelRunner (for running parallel
                simulations locally), GridRunner (for running simulations using
                a DRMAA-compatible parallel task scheduler).
            optimized (bool): whether to configure the runner to employ an
                optimized ns-3 build.
        """
        # Convert paths to be absolute
        if ns_path is not None:
            ns_path = os.path.abspath(ns_path)
        campaign_dir = os.path.abspath(campaign_dir)

        # Read the existing configuration into the new DatabaseManager
        db = DatabaseManager.load(campaign_dir)
        script = db.get_script()

        runner = None
        if ns_path is not None:
            runner = CampaignManager.create_runner(ns_path, script,
                                                   runner_type, optimized)

        return cls(db, runner, check_repo)


Instruction:
Make a summary of the following Python 3 code
def create_runner(ns_path, script, runner_type='Auto',
                      optimized=True):
        """
        Create a SimulationRunner from a string containing the desired
        class implementation, and return it.

        Args:
            ns_path (str): path to the ns-3 installation to employ in this
                SimulationRunner.
            script (str): ns-3 script that will be executed to run simulations.
            runner_type (str): implementation of the SimulationRunner to use.
                Value can be: SimulationRunner (for running sequential
                simulations locally), ParallelRunner (for running parallel
                simulations locally), GridRunner (for running simulations using
                a DRMAA-compatible parallel task scheduler). If Auto,
                automatically pick the best available runner (GridRunner if
                DRMAA is available, ParallelRunner otherwise).
            optimized (bool): whether to configure the runner to employ an
                optimized ns-3 build.
        """
        # locals() contains a dictionary pairing class names with class
        # objects: we can create the object using the desired class starting
        # from its name.
        if runner_type == 'Auto' and DRMAA_AVAILABLE:
            runner_type = 'GridRunner'
        elif runner_type == 'Auto':
            runner_type = 'ParallelRunner'

        return locals().get(runner_type,
                            globals().get(runner_type))(
                                ns_path, script, optimized=optimized)

Response:
Create a SimulationRunner from a string containing the desired
        class implementation and return it.


Instruction:
Can you implement a function in Python 3 that
runs several simulations specified by a list of parameter combinations.

Response:
def run_simulations(self, param_list, show_progress=True):
        """
        Run several simulations specified by a list of parameter combinations.

        Note: this function does not verify whether we already have the
        required simulations in the database - it just runs all the parameter
        combinations that are specified in the list.

        Args:
            param_list (list): list of parameter combinations to execute.
                Items of this list are dictionaries, with one key for each
                parameter, and a value specifying the parameter value (which
                can be either a string or a number).
            show_progress (bool): whether or not to show a progress bar with
                percentage and expected remaining time.
        """

        # Make sure we have a runner to run simulations with.
        # This can happen in case the simulation campaign is loaded and not
        # created from scratch.
        if self.runner is None:
            raise Exception("No runner was ever specified"
                            " for this CampaignManager.")

        # Return if the list is empty
        if param_list == []:
            return

        # Check all parameter combinations fully specify the desired simulation
        desired_params = self.db.get_params()
        for p in param_list:
            # Besides the parameters that were actually passed, we add the ones
            # that are always available in every script
            passed = list(p.keys())
            available = ['RngRun'] + desired_params
            if set(passed) != set(available):
                raise ValueError("Specified parameter combination does not "
                                 "match the supported parameters:\n"
                                 "Passed: %s\nSupported: %s" %
                                 (sorted(passed), sorted(available)))

        # Check that the current repo commit corresponds to the one specified
        # in the campaign
        if self.check_repo:
            self.check_repo_ok()

        # Build ns-3 before running any simulations
        # At this point, we can assume the project was already configured
        self.runner.configure_and_build(skip_configuration=True)

        # Shuffle simulations
        # This mixes up long and short simulations, and gives better time
        # estimates.
        shuffle(param_list)

        # Offload simulation execution to self.runner
        # Note that this only creates a generator for the results, no
        # computation is performed on this line.
        results = self.runner.run_simulations(param_list,
                                              self.db.get_data_dir())

        # Wrap the result generator in the progress bar generator.
        if show_progress:
            result_generator = tqdm(results, total=len(param_list),
                                    unit='simulation',
                                    desc='Running simulations')
        else:
            result_generator = results

        # Insert result object in db. Using the generator here ensures we
        # save results as they are finalized by the SimulationRunner, and
        # that they are kept even if execution is terminated abruptly by
        # crashes or by a KeyboardInterrupt.
        for result in result_generator:
            self.db.insert_result(result)


Instruction:
How would you explain what the following Python 3 function does
def get_missing_simulations(self, param_list, runs=None):

        params_to_simulate = []

        if runs is not None:  # Get next available runs from the database
            next_runs = self.db.get_next_rngruns()
            available_params = [r['params'] for r in self.db.get_results()]
            for param_comb in param_list:
                # Count how many param combinations we found, and remove them
                # from the list of available_params for faster searching in the
                # future
                needed_runs = runs
                for i, p in enumerate(available_params):
                    if param_comb == {k: p[k] for k in p.keys() if k != "RngRun"}:
                        needed_runs -= 1
                new_param_combs = []
                for needed_run in range(needed_runs):
                    # Here it's important that we make copies of the
                    # dictionaries, so that if we modify one we don't modify
                    # the others. This is necessary because after this step,
                    # typically, we will add the RngRun key which must be
                    # different for each copy.
                    new_param = deepcopy(param_comb)
                    new_param['RngRun'] = next(next_runs)
                    new_param_combs += [new_param]
                params_to_simulate += new_param_combs
        else:
            for param_comb in param_list:
                if not self.db.get_results(param_comb):
                    params_to_simulate += [param_comb]

        return params_to_simulate

Response: Returns a list of the simulations among the required ones that are not available in the database.


Instruction:
How would you explain what the following Python 3 function does
def run_missing_simulations(self, param_list, runs=None):
        # If we are passed a dictionary, we need to expand this
        if isinstance(param_list, dict):
            param_list = list_param_combinations(param_list)

        # If we are passed a list already, just run the missing simulations
        self.run_simulations(
            self.get_missing_simulations(param_list, runs))

Response: This function runs the missing simulations from the parameter list that are not yet available in the database.


Instruction:
Make a summary of the following Python 3 code
def get_results_as_numpy_array(self, parameter_space,
                                   result_parsing_function, runs):
        """
        Return the results relative to the desired parameter space in the form
        of a numpy array.

        Args:
            parameter_space (dict): dictionary containing
                parameter/list-of-values pairs.
            result_parsing_function (function): user-defined function, taking a
                result dictionary as argument, that can be used to parse the
                result files and return a list of values.
            runs (int): number of runs to gather for each parameter
                combination.
        """
        return np.array(self.get_space(self.db.get_complete_results(), {},
                                       parameter_space, runs,
                                       result_parsing_function))

Response:
Returns the results of the a
                as a numpy array.


Instruction:
Can you tell what is the following Python 3 function doing
def save_to_mat_file(self, parameter_space,
                         result_parsing_function,
                         filename, runs):
        """
        Return the results relative to the desired parameter space in the form
        of a .mat file.

        Args:
            parameter_space (dict): dictionary containing
                parameter/list-of-values pairs.
            result_parsing_function (function): user-defined function, taking a
                result dictionary as argument, that can be used to parse the
                result files and return a list of values.
            filename (path): name of output .mat file.
            runs (int): number of runs to gather for each parameter
                combination.
        """

        # Make sure all values are lists
        for key in parameter_space:
            if not isinstance(parameter_space[key], list):
                parameter_space[key] = [parameter_space[key]]

        # Add a dimension label for each non-singular dimension
        dimension_labels = [{key: str(parameter_space[key])} for key in
                            parameter_space.keys() if len(parameter_space[key])
                            > 1] + [{'runs': range(runs)}]

        # Create a list of the parameter names

        return savemat(
            filename,
            {'results':
             self.get_results_as_numpy_array(parameter_space,
                                             result_parsing_function,
                                             runs=runs),
             'dimension_labels': dimension_labels})

Response: Save the results of the current run to a. mat file.


Instruction:
How would you implement a function in Python 3 that
saves results to a numpy array file format.

Response:
def save_to_npy_file(self, parameter_space,
                         result_parsing_function,
                         filename, runs):
        """
        Save results to a numpy array file format.
        """
        np.save(filename, self.get_results_as_numpy_array(
            parameter_space, result_parsing_function, runs=runs))


Instruction:
Write a Python 3 function for
saving results to a folder structure.

Response:
def save_to_folders(self, parameter_space, folder_name, runs):
        """
        Save results to a folder structure.
        """
        self.space_to_folders(self.db.get_results(), {}, parameter_space, runs,
                              folder_name)


Instruction:
Can you tell what is the following Python 3 function doing
def space_to_folders(self, current_result_list, current_query, param_space,
                         runs, current_directory):
        """
        Convert a parameter space specification to a directory tree with a
        nested structure.
        """
        # Base case: we iterate over the runs and copy files in the final
        # directory.
        if not param_space:
            for run, r in enumerate(current_result_list[:runs]):
                files = self.db.get_result_files(r)
                new_dir = os.path.join(current_directory, "run=%s" % run)
                os.makedirs(new_dir, exist_ok=True)
                for filename, filepath in files.items():
                    shutil.copyfile(filepath, os.path.join(new_dir, filename))
            return

        [key, value] = list(param_space.items())[0]
        # Iterate over dictionary values
        for v in value:
            next_query = deepcopy(current_query)
            temp_query = deepcopy(current_query)

            # For each list, recur 'fixing' that dimension.
            next_query[key] = v  # Update query

            # Create folder
            folder_name = ("%s=%s" % (key, v)).replace('/', '_')
            new_dir = os.path.join(current_directory, folder_name)
            os.makedirs(new_dir, exist_ok=True)

            next_param_space = deepcopy(param_space)
            del(next_param_space[key])

            temp_query[key] = v
            temp_result_list = [r for r in current_result_list if
                                self.satisfies_query(r, temp_query)]

            self.space_to_folders(temp_result_list, next_query,
                                  next_param_space, runs, new_dir)

Response: Convert a parameter space specification to a nested structure with a nested structure.


Instruction:
Write a Python 3 script to
return the results of the user - defined function in the parameter space in the form of an xarray data structure.

Response:
def get_results_as_xarray(self, parameter_space,
                              result_parsing_function,
                              output_labels, runs):
        """
        Return the results relative to the desired parameter space in the form
        of an xarray data structure.

        Args:
            parameter_space (dict): The space of parameters to export.
            result_parsing_function (function): user-defined function, taking a
                result dictionary as argument, that can be used to parse the
                result files and return a list of values.
            output_labels (list): a list of labels to apply to the results
                dimensions, output by the result_parsing_function.
            runs (int): the number of runs to export for each parameter
                combination.
        """
        np_array = np.array(
            self.get_space(
                self.db.get_complete_results(), {},
                collections.OrderedDict([(k, v) for k, v in
                                         parameter_space.items()]),
                runs, result_parsing_function))

        # Create a parameter space only containing the variable parameters
        clean_parameter_space = collections.OrderedDict(
            [(k, v) for k, v in parameter_space.items()])

        clean_parameter_space['runs'] = range(runs)

        if isinstance(output_labels, list):
            clean_parameter_space['metrics'] = output_labels

        xr_array = xr.DataArray(np_array, coords=clean_parameter_space,
                                dims=list(clean_parameter_space.keys()))

        return xr_array


Instruction:
Can you generate a brief explanation for the following Python 3 code
def get_space(self, current_result_list, current_query, param_space, runs,
                  result_parsing_function):
        """
        Convert a parameter space specification to a nested array structure
        representing the space. In other words, if the parameter space is::

            param_space = {
                'a': [1, 2],
                'b': [3, 4]
            }

        the function will return a structure like the following::

            [
                [
                    {'a': 1, 'b': 3},
                    {'a': 1, 'b': 4}
                ],
                [
                    {'a': 2, 'b': 3},
                    {'a': 2, 'b': 4}
                ]
            ]

        where the first dimension represents a, and the second dimension
        represents b. This nested-array structure can then be easily converted
        to a numpy array via np.array().

        Args:
            current_query (dict): the query to apply to the structure.
            param_space (dict): representation of the parameter space.
            result_parsing_function (function): user-defined function to call
                on results, typically used to parse data and outputting
                metrics.
            runs (int): the number of runs to query for each parameter
                combination.
        """
        if result_parsing_function is None:
            result_parsing_function = CampaignManager.files_in_dictionary
            # Note that this function operates recursively.

        # Base case
        if not param_space:
            results = [r for r in current_result_list if
                       self.satisfies_query(r, current_query)]
            parsed = []
            for r in results[:runs]:
                parsed.append(result_parsing_function(r))

            return parsed

        space = []
        [key, value] = list(param_space.items())[0]
        # Iterate over dictionary values
        for v in value:
            next_query = deepcopy(current_query)
            temp_query = deepcopy(current_query)
            # For each list, recur 'fixing' that dimension.
            next_query[key] = v
            next_param_space = deepcopy(param_space)
            del(next_param_space[key])
            temp_query[key] = v
            temp_result_list = [r for r in current_result_list if
                                self.satisfies_query(r, temp_query)]
            space.append(self.get_space(temp_result_list, next_query,
                                        next_param_space, runs,
                                        result_parsing_function))
        return space

Response: This function returns a nested array structure representing the parameter space.


Instruction:
Make a summary of the following Python 3 code
def check_repo_ok(self):
        from git import Repo, exc
        # Check that git is at the expected commit and that the repo is not
        # dirty
        if self.runner is not None:
            path = self.runner.path
            try:
                repo = Repo(path)
            except(exc.InvalidGitRepositoryError):
                raise Exception("No git repository detected.\nIn order to "
                                "use SEM and its reproducibility enforcing "
                                "features, please create a git repository at "
                                "the root of your ns-3 project.")
            current_commit = repo.head.commit.hexsha
            campaign_commit = self.db.get_commit()

            if repo.is_dirty(untracked_files=True):
                raise Exception("ns-3 repository is not clean")

            if current_commit != campaign_commit:
                raise Exception("ns-3 repository is on a different commit "
                                "from the one specified in the campaign")

Response: Check that the ns - 3 repository is clean and that the commit of the one - item repository is the same as the campaign s HEAD commit.


Instruction:
Implement a Python 3 function for
viewing results of simulations.

Response:
def view(results_dir, result_id, hide_simulation_output, parameters, no_pager):
    """
    View results of simulations.
    """

    campaign = sem.CampaignManager.load(results_dir)

    # Pick the most appropriate function based on the level of detail we want
    if hide_simulation_output:
        get_results_function = campaign.db.get_results
    else:
        get_results_function = campaign.db.get_complete_results

    # If a result id was specified, just query for that result
    if result_id:
        output = '\n\n\n'.join([pprint.pformat(item) for item in
                                get_results_function(result_id=result_id)])
    else:

        [params, defaults] = zip(*get_params_and_defaults(
            campaign.db.get_params(), campaign.db))

        if not parameters:
            # Convert to string
            string_defaults = list()
            for idx, d in enumerate(defaults):
                string_defaults.append(str(d))

            script_params = query_parameters(params, string_defaults)
        else:
            script_params = import_parameters_from_file(parameters)

        # Perform the search
        output = '\n\n\n'.join([pprint.pformat(item) for item in
                                get_results_function(script_params)])

    # Print the results
    if no_pager:
        click.echo(output)
    else:
        click.echo_via_pager(output)


Instruction:
Explain what the following Python 3 code does
def command(results_dir, result_id):
    campaign = sem.CampaignManager.load(results_dir)

    result = campaign.db.get_results(result_id=result_id)[0]

    click.echo("Simulation command:")
    click.echo(sem.utils.get_command_from_result(campaign.db.get_script(),
                                                 result))
    click.echo("Debug command:")
    click.echo(sem.utils.get_command_from_result(campaign.db.get_script(),
                                                 result,
                                                 debug=True))

Response: Print the command that needs to be used to reproduce a result.


Instruction:
Make a summary of the following Python 3 code
def export(results_dir, filename, do_not_try_parsing, parameters):

    # Get the extension
    _, extension = os.path.splitext(filename)

    campaign = sem.CampaignManager.load(results_dir)

    [params, defaults] = zip(*get_params_and_defaults(campaign.db.get_params(),
                                                      campaign.db))

    if do_not_try_parsing:
        parsing_function = None
    else:
        parsing_function = sem.utils.automatic_parser

    if not parameters:
        # Convert to string
        string_defaults = list()
        for idx, d in enumerate(defaults):
            string_defaults.append(str(d))
        parameter_query = query_parameters(params, string_defaults)
    else:
        # Import specified parameter file
        parameter_query = import_parameters_from_file(parameters)

    if extension == ".mat":
        campaign.save_to_mat_file(parameter_query, parsing_function, filename,
                                  runs=click.prompt("Runs", type=int))
    elif extension == ".npy":
        campaign.save_to_npy_file(parameter_query, parsing_function, filename,
                                  runs=click.prompt("Runs", type=int))
    elif extension == "":
        campaign.save_to_folders(parameter_query, filename,
                                 runs=click.prompt("Runs", type=int))
    else:  # Unrecognized format
        raise ValueError("Format not recognized")

Response: Export the results to a file.


Instruction:
How would you code a function in Python 3 to
merge multiple results folder into one by copying the results over to a new folder.

Response:
def merge(move, output_dir, sources):
    """
    Merge multiple results folder into one, by copying the results over to a new folder.

    For a faster operation (which on the other hand destroys the campaign data
    if interrupted), the move option can be used to directly move results to
    the new folder.
    """
    # Get paths for all campaign JSONS
    jsons = []
    for s in sources:
        filename = "%s.json" % os.path.split(s)[1]
        jsons += [os.path.join(s, filename)]

    # Check that the configuration for all campaigns is the same
    reference_config = TinyDB(jsons[0]).table('config')
    for j in jsons[1:]:
        for i, j in zip(reference_config.all(), TinyDB(j).table('config').all()):
            assert i == j

    # Create folders for new results directory
    filename = "%s.json" % os.path.split(output_dir)[1]
    output_json = os.path.join(output_dir, filename)
    output_data = os.path.join(output_dir, 'data')
    os.makedirs(output_data)

    # Create new database
    db = TinyDB(output_json)
    db.table('config').insert_multiple(reference_config.all())

    # Import results from all databases to the new JSON file
    for s in sources:
        filename = "%s.json" % os.path.split(s)[1]
        current_db = TinyDB(os.path.join(s, filename))
        db.table('results').insert_multiple(current_db.table('results').all())

    # Copy or move results to new data folder
    for s in sources:
        for r in glob.glob(os.path.join(s, 'data/*')):
            basename = os.path.basename(r)
            if move:
                shutil.move(r, os.path.join(output_data, basename))
            else:
                shutil.copytree(r, os.path.join(output_data, basename))

    if move:
        for s in sources:
            shutil.rmtree(os.path.join(s, 'data/*'))
            shutil.rmtree(os.path.join(s, "%s.json" % os.path.split(s)[1]))
            shutil.rmtree(s)


Instruction:
Can you generate the documentation for the following Python 3 function
def get_params_and_defaults(param_list, db):
    return [[p, d] for p, d in db.get_all_values_of_all_params().items()]

Response: Returns a list of parameter pairs from the database.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def query_parameters(param_list, defaults=None):

    script_params = collections.OrderedDict([k, []] for k in param_list)

    for param, default in zip(list(script_params.keys()), defaults):
        user_input = click.prompt("%s" % param, default=default)
        script_params[param] = ast.literal_eval(user_input)

    return script_params

Response: Ask the user for parameters.


Instruction:
Implement a Python 3 function for
trying importing a parameter dictionary from file.

Response:
def import_parameters_from_file(parameters_file):
    """
    Try importing a parameter dictionary from file.

    We expect values in parameters_file to be defined as follows:
        param1: value1
        param2: [value2, value3]
    """
    params = {}

    with open(parameters_file, 'r') as f:
        matches = re.findall('(.*): (.*)', f.read())

    for m in matches:
        params[m[0]] = ast.literal_eval(m[1])

    return params


Instruction:
Write a Python 3 function that can
launch a single simulation using the specified parameter list.

Response:
def launch_simulation(self, parameter):
        """
        Launch a single simulation, using SimulationRunner's facilities.

        This function is used by ParallelRunner's run_simulations to map
        simulation running over the parameter list.

        Args:
            parameter (dict): the parameter combination to simulate.
        """
        return next(SimulationRunner.run_simulations(self, [parameter],
                                                     self.data_folder))


Instruction:
Write a Python 3 function for
aliasing of helper. string. serialization. json. stringify

Response:
def stringify(self, obj, beautify=False, raise_exception=False):
        """Alias of helper.string.serialization.json.stringify"""

        return self.helper.string.serialization.json.stringify(
            obj=obj,
            beautify=beautify,
            raise_exception=raise_exception)


Instruction:
Create a Python 3 function to
alias of helper. string. serialization. json. parse

Response:
def parse(self, text, encoding='utf8', raise_exception=False):
        """Alias of helper.string.serialization.json.parse"""

        return self.helper.string.serialization.json.parse(
            text=text,
            encoding=encoding,
            raise_exception=raise_exception)


Instruction:
Can you write a function in Python 3 where it
initializes a new instance of the class with the given script commit and parameters.

Response:
def new(cls, script, commit, params, campaign_dir, overwrite=False):
        """
        Initialize a new class instance with a set configuration and filename.

        The created database has the same name of the campaign directory.

        Args:
            script (str): the ns-3 name of the script that will be used in this
                campaign;
            commit (str): the commit of the ns-3 installation that is used to
                run the simulations.
            params (list): a list of the parameters that can be used on the
                script.
            campaign_dir (str): The path of the file where to save the DB.
            overwrite (bool): Whether or not existing directories should be
                overwritten.

        """

        # We only accept absolute paths
        if not Path(campaign_dir).is_absolute():
            raise ValueError("Path is not absolute")

        # Make sure the directory does not exist already
        if Path(campaign_dir).exists() and not overwrite:
            raise FileExistsError("The specified directory already exists")
        elif Path(campaign_dir).exists() and overwrite:
            # Verify we are not deleting files belonging to the user
            campaign_dir_name = os.path.basename(campaign_dir)
            folder_contents = set(os.listdir(campaign_dir))
            allowed_files = set(
                ['data', '%s.json' % campaign_dir_name] +
                # Allow hidden files (like .DS_STORE in macos)
                [os.path.basename(os.path.normpath(f)) for f in
                 glob.glob(os.path.join(campaign_dir, ".*"))])

            if(not folder_contents.issubset(allowed_files)):
                raise ValueError("The specified directory cannot be overwritten"
                                 " because it contains user files.")
            # This operation destroys data.
            shutil.rmtree(campaign_dir)

        # Create the directory and database file in it
        # The indent and separators ensure the database is human readable.
        os.makedirs(campaign_dir)
        tinydb = TinyDB(os.path.join(campaign_dir, "%s.json" %
                                     os.path.basename(campaign_dir)))

        # Save the configuration in the database
        config = {
            'script': script,
            'commit': commit,
            'params': sorted(params)
        }
        tinydb.table('config').insert(config)

        return cls(tinydb, campaign_dir)


Instruction:
Implement a Python 3 function for
initializing from an existing database.

Response:
def load(cls, campaign_dir):
        """
        Initialize from an existing database.

        It is assumed that the database json file has the same name as its
        containing folder.

        Args:
            campaign_dir (str): The path to the campaign directory.
        """

        # We only accept absolute paths
        if not Path(campaign_dir).is_absolute():
            raise ValueError("Path is not absolute")

        # Verify file exists
        if not Path(campaign_dir).exists():
            raise ValueError("Directory does not exist")

        # Extract filename from campaign dir
        filename = "%s.json" % os.path.split(campaign_dir)[1]
        filepath = os.path.join(campaign_dir, filename)

        try:
            # Read TinyDB instance from file
            tinydb = TinyDB(filepath)

            # Make sure the configuration is a valid dictionary
            assert set(
                tinydb.table('config').all()[0].keys()) == set(['script',
                                                                'params',
                                                                'commit'])
        except:
            # Remove the database instance created by tinydb
            os.remove(filepath)
            raise ValueError("Specified campaign directory seems corrupt")

        return cls(tinydb, campaign_dir)


Instruction:
How would you code a function in Python 3 to
yield the next RngRun values that can be used in this campaign.

Response:
def get_next_rngruns(self):
        """
        Yield the next RngRun values that can be used in this campaign.
        """
        available_runs = [result['params']['RngRun'] for result in
                          self.get_results()]
        yield from DatabaseManager.get_next_values(available_runs)


Instruction:
Write a Python 3 script for
inserting a new result in the database.

Response:
def insert_result(self, result):
        """
        Insert a new result in the database.

        This function also verifies that the result dictionaries saved in the
        database have the following structure (with {'a': 1} representing a
        dictionary, 'a' a key and 1 its value)::

            {
                'params': {
                            'param1': value1,
                            'param2': value2,
                            ...
                            'RngRun': value3
                           },
                'meta': {
                          'elapsed_time': value4,
                          'id': value5
                        }
            }

        Where elapsed time is a float representing the seconds the simulation
        execution took, and id is a UUID uniquely identifying the result, and
        which is used to locate the output files in the campaign_dir/data
        folder.
        """

        # This dictionary serves as a model for how the keys in the newly
        # inserted result should be structured.
        example_result = {
            'params': {k: ['...'] for k in self.get_params() + ['RngRun']},
            'meta': {k: ['...'] for k in ['elapsed_time', 'id']},
        }

        # Verify result format is correct
        if not(DatabaseManager.have_same_structure(result, example_result)):
            raise ValueError(
                '%s:\nExpected: %s\nGot: %s' % (
                    "Result dictionary does not correspond to database format",
                    pformat(example_result, depth=1),
                    pformat(result, depth=1)))

        # Insert result
        self.db.table('results').insert(result)


Instruction:
Here you have a function in Python 3, explain what it does
def get_results(self, params=None, result_id=None):

        # In this case, return all results
        # A cast to dict is necessary, since self.db.table() contains TinyDB's
        # Document object (which is simply a wrapper for a dictionary, thus the
        # simple cast).
        if result_id is not None:
            return [dict(i) for i in self.db.table('results').all() if
                    i['meta']['id'] == result_id]

        if params is None:
            return [dict(i) for i in self.db.table('results').all()]

        # Verify parameter format is correct
        all_params = set(['RngRun'] + self.get_params())
        param_subset = set(params.keys())
        if (not all_params.issuperset(param_subset)):
            raise ValueError(
                '%s:\nParameters: %s\nQuery: %s' % (
                    'Specified parameter keys do not match database format',
                    all_params,
                    param_subset))

        # Convert values that are not lists into lists to later perform
        # iteration over values more naturally. Perform this on a new
        # dictionary not to modify the original copy.
        query_params = {}
        for key in params:
            if not isinstance(params[key], list):
                query_params[key] = [params[key]]
            else:
                query_params[key] = params[key]

        # Handle case where query params has no keys
        if not query_params.keys():
            return [dict(i) for i in self.db.table('results').all()]

        # Create the TinyDB query
        # In the docstring example above, this is equivalent to:
        # AND(OR(param1 == value1), OR(param2 == value2, param2 == value3))
        query = reduce(and_, [reduce(or_, [
            where('params')[key] == v for v in value]) for key, value in
                              query_params.items()])

        return [dict(i) for i in self.db.table('results').search(query)]

Response: Returns all the results available from the database that fulfill some parameter combinations.


Instruction:
Write a Python 3 script for
returning a dictionary containing filename values for each output file associated with an id.

Response:
def get_result_files(self, result):
        """
        Return a dictionary containing filename: filepath values for each
        output file associated with an id.

        Result can be either a result dictionary (e.g., obtained with the
        get_results() method) or a result id.
        """
        if isinstance(result, dict):
            result_id = result['meta']['id']
        else:  # Should already be a string containing the id
            result_id = result

        result_data_dir = os.path.join(self.get_data_dir(), result_id)

        filenames = next(os.walk(result_data_dir))[2]

        filename_path_pairs = [
            (f, os.path.join(self.get_data_dir(), result_id, f))
            for f in filenames]

        return {k: v for k, v in filename_path_pairs}


Instruction:
Can you generate a brief explanation for the following Python 3 code
def get_complete_results(self, params=None, result_id=None):

        if result_id is not None:
            results = deepcopy(self.get_results(result_id=result_id))
        else:
            results = deepcopy(self.get_results(params))

        for r in results:
            r['output'] = {}
            available_files = self.get_result_files(r['meta']['id'])
            for name, filepath in available_files.items():
                with open(filepath, 'r') as file_contents:
                    r['output'][name] = file_contents.read()

        return results

Response: Returns the results of the get_results function.


Instruction:
Write a Python 3 script for
removing all results from the database.

Response:
def wipe_results(self):
        """
        Remove all results from the database.

        This also removes all output files, and cannot be undone.
        """
        # Clean results table
        self.db.purge_table('results')

        # Get rid of contents of data dir
        map(shutil.rmtree, glob.glob(os.path.join(self.get_data_dir(), '*.*')))


Instruction:
Create a Python 3 function for
giving two dictionaries (possibly with other nested dictionaries as values), this function checks whether they have the same key structure. >>> from sem import DatabaseManager >>> d1 = {'a': 1, 'b': 2} >>> d2 = {'a': [], 'b': 3} >>> d3 = {'a': 4, 'c': 5} >>> DatabaseManager.have_same_structure(d1, d2) True >>> DatabaseManager.have_same_structure(d1, d3) False >>> d4 = {'a': {'c': 1}, 'b': 2} >>> d5 = {'a': {'c': 3}, 'b': 4} >>> d6 = {'a': {'c': 5, 'd': 6}, 'b': 7} >>> DatabaseManager.have_same_structure(d1, d4) False >>> DatabaseManager.have_same_structure(d4, d5) True >>> DatabaseManager.have_same_structure(d4, d6) False

Response:
def have_same_structure(d1, d2):
        """
        Given two dictionaries (possibly with other nested dictionaries as
        values), this function checks whether they have the same key structure.

        >>> from sem import DatabaseManager
        >>> d1 = {'a': 1, 'b': 2}
        >>> d2 = {'a': [], 'b': 3}
        >>> d3 = {'a': 4, 'c': 5}
        >>> DatabaseManager.have_same_structure(d1, d2)
        True
        >>> DatabaseManager.have_same_structure(d1, d3)
        False

        >>> d4 = {'a': {'c': 1}, 'b': 2}
        >>> d5 = {'a': {'c': 3}, 'b': 4}
        >>> d6 = {'a': {'c': 5, 'd': 6}, 'b': 7}
        >>> DatabaseManager.have_same_structure(d1, d4)
        False
        >>> DatabaseManager.have_same_structure(d4, d5)
        True
        >>> DatabaseManager.have_same_structure(d4, d6)
        False
        """
        # Keys of this level are the same
        if set(d1.keys()) != set(d2.keys()):
            return False

        # Check nested dictionaries
        for k1, k2 in zip(sorted(d1.keys()), sorted(d2.keys())):
            # If one of the values is a dictionary and the other is not
            if isinstance(d1[k1], dict) != isinstance(d2[k2], dict):
                return False
            # If both are dictionaries, recur
            elif isinstance(d1[k1], dict) and isinstance(d2[k2], dict):
                if not DatabaseManager.have_same_structure(d1[k1], d2[k2]):
                    return False

        return True


Instruction:
Here you have a function in Python 3, explain what it does
def get_all_values_of_all_params(self):

        values = collections.OrderedDict([[p, []] for p in
                                          sorted(self.get_params())])

        for result in self.get_results():
            for param in self.get_params():
                values[param] += [result['params'][param]]

        sorted_values = collections.OrderedDict([[k,
                                                 sorted(list(set(values[k])))]
                                                 for k in values.keys()])

        for k in sorted_values.keys():
            if sorted_values[k] == []:
                sorted_values[k] = None

        return sorted_values

Response: Returns a dictionary containing all values that are taken by all available parameters.


Instruction:
Write a Python 3 script to
serialize a single object into a string.

Response:
def serialize(self, obj, method='json', beautify=False, raise_exception=False):
        """Alias of helper.string.serialization.serialize"""

        return self.helper.string.serialization.serialize(
            obj=obj, method=method, beautify=beautify, raise_exception=raise_exception)


Instruction:
Here you have a function in Python 3, explain what it does
def deserialize(self, text, method='json', encoding='utf8', raise_exception=False):

        return self.helper.string.serialization.deserialize(
            text, method=method, encoding=encoding, raise_exception=raise_exception)

Response: Deserialize a string into a new object.


Instruction:
Write a Python 3 function that can
return a list of the parameters made available by the script.

Response:
def get_available_parameters(self):
        """
        Return a list of the parameters made available by the script.
        """

        # At the moment, we rely on regex to extract the list of available
        # parameters. A tighter integration with waf would allow for a more
        # natural extraction of the information.

        stdout = self.run_program("%s %s" % (self.script_executable,
                                             '--PrintHelp'),
                                  environment=self.environment,
                                  native_spec=BUILD_GRID_PARAMS)

        options = re.findall('.*Program\s(?:Arguments|Options):(.*)'
                             'General\sArguments.*',
                             stdout, re.DOTALL)

        if len(options):
            args = re.findall('.*--(.*?):.*', options[0], re.MULTILINE)
            return args
        else:
            return []


Instruction:
Implement a function in Python 3 to
run a program through the grid and returns the output.

Response:
def run_program(self, command, working_directory=os.getcwd(),
                    environment=None, cleanup_files=True,
                    native_spec="-l cputype=intel"):
        """
        Run a program through the grid, capturing the standard output.
        """
        try:
            s = drmaa.Session()
            s.initialize()
            jt = s.createJobTemplate()
            jt.remoteCommand = os.path.dirname(
                os.path.abspath(__file__)) + '/run_program.sh'
            jt.args = [command]

            if environment is not None:
                jt.jobEnvironment = environment

            jt.workingDirectory = working_directory
            jt.nativeSpecification = native_spec
            output_filename = os.path.join(working_directory, 'output.txt')
            jt.outputPath = ':' + output_filename
            jt.joinFiles = True

            jobid = s.runJob(jt)

            s.wait(jobid, drmaa.Session.TIMEOUT_WAIT_FOREVER)

            with open(output_filename, 'r') as output:
                stdout = output.read()

            # Clean up
            if cleanup_files:
                os.remove(output_filename)

        finally:
            try:
                s.control(drmaa.JOB_IDS_SESSION_ALL,
                          drmaa.JobControlAction.TERMINATE)
                s.synchronize([drmaa.JOB_IDS_SESSION_ALL], dispose=True)
                s.exit()
            except(drmaa.errors.NoActiveSessionException):
                pass

        return stdout


Instruction:
Can you generate the documentation for the following Python 3 function
def fill_labeled_holes(labels, mask=None, size_fn = None):
    '''Fill all background pixels that are holes inside the foreground

    A pixel is a hole inside a foreground object if

    * there is no path from the pixel to the edge AND

    * there is no path from the pixel to any other non-hole
      pixel AND

    * there is no path from the pixel to two similarly-labeled pixels that
      are adjacent to two differently labeled non-hole pixels.

    labels - the current labeling

    mask - mask of pixels to ignore

    size_fn - if not None, it is a function that takes a size and a boolean
              indicating whether it is foreground (True) or background (False)
              The function should return True to analyze and False to ignore

    returns a filled copy of the labels matrix
    '''
    #
    # The algorithm:
    #
    # Label the background to get distinct background objects
    # Construct a graph of both foreground and background objects.
    # Walk the graph according to the rules.
    #
    labels_type = labels.dtype
    background = labels == 0
    if mask is not None:
        background &= mask

    blabels, count = scind.label(background, four_connect)
    labels = labels.copy().astype(int)
    lcount = np.max(labels)
    labels[blabels != 0] = blabels[blabels != 0] + lcount + 1
    lmax = lcount + count + 1
    is_not_hole = np.ascontiguousarray(np.zeros(lmax + 1, np.uint8))
    #
    # Find the indexes on the edge and use to populate the to-do list
    #
    to_do = np.unique(np.hstack((
        labels[0, :], labels[:, 0], labels[-1, :], labels[:, -1])))
    to_do = to_do[to_do != 0]
    is_not_hole[to_do] = True
    to_do = list(to_do)
    #
    # An array that names the first non-hole object
    #
    adjacent_non_hole = np.ascontiguousarray(np.zeros(lmax + 1), np.uint32)
    #
    # Find all 4-connected adjacent pixels
    # Note that there will be some i, j not in j, i
    #
    i = np.hstack([labels[:-1, :].flatten(), labels[:, :-1].flatten()])
    j = np.hstack([labels[1:, :].flatten(), labels[:, 1:].flatten()])
    i, j = i[i!=j], j[i!=j]
    if (len(i)) > 0:
        order = np.lexsort((j, i))
        i = i[order]
        j = j[order]
        # Remove duplicates and stack to guarantee that j, i is in i, j
        first = np.hstack([[True], (i[:-1] != i[1:]) | (j[:-1] != j[1:])])
        i, j = np.hstack((i[first], j[first])), np.hstack((j[first], i[first]))
        # Remove dupes again. (much shorter)
        order = np.lexsort((j, i))
        i = i[order]
        j = j[order]
        first = np.hstack([[True], (i[:-1] != i[1:]) | (j[:-1] != j[1:])])
        i, j = i[first], j[first]
        #
        # Now we make a ragged array of i and j
        #
        i_count = np.bincount(i)
        if len(i_count) < lmax + 1:
            i_count = np.hstack((i_count, np.zeros(lmax + 1 - len(i_count), int)))
        indexer = Indexes([i_count])
        #
        # Filter using the size function passed, if any
        #
        if size_fn is not None:
            areas = np.bincount(labels.flatten())
            for ii, area in enumerate(areas):
                if (ii > 0 and area > 0 and not is_not_hole[ii] and
                    not size_fn(area, ii <= lcount)):
                    is_not_hole[ii] = True
                    to_do.append(ii)

        to_do_count = len(to_do)
        if len(to_do) < len(is_not_hole):
            to_do += [ 0 ] * (len(is_not_hole) - len(to_do))
        to_do = np.ascontiguousarray(np.array(to_do), np.uint32)
        fill_labeled_holes_loop(
            np.ascontiguousarray(i, np.uint32),
            np.ascontiguousarray(j, np.uint32),
            np.ascontiguousarray(indexer.fwd_idx, np.uint32),
            np.ascontiguousarray(i_count, np.uint32),
            is_not_hole, adjacent_non_hole, to_do, lcount, to_do_count)
    #
    # Make an array that assigns objects to themselves and background to 0
    #
    new_indexes = np.arange(len(is_not_hole)).astype(np.uint32)
    new_indexes[(lcount+1):] = 0
    #
    # Fill the holes by replacing the old value by the value of the
    # enclosing object.
    #
    is_not_hole = is_not_hole.astype(bool)
    new_indexes[~is_not_hole] = adjacent_non_hole[~ is_not_hole]
    if mask is not None:
        labels[mask] = new_indexes[labels[mask]]
    else:
        labels = new_indexes[labels]
    return labels.astype(labels_type)

Response: Fill all background pixels that are holes inside the foreground object.


Instruction:
Make a summary of the following Python 3 code
def adjacent(labels):
    '''Return a binary mask of all pixels which are adjacent to a pixel of
       a different label.

    '''
    high = labels.max()+1
    if high > np.iinfo(labels.dtype).max:
        labels = labels.astype(np.int)
    image_with_high_background = labels.copy()
    image_with_high_background[labels == 0] = high
    min_label = scind.minimum_filter(image_with_high_background,
                                     footprint=np.ones((3,3),bool),
                                     mode = 'constant',
                                     cval = high)
    max_label = scind.maximum_filter(labels,
                                     footprint=np.ones((3,3),bool),
                                     mode = 'constant',
                                     cval = 0)
    return (min_label != max_label) & (labels > 0)

Response:
Return a binary mask of all pixels which are adjacent to a pixel of
       a different label.


Instruction:
Can you generate the documentation for the following Python 3 function
def binary_shrink_old(image, iterations=-1):
    global binary_shrink_top_right, binary_shrink_bottom_left
    if binary_shrink_top_right is None:
        #
        # None of these patterns can remove both of two isolated
        # eight-connected pixels. Taken together, they can remove any
        # pixel touching a background pixel.
        #
        # The top right pixels:
        #
        # 0xx
        # ..0
        # ...
        #
        binary_shrink_top_right = make_table(False,
                                             np.array([[0,0,0],
                                                       [0,1,0],
                                                       [0,1,0]],bool),
                                             np.array([[1,1,1],
                                                       [0,1,0],
                                                       [0,1,0]],bool))
        binary_shrink_top_right &= make_table(False,
                                              np.array([[0,0,0],
                                                        [0,1,0],
                                                        [1,0,0]], bool),
                                              np.array([[1,1,1],
                                                        [0,1,1],
                                                        [1,0,1]], bool))
        binary_shrink_top_right &= make_table(False,
                                              np.array([[0,0,0],
                                                        [1,1,0],
                                                        [0,0,0]], bool),
                                              np.array([[0,0,1],
                                                        [1,1,1],
                                                        [0,0,1]], bool))
        binary_shrink_top_right &= make_table(False,
                                              np.array([[0,0,0],
                                                        [1,1,0],
                                                        [0,1,1]], bool),
                                              np.array([[0,0,1],
                                                        [1,1,1],
                                                        [0,1,0]], bool))
        binary_shrink_top_right &= make_table(False,
                                              np.array([[0,0,0],
                                                        [0,1,0],
                                                        [0,0,1]], bool),
                                              np.array([[1,1,1],
                                                        [1,1,0],
                                                        [1,0,1]], bool))
        binary_shrink_top_right &= make_table(False,
                                              np.array([[0,0,0],
                                                        [0,1,0],
                                                        [1,1,1]], bool),
                                              np.array([[1,1,1],
                                                        [1,1,0],
                                                        [0,1,1]], bool))
        #
        # bottom left pixels
        #
        # ...
        # 0..
        # xx0
        binary_shrink_bottom_left = make_table(False,
                                               np.array([[0,1,0],
                                                         [0,1,0],
                                                         [0,0,0]],bool),
                                               np.array([[0,1,0],
                                                         [0,1,0],
                                                         [1,1,1]],bool))
        binary_shrink_bottom_left &= make_table(False,
                                                np.array([[0,0,1],
                                                          [0,1,0],
                                                          [0,0,0]], bool),
                                                np.array([[1,0,1],
                                                          [1,1,0],
                                                          [1,1,1]], bool))
        binary_shrink_bottom_left &= make_table(False,
                                                np.array([[0,0,0],
                                                          [0,1,1],
                                                          [0,0,0]], bool),
                                                np.array([[1,0,0],
                                                          [1,1,1],
                                                          [1,0,0]], bool))
        binary_shrink_bottom_left &= make_table(False,
                                                np.array([[1,1,0],
                                                          [0,1,1],
                                                          [0,0,0]], bool),
                                                np.array([[0,1,0],
                                                          [1,1,1],
                                                          [1,0,0]], bool))
        binary_shrink_bottom_left &= make_table(False,
                                                np.array([[1,0,0],
                                                          [0,1,0],
                                                          [0,0,0]], bool),
                                                np.array([[1,0,1],
                                                          [0,1,1],
                                                          [1,1,1]], bool))
        binary_shrink_bottom_left &= make_table(False,
                                                np.array([[1,1,1],
                                                          [0,1,0],
                                                          [0,0,0]], bool),
                                                np.array([[1,1,0],
                                                          [0,1,1],
                                                          [1,1,1]], bool))
    orig_image = image
    index_i, index_j, image = prepare_for_index_lookup(image, False)
    if iterations == -1:
        iterations = len(index_i)
    for i in range(iterations):
        pixel_count = len(index_i)
        for table in (binary_shrink_top_right,
                      binary_shrink_bottom_left):
            index_i, index_j = index_lookup(index_i, index_j,
                                            image, table, 1)
        if len(index_i) == pixel_count:
            break
    image = extract_from_image_lookup(orig_image, index_i, index_j)
    return image

Response:
Shrinks an image by repeatedly removing pixels which have partners
       above to the right and below until idempotent.


Instruction:
Create a Python 3 function for
shrinking an image by repeatedly removing pixels which have partners above and below until idempotent

Response:
def binary_shrink(image, iterations=-1):
    """Shrink an image by repeatedly removing pixels which have partners
       above, to the left, to the right and below until the image doesn't change

       image - binary image to be manipulated
       iterations - # of times to shrink, -1 to shrink until idempotent

       There are horizontal/vertical thinners which detect a pixel on
       an edge with an interior pixel either horizontally or vertically
       attached like this:
       0  0  0
       X  1  X
       X  1  X
       and there are much more specific diagonal thinners which detect
       a pixel on the edge of a diagonal, like this:
       0  0  0
       0  1  0
       0  0  1
       Rotate each of these 4x to get the four directions for each
    """
    global erode_table, binary_shrink_ulr_table, binary_shrink_lrl_table
    global binary_shrink_urb_table, binary_shrink_llt_table
    if erode_table is None:
        #
        # The erode table hits all patterns that can be eroded without
        # changing the euler_number
        erode_table = np.array([pattern_of(index)[1,1] and
                                (scind.label(pattern_of(index-16))[1] != 1)
                                for index in range(512)])
        erode_table[index_of(np.ones((3,3), bool))] = True
        #
        # Each other table is more specific: a specific corner or a specific
        # edge must be on where the corner and edge are not adjacent
        #
        binary_shrink_ulr_table = (
            erode_table |
            (make_table(False, np.array([[0,0,0],
                                         [1,1,0],
                                         [0,0,0]], bool),
                        np.array([[0,0,0],
                                  [1,1,1],
                                  [0,0,0]],bool)) &
             make_table(False, np.array([[1,0,0],
                                         [0,1,0],
                                         [0,0,0]],bool),
                        np.array([[1,0,0],
                                  [0,1,1],
                                  [0,1,1]],bool))))
        binary_shrink_urb_table = (
            erode_table |
            (make_table(False, np.array([[0,1,0],
                                         [0,1,0],
                                         [0,0,0]], bool),
                       np.array([[0,1,0],
                                 [0,1,0],
                                 [0,1,0]],bool)) &
             make_table(False, np.array([[0,0,1],
                                         [0,1,0],
                                         [0,0,0]],bool),
                        np.array([[0,0,1],
                                  [1,1,0],
                                  [1,1,0]],bool))))
        binary_shrink_lrl_table = (
            erode_table |
            (make_table(False, np.array([[0,0,0],
                                         [0,1,1],
                                         [0,0,0]], bool),
                        np.array([[0,0,0],
                                  [1,1,1],
                                  [0,0,0]],bool)) &
             make_table(False, np.array([[0,0,0],
                                         [0,1,0],
                                         [0,0,1]], bool),
                        np.array([[1,1,0],
                                  [1,1,0],
                                  [0,0,1]], bool))))
        binary_shrink_llt_table = (
            erode_table |
            (make_table(False, np.array([[0,0,0],
                                         [0,1,0],
                                         [0,1,0]], bool),
                        np.array([[0,1,0],
                                  [0,1,0],
                                  [0,1,0]],bool)) &
             make_table(False, np.array([[0,0,0],
                                         [0,1,0],
                                         [1,0,0]], bool),
                        np.array([[0,1,1],
                                  [0,1,1],
                                  [1,0,0]], bool))))

    orig_image = image
    index_i, index_j, image = prepare_for_index_lookup(image, False)
    if iterations == -1:
        iterations = len(index_i)
    for i in range(iterations):
        pixel_count = len(index_i)
        for table in (binary_shrink_ulr_table,
                      binary_shrink_urb_table,
                      binary_shrink_lrl_table,
                      binary_shrink_llt_table):
            index_i, index_j = index_lookup(index_i, index_j,
                                            image, table, 1)
        if len(index_i) == pixel_count:
            break
    image = extract_from_image_lookup(orig_image, index_i, index_j)
    return image


Instruction:
How would you explain what the following Python 3 function does
def strel_disk(radius):
    iradius = int(radius)
    x,y     = np.mgrid[-iradius:iradius+1,-iradius:iradius+1]
    radius2 = radius * radius
    strel   = np.zeros(x.shape)
    strel[x*x+y*y <= radius2] = 1
    return strel

Response: Create a disk structuring element for morphological operations


Instruction:
Can you write a function in Python 3 where it
creates a diamond structuring element for morphological operations

Response:
def strel_diamond(radius):
    """Create a diamond structuring element for morphological operations

    radius - the offset of the corners of the diamond from the origin
             rounded down (e.g. r=2: (0, 2), (2, 0), (0, -2), (-2, 0))

    returns a two-dimensional binary array
    """
    iradius = int(radius)
    i, j = np.mgrid[-iradius:(iradius + 1), -iradius:(iradius+1)]

    strel = (((i+j) <= radius) & ((i+j) >= -radius) &
             ((i-j) <= radius) & ((i-j) >= -radius))
    return strel


Instruction:
Can you generate a brief explanation for the following Python 3 code
def strel_line(length, angle):
    angle = float(angle) * np.pi / 180.
    x_off = int(np.finfo(float).eps + np.cos(angle) * length / 2)
    # Y is flipped here because "up" is negative
    y_off = -int(np.finfo(float).eps + np.sin(angle) * length / 2)
    x_center = abs(x_off)
    y_center = abs(y_off)
    strel = np.zeros((y_center * 2 + 1,
                      x_center * 2 + 1), bool)
    draw_line(strel,
              (y_center - y_off, x_center - x_off),
              (y_center, x_center), True)
    draw_line(strel,
              (y_center + y_off, x_center + x_off),
              (y_center, x_center), True)

    return strel

Response: Create a line structuring element for morphological operations


Instruction:
Make a summary of the following Python 3 code
def strel_octagon(radius):
    #
    # Inscribe a diamond in a square to get an octagon.
    #
    iradius = int(radius)
    i, j = np.mgrid[-iradius:(iradius + 1), -iradius:(iradius+1)]
    #
    # The distance to the diagonal side is also iradius:
    #
    # iradius ** 2 = i**2 + j**2 and i = j
    # iradius ** 2 = 2 * i ** 2
    # i = iradius / sqrt(2)
    # i + j = iradius * sqrt(2)
    #
    dradius = float(iradius) * np.sqrt(2)
    strel = (((i+j) <= dradius) & ((i+j) >= -dradius) &
             ((i-j) <= dradius) & ((i-j) >= -dradius))
    return strel

Response: Create an octagonal structuring element for morphological operations


Instruction:
Here you have a function in Python 3, explain what it does
def strel_rectangle(width, height):
    return np.ones([int((hw - 1) // 2) * 2 + 1 for hw in (height, width)], bool)

Response: Create a rectangular structuring element


Instruction:
Implement a Python 3 function for
finding the local maximum at each point in the image using the given structure

Response:
def cpmaximum(image, structure=np.ones((3,3),dtype=bool),offset=None):
    """Find the local maximum at each point in the image, using the given structuring element

    image - a 2-d array of doubles
    structure - a boolean structuring element indicating which
                local elements should be sampled
    offset - the offset to the center of the structuring element
    """
    center = np.array(structure.shape) // 2
    if offset is None:
        offset = center
    origin = np.array(offset) - center
    return scind.maximum_filter(image, footprint=structure, origin=origin,
                                mode='constant', cval=np.min(image))


Instruction:
Can you tell what is the following Python 3 function doing
def relabel(image):
    #
    # Build a label table that converts an old label # into
    # labels using the new numbering scheme
    #
    unique_labels = np.unique(image[image!=0])
    if len(unique_labels) == 0:
        return (image,0)
    consecutive_labels = np.arange(len(unique_labels))+1
    label_table = np.zeros(unique_labels.max()+1, int)
    label_table[unique_labels] = consecutive_labels
    #
    # Use the label table to remap all of the labels
    #
    new_image = label_table[image]
    return (new_image,len(unique_labels))

Response: Relabels each object in the object list into a new object list.


Instruction:
Create a Python 3 function for
giving a binary image return an image of the convex hull

Response:
def convex_hull_image(image):
    '''Given a binary image, return an image of the convex hull'''
    labels = image.astype(int)
    points, counts = convex_hull(labels, np.array([1]))
    output = np.zeros(image.shape, int)
    for i in range(counts[0]):
        inext = (i+1) % counts[0]
        draw_line(output, points[i,1:], points[inext,1:],1)
    output = fill_labeled_holes(output)
    return output == 1


Instruction:
Implement a function in Python 3 to
give a labeled image return a list of points per object ordered by the interior point.

Response:
def convex_hull(labels, indexes=None, fast=True):
    """Given a labeled image, return a list of points per object ordered by
    angle from an interior point, representing the convex hull.s

    labels - the label matrix
    indexes - an array of label #s to be processed, defaults to all non-zero
              labels

    Returns a matrix and a vector. The matrix consists of one row per
    point in the convex hull. Each row has three columns, the label #,
    the i coordinate of the point and the j coordinate of the point. The
    result is organized first by label, then the points are arranged
    counter-clockwise around the perimeter.
    The vector is a vector of #s of points in the convex hull per label
    """
    if indexes is None:
        indexes = np.unique(labels)
        indexes.sort()
        indexes=indexes[indexes!=0]
    else:
        indexes=np.array(indexes)
    if len(indexes) == 0:
        return np.zeros((0,2),int),np.zeros((0,),int)
    #
    # Reduce the # of points to consider
    #
    outlines = outline(labels)
    coords = np.argwhere(outlines > 0).astype(np.int32)
    if len(coords)==0:
        # Every outline of every image is blank
        return (np.zeros((0,3),int),
                np.zeros((len(indexes),),int))

    i = coords[:,0]
    j = coords[:,1]
    labels_per_point = labels[i,j]
    pixel_labels = np.column_stack((i,j,labels_per_point))
    return convex_hull_ijv(pixel_labels, indexes, fast)