Instruction:
Write a Python 3 function that can
okay this worker is going build graphs from PCAP Bro output logs

Response:
def execute(self, input_data):
        ''' Okay this worker is going build graphs from PCAP Bro output logs '''

        # Grab the Bro log handles from the input
        bro_logs = input_data['pcap_bro']

        # Weird log
        if 'weird_log' in bro_logs:
            stream = self.workbench.stream_sample(bro_logs['weird_log'])
            self.weird_log_graph(stream)

        # HTTP log
        gsleep()
        stream = self.workbench.stream_sample(bro_logs['http_log'])
        self.http_log_graph(stream)

        # Files log
        gsleep()
        stream = self.workbench.stream_sample(bro_logs['files_log'])
        self.files_log_graph(stream)

        return {'output':'go to http://localhost:7474/browser and execute this query "match (s:origin), (t:file), p=allShortestPaths((s)--(t)) return p"'}


Instruction:
Can you generate a brief explanation for the following Python 3 code
def http_log_graph(self, stream):
        ''' Build up a graph (nodes and edges from a Bro http.log) '''
        print 'Entering http_log_graph...'
        for row in list(stream):

            # Skip '-' hosts
            if (row['id.orig_h'] == '-'):
                continue

            # Add the originating host
            self.add_node(row['id.orig_h'], row['id.orig_h'], ['host', 'origin'])

            # Add the response host and reponse ip
            self.add_node(row['host'], row['host'], ['host'])
            self.add_node(row['id.resp_h'], row['id.resp_h'], ['host'])

            # Add the http request relationships
            self.add_rel(row['id.orig_h'], row['host'], 'http_request')
            self.add_rel(row['host'], row['id.resp_h'], 'A')

Response: Build a graph of nodes and edges from a Bro http. log file.


Instruction:
Create a Python 3 function to
build a graph of the files in the files log file.

Response:
def files_log_graph(self, stream):
        ''' Build up a graph (nodes and edges from a Bro dns.log) '''
        for row in list(stream):

            # dataframes['files_log'][['md5','mime_type','missing_bytes','rx_hosts','source','tx_hosts']]

            # If the mime-type is interesting add the uri and the host->uri->host relationships
            if row['mime_type'] not in self.exclude_mime_types:

                # Check for weird conditions
                if (row['total_bytes'] == '-'):
                    continue
                if ('-' in row['md5']):
                    continue

                # Check for missing bytes and small file
                if row['missing_bytes']:
                    labels = ['missing', 'file']
                elif row['total_bytes'] < 50*1024:
                    labels = ['small','file']
                else:
                    labels = ['file']

                # Make the file node name kewl
                name = '%6s  %s  %.0f-KB' % (row['md5'][:6], row['mime_type'], row['total_bytes']/1024.0)
                if row['missing_bytes']:
                    name += '*'
                name = name.replace('application/','')

                # Add the file node
                self.add_node(row['md5'], name, labels)

                # Add the tx_host
                self.add_node(row['tx_hosts'], row['tx_hosts'], ['host'])

                # Add the file->tx_host relationship
                self.add_rel(row['tx_hosts'], row['md5'], 'file')


Instruction:
How would you explain what the following Python 3 function does
def register_callbacks(self, on_create, on_modify, on_delete):
        self.on_create = on_create
        self.on_modify = on_modify
        self.on_delete = on_delete

Response: Register callbacks for file creation modification and deletion.


Instruction:
Explain what the following Python 3 code does
def _start_monitoring(self):

        # Grab all the timestamp info
        before = self._file_timestamp_info(self.path)

        while True:
            gevent.sleep(1)
            after = self._file_timestamp_info(self.path)

            added = [fname for fname in after.keys() if fname not in before.keys()]
            removed = [fname for fname in before.keys() if fname not in after.keys()]
            modified = []

            for fname in before.keys():
                if fname not in removed:
                    if os.path.getmtime(fname) != before.get(fname):
                        modified.append(fname)

            if added:
                self.on_create(added)
            if removed:
                self.on_delete(removed)
            if modified:
                self.on_modify(modified)

            before = after

Response: Internal method that monitors the directory for changes


Instruction:
Implement a function in Python 3 to
grab all the timestamps for the files in the directory

Response:
def _file_timestamp_info(self, path):
        """ Grab all the timestamps for the files in the directory """
        files = [os.path.join(path, fname) for fname in os.listdir(path) if '.py' in fname]
        return dict ([(fname, os.path.getmtime(fname)) for fname in files])


Instruction:
Explain what the following Python 3 code does
def get_rules_from_disk(self):
        ''' Recursively traverse the yara/rules directory for rules '''

        # Try to find the yara rules directory relative to the worker
        my_dir = os.path.dirname(os.path.realpath(__file__))
        yara_rule_path = os.path.join(my_dir, 'yara/rules')
        if not os.path.exists(yara_rule_path):
            raise RuntimeError('yara could not find yara rules directory under: %s' % my_dir)

        # Okay load in all the rules under the yara rule path
        self.rules = yara.load_rules(rules_rootpath=yara_rule_path)

        # Save rules to Workbench
        self.save_rules_to_workbench(self.rules)

        return self.rules

Response: Recursively load the rules from the yara rules directory and save them to Workbench


Instruction:
Can you create a Python 3 function that
executes the yara match data worker

Response:
def execute(self, input_data):
        ''' yara worker execute method '''
        raw_bytes = input_data['sample']['raw_bytes']
        matches = self.rules.match_data(raw_bytes)

        # The matches data is organized in the following way
        # {'filename1': [match_list], 'filename2': [match_list]}
        # match_list = list of match
        # match = {'meta':{'description':'blah}, tags=[], matches:True,
        #           strings:[string_list]}
        # string = {'flags':blah, 'identifier':'$', 'data': FindWindow, 'offset'}
        #
        # So we're going to flatten a bit (shrug)
        # {filename_match_meta_description: string_list}
        flat_data = collections.defaultdict(list)
        for filename, match_list in matches.iteritems():
            for match in match_list:
                if 'description' in match['meta']:
                    new_tag = filename+'_'+match['meta']['description']
                else:
                    new_tag = filename+'_'+match['rule']
                for match in match['strings']:
                    flat_data[new_tag].append(match['data'])
                # Remove duplicates
                flat_data[new_tag] = list(set(flat_data[new_tag]))

        return {'matches': flat_data}


Instruction:
Create a Python 3 function to
yield chunk_size chunks from data.

Response:
def chunks(data, chunk_size):
    """ Yield chunk_size chunks from data."""
    for i in xrange(0, len(data), chunk_size):
        yield data[i:i+chunk_size]


Instruction:
Here you have a function in Python 3, explain what it does
def get_rules_from_disk():
    ''' Recursively traverse the yara/rules directory for rules '''

    # Try to find the yara rules directory relative to the worker
    my_dir = os.path.dirname(os.path.realpath(__file__))
    yara_rule_path = os.path.join(my_dir, 'yara/rules')
    if not os.path.exists(yara_rule_path):
        raise RuntimeError('yara could not find yara rules directory under: %s' % my_dir)

    # Okay load in all the rules under the yara rule path
    rules = yara.load_rules(rules_rootpath=yara_rule_path, fast_match=True)

    return rules

Response: Recursively traverse the yara rules directory for rules


Instruction:
How would you explain what the following Python 3 function does
def setup_pcap_inputs(self, input_data):
        ''' Write the PCAPs to disk for Bro to process and return the pcap filenames '''

        # Setup the pcap in the input data for processing by Bro. The input
        # may be either an individual sample or a sample set.
        file_list = []
        if 'sample' in input_data:
            raw_bytes = input_data['sample']['raw_bytes']
            filename = os.path.basename(input_data['sample']['filename'])
            file_list.append({'filename': filename, 'bytes': raw_bytes})
        else:
            for md5 in input_data['sample_set']['md5_list']:
                sample = self.workbench.get_sample(md5)['sample']
                raw_bytes = sample['raw_bytes']
                filename = os.path.basename(sample['filename'])
                file_list.append({'filename': filename, 'bytes': raw_bytes})

        # Write the pcaps to disk and keep the filenames for Bro to process
        for file_info in file_list:
            with open(file_info['filename'], 'wb') as pcap_file:
                pcap_file.write(file_info['bytes'])

        # Return filenames
        return [file_info['filename'] for file_info in file_list]

Response: Setup the PCAPs for Bro to process and return the pcap filenames


Instruction:
Can you generate a brief explanation for the following Python 3 code
def execute(self, input_data):
        ''' Execute '''

        # Get the bro script path (workers/bro/__load__.bro)
        script_path = self.bro_script_dir

        # Create a temporary directory
        with self.goto_temp_directory() as temp_dir:

            # Get the pcap inputs (filenames)
            print 'pcap_bro: Setting up PCAP inputs...'
            filenames = self.setup_pcap_inputs(input_data)
            command_line = ['bro']
            for filename in filenames:
                command_line += ['-C', '-r', filename]
            if script_path:
                command_line.append(script_path)

            # Execute command line as a subprocess
            print 'pcap_bro: Executing subprocess...'
            self.subprocess_manager(command_line)

            # Scrape up all the output log files
            gsleep()
            print 'pcap_bro: Scraping output logs...'
            my_output = {}
            for output_log in glob.glob('*.log'):

                # Store the output into workbench, put the name:md5 in my output
                output_name = os.path.splitext(output_log)[0] + '_log'
                with open(output_log, 'rb') as bro_file:
                    raw_bytes = bro_file.read()
                    my_output[output_name] = self.workbench.store_sample(raw_bytes, output_name, 'bro')

            # Scrape any extracted files
            gsleep()
            print 'pcap_bro: Scraping extracted files...'
            my_output['extracted_files'] = []
            for output_file in glob.glob('extract_files/*'):

                # Store the output into workbench, put md5s in the 'extracted_files' field
                output_name = os.path.basename(output_file)
                with open(output_file, 'rb') as extracted_file:
                    if output_name.endswith('exe'):
                        type_tag = 'exe'
                    else:
                        type_tag = output_name[-3:]
                    raw_bytes = extracted_file.read()
                    my_output['extracted_files'].append(self.workbench.store_sample(raw_bytes, output_name, type_tag))

        # Construct back-pointers to the PCAPs
        if 'sample' in input_data:
            my_output['pcaps'] = [input_data['sample']['md5']]
        else:
            my_output['pcaps'] = input_data['sample_set']['md5_list']

        # Return my output
        return my_output

Response: Execute the command line and return the result of the command line.


Instruction:
Write a Python 3 script for
getting the console output of a virtual machine.

Response:
def getConsole(rh):
    """
    Get the virtual machine's console output.

    Input:
       Request Handle with the following properties:
          function    - 'CMDVM'
          subfunction - 'CMD'
          userid      - userid of the virtual machine

    Output:
       Request Handle updated with the results.
       Return code - 0: ok, non-zero: error
    """

    rh.printSysLog("Enter getVM.getConsole")

    # Transfer the console to this virtual machine.
    parms = ["-T", rh.userid]
    results = invokeSMCLI(rh, "Image_Console_Get", parms)

    if results['overallRC'] != 0:
        if (results['overallRC'] == 8 and results['rc'] == 8 and
            results['rs'] == 8):
            # Give a more specific message.  Userid is either
            # not logged on or not spooling their console.
            msg = msgs.msg['0409'][1] % (modId, rh.userid)
        else:
            msg = results['response']
        rh.updateResults(results)    # Use results from invokeSMCLI
        rh.printLn("ES", msg)
        rh.printSysLog("Exit getVM.parseCmdLine, rc: " +
                       str(rh.results['overallRC']))
        return rh.results['overallRC']

    # Check whether the reader is online
    with open('/sys/bus/ccw/drivers/vmur/0.0.000c/online', 'r') as myfile:
        out = myfile.read().replace('\n', '')
        myfile.close()

    # Nope, offline, error out and exit
    if int(out) != 1:
        msg = msgs.msg['0411'][1]
        rh.printLn("ES", msg)
        rh.updateResults(msgs.msg['0411'][0])
        rh.printSysLog("Exit getVM.parseCmdLine, rc: " +
                       str(rh.results['overallRC']))
        return rh.results['overallRC']

    # We should set class to *, otherwise we will get errors like:
    # vmur: Reader device class does not match spool file class
    cmd = ["sudo", "/sbin/vmcp", "spool reader class *"]
    strCmd = ' '.join(cmd)
    rh.printSysLog("Invoking: " + strCmd)
    try:
        subprocess.check_output(
            cmd,
            close_fds=True,
            stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError as e:
        # If we couldn't change the class, that's not fatal
        # But we want to warn about possibly incomplete
        # results
        msg = msgs.msg['0407'][1] % (modId, strCmd, e.output)
        rh.printLn("WS", msg)
    except Exception as e:
        # All other exceptions.
        # If we couldn't change the class, that's not fatal
        # But we want to warn about possibly incomplete
        # results
        rh.printLn("ES", msgs.msg['0422'][1] % (modId, strCmd,
            type(e).__name__, str(e)))
        rh.printLn("ES", msgs.msg['0423'][1] % modId, strCmd,
            type(e).__name__, str(e))

    # List the spool files in the reader
    cmd = ["sudo", "/usr/sbin/vmur", "list"]
    strCmd = ' '.join(cmd)
    rh.printSysLog("Invoking: " + strCmd)
    try:
        files = subprocess.check_output(
            cmd,
            close_fds=True,
            stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError as e:
        # Uh oh, vmur list command failed for some reason
        msg = msgs.msg['0408'][1] % (modId, rh.userid,
                                     strCmd, e.output)
        rh.printLn("ES", msg)
        rh.updateResults(msgs.msg['0408'][0])
        rh.printSysLog("Exit getVM.parseCmdLine, rc: " +
                       str(rh.results['overallRC']))
        return rh.results['overallRC']
    except Exception as e:
        # All other exceptions.
        rh.printLn("ES", msgs.msg['0421'][1] % (modId, strCmd,
            type(e).__name__, str(e)))
        rh.updateResults(msgs.msg['0421'][0])
        rh.printSysLog("Exit getVM.parseCmdLine, rc: " +
                       str(rh.results['overallRC']))
        return rh.results['overallRC']

    # Now for each line that contains our user and is a
    # class T console file, add the spool id to our list
    spoolFiles = files.split('\n')
    outstr = ""
    for myfile in spoolFiles:
        if (myfile != "" and
                myfile.split()[0] == rh.userid and
                myfile.split()[2] == "T" and
                myfile.split()[3] == "CON"):

            fileId = myfile.split()[1]
            outstr += fileId + " "

    # No files in our list
    if outstr == "":
        msg = msgs.msg['0410'][1] % (modId, rh.userid)
        rh.printLn("ES", msg)
        rh.updateResults(msgs.msg['0410'][0])
        rh.printSysLog("Exit getVM.parseCmdLine, rc: " +
                       str(rh.results['overallRC']))
        return rh.results['overallRC']

    # Output the list
    rh.printLn("N", "List of spool files containing "
               "console logs from %s: %s" % (rh.userid, outstr))

    rh.results['overallRC'] = 0
    rh.printSysLog("Exit getVM.getConsole, rc: " +
                   str(rh.results['overallRC']))
    return rh.results['overallRC']


Instruction:
How would you explain what the following Python 3 function does
def getDirectory(rh):
    rh.printSysLog("Enter getVM.getDirectory")

    parms = ["-T", rh.userid]
    results = invokeSMCLI(rh, "Image_Query_DM", parms)
    if results['overallRC'] == 0:
        results['response'] = re.sub('\*DVHOPT.*', '', results['response'])
        rh.printLn("N", results['response'])
    else:
        # SMAPI API failed.
        rh.printLn("ES", results['response'])
        rh.updateResults(results)    # Use results from invokeSMCLI

    rh.printSysLog("Exit getVM.getDirectory, rc: " +
                   str(rh.results['overallRC']))
    return rh.results['overallRC']

Response: Returns the virtual machine s directory statements.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def getStatus(rh):

    rh.printSysLog("Enter getVM.getStatus, userid: " + rh.userid)

    results = isLoggedOn(rh, rh.userid)
    if results['rc'] != 0:
        # Uhoh, can't determine if guest is logged on or not
        rh.updateResults(results)
        rh.printSysLog("Exit getVM.getStatus, rc: " +
                       str(rh.results['overallRC']))
        return rh.results['overallRC']

    if results['rs'] == 1:
        # Guest is logged off, everything is 0
        powerStr = "Power state: off"
        memStr = "Total Memory: 0M"
        usedMemStr = "Used Memory: 0M"
        procStr = "Processors: 0"
        timeStr = "CPU Used Time: 0 sec"

    else:
        powerStr = "Power state: on"

    if 'power' in rh.parms:
        # Test here to see if we only need power state
        # Then we can return early
        rh.printLn("N", powerStr)
        rh.updateResults(results)
        rh.printSysLog("Exit getVM.getStatus, rc: " +
                       str(rh.results['overallRC']))
        return rh.results['overallRC']

    if results['rs'] != 1:
        # Guest is logged on, go get more info
        results = getPerfInfo(rh, rh.userid)

        if results['overallRC'] != 0:
            # Something went wrong in subroutine, exit
            rh.updateResults(results)
            rh.printSysLog("Exit getVM.getStatus, rc: " +
                           str(rh.results['overallRC']))
            return rh.results['overallRC']
        else:
            # Everything went well, response should be good
            memStr = results['response'].split("\n")[0]
            usedMemStr = results['response'].split("\n")[1]
            procStr = results['response'].split("\n")[2]
            timeStr = results['response'].split("\n")[3]

    # Build our output string according
    # to what information was asked for
    if 'memory' in rh.parms:
        outStr = memStr + "\n" + usedMemStr
    elif 'cpu' in rh.parms:
        outStr = procStr + "\n" + timeStr
    else:
        # Default to all
        outStr = powerStr + "\n" + memStr + "\n" + usedMemStr
        outStr += "\n" + procStr + "\n" + timeStr
    rh.printLn("N", outStr)
    rh.printSysLog("Exit getVM.getStatus, rc: " +
                   str(rh.results['overallRC']))
    return rh.results['overallRC']

Response: Get the basic status of a virtual machine.


Instruction:
Write a Python 3 function that can
extract data from smcli System_WWPN_Query output.

Response:
def extract_fcp_data(raw_data, status):
    """
    extract data from smcli System_WWPN_Query output.
    Input:
        raw data returned from smcli
    Output:
        data extracted would be like:
    'status:Free \n
     fcp_dev_no:1D2F\n
     physical_wwpn:C05076E9928051D1\n
     channel_path_id:8B\n
     npiv_wwpn': 'NONE'\n

     status:Free\n
     fcp_dev_no:1D29\n
     physical_wwpn:C05076E9928051D1\n
     channel_path_id:8B\n
     npiv_wwpn:NONE
    """
    raw_data = raw_data.split('\n')

    # clear blank lines
    data = []
    for i in raw_data:
        i = i.strip(' \n')
        if i == '':
            continue
        else:
            data.append(i)
    # process data into one list of dicts
    results = []
    for i in range(0, len(data), 5):
        temp = data[i + 1].split(':')[-1].strip()
        # only return results match the status
        if temp.lower() == status.lower():
            results.extend(data[i:i + 5])

    return '\n'.join(results)


Instruction:
Create a Python 3 function to
get fcp info and filter by the status. Input: Request Handle with the following properties: function - 'GETVM' subfunction - 'FCPINFO' userid - userid of the virtual machine parms['status'] - The status for filter results. Output: Request Handle updated with the results. Return code - 0: ok, non-zero: error

Response:
def fcpinfo(rh):
    """
    Get fcp info and filter by the status.

    Input:
       Request Handle with the following properties:
          function    - 'GETVM'
          subfunction - 'FCPINFO'
          userid      - userid of the virtual machine
          parms['status']       - The status for filter results.

    Output:
       Request Handle updated with the results.
       Return code - 0: ok, non-zero: error
    """
    rh.printSysLog("Enter changeVM.dedicate")

    parms = ["-T", rh.userid]

    hideList = []
    results = invokeSMCLI(rh,
                          "System_WWPN_Query",
                          parms,
                          hideInLog=hideList)

    if results['overallRC'] != 0:
        # SMAPI API failed.
        rh.printLn("ES", results['response'])
        rh.updateResults(results)    # Use results from invokeSMCLI

    if results['overallRC'] == 0:
        # extract data from smcli return
        ret = extract_fcp_data(results['response'], rh.parms['status'])
        # write the ret into results['response']
        rh.printLn("N", ret)
    else:
        rh.printLn("ES", results['response'])
        rh.updateResults(results)    # Use results from invokeSMCLI

    return rh.results['overallRC']


Instruction:
Here you have a function in Python 3, explain what it does
def _no_auto_update_getter(self):
    if getattr(self, '_no_auto_update', None) is not None:
        return self._no_auto_update
    else:
        self._no_auto_update = utils._TempBool()
    return self._no_auto_update

Response: A method to get the value of _no_auto_update


Instruction:
Can you generate the documentation for the following Python 3 function
def _infer_interval_breaks(coord):
    coord = np.asarray(coord)
    deltas = 0.5 * (coord[1:] - coord[:-1])
    first = coord[0] - deltas[0]
    last = coord[-1] + deltas[-1]
    return np.r_[[first], coord[:-1] + deltas, [last]]

Response: Infer interval breaks from a coordinate.


Instruction:
Make a summary of the following Python 3 code
def _get_variable_names(arr):
    if VARIABLELABEL in arr.dims:
        return arr.coords[VARIABLELABEL].tolist()
    else:
        return arr.name

Response: Return the variable names of an array


Instruction:
How would you explain what the following Python 3 function does
def to_slice(arr):
    if isinstance(arr, slice):
        return arr
    if len(arr) == 1:
        return slice(arr[0], arr[0] + 1)
    step = np.unique(arr[1:] - arr[:-1])
    if len(step) == 1:
        return slice(arr[0], arr[-1] + step[0], step[0])

Response: Test whether arr can be replaced by a slice


Instruction:
Write a Python 3 script for
functioning to return the coordinate as integer array or slice of integers or slice of integers

Response:
def get_index_from_coord(coord, base_index):
    """Function to return the coordinate as integer, integer array or slice

    If `coord` is zero-dimensional, the corresponding integer in `base_index`
    will be supplied. Otherwise it is first tried to return a slice, if that
    does not work an integer array with the corresponding indices is returned.

    Parameters
    ----------
    coord: xarray.Coordinate or xarray.Variable
        Coordinate to convert
    base_index: pandas.Index
        The base index from which the `coord` was extracted

    Returns
    -------
    int, array of ints or slice
        The indexer that can be used to access the `coord` in the
        `base_index`
    """
    try:
        values = coord.values
    except AttributeError:
        values = coord
    if values.ndim == 0:
        return base_index.get_loc(values[()])
    if len(values) == len(base_index) and (values == base_index).all():
        return slice(None)
    values = np.array(list(map(lambda i: base_index.get_loc(i), values)))
    return to_slice(values) or values


Instruction:
Write a Python 3 script for
getting the time information from file names

Response:
def get_tdata(t_format, files):
    """
    Get the time information from file names

    Parameters
    ----------
    t_format: str
        The string that can be used to get the time information in the files.
        Any numeric datetime format string (e.g. %Y, %m, %H) can be used, but
        not non-numeric strings like %b, etc. See [1]_ for the datetime format
        strings
    files: list of str
        The that contain the time informations

    Returns
    -------
    pandas.Index
        The time coordinate
    list of str
        The file names as they are sorten in the returned index

    References
    ----------
    .. [1] https://docs.python.org/2/library/datetime.html"""
    def median(arr):
        return arr.min() + (arr.max() - arr.min())/2
    import re
    from pandas import Index
    t_pattern = t_format
    for fmt, patt in t_patterns.items():
        t_pattern = t_pattern.replace(fmt, patt)
    t_pattern = re.compile(t_pattern)
    time = list(range(len(files)))
    for i, f in enumerate(files):
        time[i] = median(np.array(list(map(
            lambda s: np.datetime64(dt.datetime.strptime(s, t_format)),
            t_pattern.findall(f)))))
    ind = np.argsort(time)  # sort according to time
    files = np.array(files)[ind]
    time = np.array(time)[ind]
    return to_datetime(Index(time, name='time')), files


Instruction:
Can you generate a brief explanation for the following Python 3 code
def to_netcdf(ds, *args, **kwargs):
    to_update = {}
    for v, obj in six.iteritems(ds.variables):
        units = obj.attrs.get('units', obj.encoding.get('units', None))
        if units == 'day as %Y%m%d.%f' and np.issubdtype(
                obj.dtype, np.datetime64):
            to_update[v] = xr.Variable(
                obj.dims, AbsoluteTimeEncoder(obj), attrs=obj.attrs.copy(),
                encoding=obj.encoding)
            to_update[v].attrs['units'] = units
    if to_update:
        ds = ds.copy()
        ds.update(to_update)
    return xarray_api.to_netcdf(ds, *args, **kwargs)

Response: This function will store the given dataset as a netCDF file and return the netCDF file.


Instruction:
How would you code a function in Python 3 to
try to get the file name from the NioDataStore store

Response:
def _get_fname_nio(store):
    """Try to get the file name from the NioDataStore store"""
    try:
        f = store.ds.file
    except AttributeError:
        return None
    try:
        return f.path
    except AttributeError:
        return None


Instruction:
Can you generate a brief explanation for the following Python 3 code
def get_filename_ds(ds, dump=True, paths=None, **kwargs):
    from tempfile import NamedTemporaryFile

    # if already specified, return that filename
    if ds.psy._filename is not None:
        return tuple([ds.psy._filename] + list(ds.psy.data_store))

    def dump_nc():
        # make sure that the data store is not closed by providing a
        # write argument
        if xr_version < (0, 11):
            kwargs.setdefault('writer', xarray_api.ArrayWriter())
            store = to_netcdf(ds, fname, **kwargs)
        else:
            # `writer` parameter was removed by
            # https://github.com/pydata/xarray/pull/2261
            kwargs.setdefault('multifile', True)
            store = to_netcdf(ds, fname, **kwargs)[1]
        store_mod = store.__module__
        store_cls = store.__class__.__name__
        ds._file_obj = store
        return store_mod, store_cls

    def tmp_it():
        while True:
            yield NamedTemporaryFile(suffix='.nc').name

    fname = None
    if paths is True or (dump and paths is None):
        paths = tmp_it()
    elif paths is not None:
        if isstring(paths):
            paths = iter([paths])
        else:
            paths = iter(paths)
    # try to get the filename from  the data store of the obj
    store_mod, store_cls = ds.psy.data_store
    if store_mod is not None:
        store = ds._file_obj
        # try several engines
        if hasattr(store, 'file_objs'):
            fname = []
            store_mod = []
            store_cls = []
            for obj in store.file_objs:  # mfdataset
                _fname = None
                for func in get_fname_funcs:
                    if _fname is None:
                        _fname = func(obj)
                        if _fname is not None:
                            fname.append(_fname)
                            store_mod.append(obj.__module__)
                            store_cls.append(obj.__class__.__name__)
            fname = tuple(fname)
            store_mod = tuple(store_mod)
            store_cls = tuple(store_cls)
        else:
            for func in get_fname_funcs:
                fname = func(store)
                if fname is not None:
                    break
    # check if paths is provided and if yes, save the file
    if fname is None and paths is not None:
        fname = next(paths, None)
        if dump and fname is not None:
            store_mod, store_cls = dump_nc()

    ds.psy.filename = fname
    ds.psy.data_store = (store_mod, store_cls)

    return fname, store_mod, store_cls

Response: Returns the path to the dataset that corresponds to a single file.


Instruction:
Write a Python 3 function that can
open an instance of xarray. Dataset.

Response:
def open_dataset(filename_or_obj, decode_cf=True, decode_times=True,
                 decode_coords=True, engine=None, gridfile=None, **kwargs):
    """
    Open an instance of :class:`xarray.Dataset`.

    This method has the same functionality as the :func:`xarray.open_dataset`
    method except that is supports an additional 'gdal' engine to open
    gdal Rasters (e.g. GeoTiffs) and that is supports absolute time units like
    ``'day as %Y%m%d.%f'`` (if `decode_cf` and `decode_times` are True).

    Parameters
    ----------
    %(xarray.open_dataset.parameters.no_engine)s
    engine: {'netcdf4', 'scipy', 'pydap', 'h5netcdf', 'gdal'}, optional
        Engine to use when reading netCDF files. If not provided, the default
        engine is chosen based on available dependencies, with a preference for
        'netcdf4'.
    %(CFDecoder.decode_coords.parameters.gridfile)s

    Returns
    -------
    xarray.Dataset
        The dataset that contains the variables from `filename_or_obj`"""
    # use the absolute path name (is saver when saving the project)
    if isstring(filename_or_obj) and osp.exists(filename_or_obj):
        filename_or_obj = osp.abspath(filename_or_obj)
    if engine == 'gdal':
        from psyplot.gdal_store import GdalStore
        filename_or_obj = GdalStore(filename_or_obj)
        engine = None
    ds = xr.open_dataset(filename_or_obj, decode_cf=decode_cf,
                         decode_coords=False, engine=engine,
                         decode_times=decode_times, **kwargs)
    if decode_cf:
        ds = CFDecoder.decode_ds(
            ds, decode_coords=decode_coords, decode_times=decode_times,
            gridfile=gridfile)
    return ds


Instruction:
Can you implement a function in Python 3 that
opens multiple files as a single dataset.

Response:
def open_mfdataset(paths, decode_cf=True, decode_times=True,
                   decode_coords=True, engine=None, gridfile=None,
                   t_format=None, **kwargs):
    """
    Open multiple files as a single dataset.

    This function is essentially the same as the :func:`xarray.open_mfdataset`
    function but (as the :func:`open_dataset`) supports additional decoding
    and the ``'gdal'`` engine.
    You can further specify the `t_format` parameter to get the time
    information from the files and use the results to concatenate the files

    Parameters
    ----------
    %(xarray.open_mfdataset.parameters.no_engine)s
    %(open_dataset.parameters.engine)s
    %(get_tdata.parameters.t_format)s
    %(CFDecoder.decode_coords.parameters.gridfile)s

    Returns
    -------
    xarray.Dataset
        The dataset that contains the variables from `filename_or_obj`"""
    if t_format is not None or engine == 'gdal':
        if isinstance(paths, six.string_types):
            paths = sorted(glob(paths))
        if not paths:
            raise IOError('no files to open')
    if t_format is not None:
        time, paths = get_tdata(t_format, paths)
        kwargs['concat_dim'] = time
    if engine == 'gdal':
        from psyplot.gdal_store import GdalStore
        paths = list(map(GdalStore, paths))
        engine = None
        kwargs['lock'] = False

    ds = xr.open_mfdataset(
        paths, decode_cf=decode_cf, decode_times=decode_times, engine=engine,
        decode_coords=False, **kwargs)
    if decode_cf:
        ds = CFDecoder.decode_ds(ds, gridfile=gridfile,
                                 decode_coords=decode_coords,
                                 decode_times=decode_times)
    ds.psy._concat_dim = kwargs.get('concat_dim')
    return ds


Instruction:
Implement a Python 3 function for
opening a dataset and return it

Response:
def _open_ds_from_store(fname, store_mod=None, store_cls=None, **kwargs):
    """Open a dataset and return it"""
    if isinstance(fname, xr.Dataset):
        return fname
    if not isstring(fname):
        try:  # test iterable
            fname[0]
        except TypeError:
            pass
        else:
            if store_mod is not None and store_cls is not None:
                if isstring(store_mod):
                    store_mod = repeat(store_mod)
                if isstring(store_cls):
                    store_cls = repeat(store_cls)
                fname = [_open_store(sm, sc, f)
                         for sm, sc, f in zip(store_mod, store_cls, fname)]
                kwargs['engine'] = None
                kwargs['lock'] = False
                return open_mfdataset(fname, **kwargs)
    if store_mod is not None and store_cls is not None:
        fname = _open_store(store_mod, store_cls, fname)
    return open_dataset(fname, **kwargs)


Instruction:
Implement a function in Python 3 to
disconnect a function call to the signal.

Response:
def disconnect(self, func=None):
        """Disconnect a function call to the signal. If None, all connections
        are disconnected"""
        if func is None:
            self._connections = []
        else:
            self._connections.remove(func)


Instruction:
Can you generate the documentation for the following Python 3 function
def logger(self):
        try:
            return self._logger
        except AttributeError:
            name = '%s.%s' % (self.__module__, self.__class__.__name__)
            self._logger = logging.getLogger(name)
            self.logger.debug('Initializing...')
            return self._logger

Response: Returns the logger of this instance.


Instruction:
Can you implement a function in Python 3 that
returns the right decoder class that can decode the given dataset and variable.

Response:
def get_decoder(cls, ds, var):
        """
        Class method to get the right decoder class that can decode the
        given dataset and variable

        Parameters
        ----------
        %(CFDecoder.can_decode.parameters)s

        Returns
        -------
        CFDecoder
            The decoder for the given dataset that can decode the variable
            `var`"""
        for decoder_cls in cls._registry:
            if decoder_cls.can_decode(ds, var):
                return decoder_cls(ds)
        return CFDecoder(ds)


Instruction:
Create a Python 3 function for
setting the coordinates and bounds in a dataset This static method sets those coordinates and bounds that are marked marked in the netCDF attributes as coordinates in :attr:`ds` (without deleting them from the variable attributes because this information is necessary for visualizing the data correctly) Parameters ---------- ds: xarray.Dataset The dataset to decode gridfile: str The path to a separate grid file or a xarray.Dataset instance which may store the coordinates used in `ds` Returns ------- xarray.Dataset `ds` with additional coordinates

Response:
def decode_coords(ds, gridfile=None):
        """
        Sets the coordinates and bounds in a dataset

        This static method sets those coordinates and bounds that are marked
        marked in the netCDF attributes as coordinates in :attr:`ds` (without
        deleting them from the variable attributes because this information is
        necessary for visualizing the data correctly)

        Parameters
        ----------
        ds: xarray.Dataset
            The dataset to decode
        gridfile: str
            The path to a separate grid file or a xarray.Dataset instance which
            may store the coordinates used in `ds`

        Returns
        -------
        xarray.Dataset
            `ds` with additional coordinates"""
        def add_attrs(obj):
            if 'coordinates' in obj.attrs:
                extra_coords.update(obj.attrs['coordinates'].split())
                obj.encoding['coordinates'] = obj.attrs.pop('coordinates')
            if 'bounds' in obj.attrs:
                extra_coords.add(obj.attrs['bounds'])
        if gridfile is not None and not isinstance(gridfile, xr.Dataset):
            gridfile = open_dataset(gridfile)
        extra_coords = set(ds.coords)
        for k, v in six.iteritems(ds.variables):
            add_attrs(v)
        add_attrs(ds)
        if gridfile is not None:
            ds.update({k: v for k, v in six.iteritems(gridfile.variables)
                       if k in extra_coords})
        if xr_version < (0, 11):
            ds.set_coords(extra_coords.intersection(ds.variables),
                          inplace=True)
        else:
            ds._coord_names.update(extra_coords.intersection(ds.variables))
        return ds


Instruction:
Write a Python 3 script for
testing if a variable is on a triangular grid.

Response:
def is_triangular(self, var):
        """
        Test if a variable is on a triangular grid

        This method first checks the `grid_type` attribute of the variable (if
        existent) whether it is equal to ``"unstructered"``, then it checks
        whether the bounds are not two-dimensional.

        Parameters
        ----------
        var: xarray.Variable or xarray.DataArray
            The variable to check

        Returns
        -------
        bool
            True, if the grid is triangular, else False"""
        warn("The 'is_triangular' method is depreceated and will be removed "
             "soon! Use the 'is_unstructured' method!", DeprecationWarning,
             stacklevel=1)
        return str(var.attrs.get('grid_type')) == 'unstructured' or \
            self._check_triangular_bounds(var)[0]


Instruction:
Can you generate a brief explanation for the following Python 3 code
def get_cell_node_coord(self, var, coords=None, axis='x', nans=None):
        if coords is None:
            coords = self.ds.coords
        axis = axis.lower()
        get_coord = self.get_x if axis == 'x' else self.get_y
        coord = get_coord(var, coords=coords)
        if coord is not None:
            bounds = self._get_coord_cell_node_coord(coord, coords, nans,
                                                     var=var)
            if bounds is None:
                bounds = self.get_plotbounds(coord)
                dim0 = coord.dims[-1]

                bounds = xr.DataArray(
                    np.dstack([bounds[:-1], bounds[1:]])[0],
                    dims=(dim0, '_bnds'),  attrs=coord.attrs.copy(),
                    name=coord.name + '_bnds')
            if bounds is not None and bounds.shape[-1] == 2:
                # normal CF-Conventions for rectangular grids
                arr = bounds.values
                if axis == 'y':
                    stacked = np.repeat(
                        np.dstack([arr, arr]).reshape((-1, 4)),
                        len(self.get_x(var, coords)), axis=0)
                else:
                    stacked = np.tile(np.c_[arr, arr[:, ::-1]],
                                      (len(self.get_y(var, coords)), 1))
                bounds = xr.DataArray(
                    stacked,
                    dims=('cell', bounds.dims[1]), name=bounds.name,
                    attrs=bounds.attrs)

            return bounds
        return None

Response: Returns the coordinates of the cell node in the variable attribute.


Instruction:
How would you code a function in Python 3 to
get the boundaries of an unstructed coordinate

Response:
def _get_coord_cell_node_coord(self, coord, coords=None, nans=None,
                                   var=None):
        """
        Get the boundaries of an unstructed coordinate

        Parameters
        ----------
        coord: xr.Variable
            The coordinate whose bounds should be returned
        %(CFDecoder.get_cell_node_coord.parameters.no_var|axis)s

        Returns
        -------
        %(CFDecoder.get_cell_node_coord.returns)s
        """
        bounds = coord.attrs.get('bounds')
        if bounds is not None:
            bounds = self.ds.coords.get(bounds)
        if bounds is not None:
            if coords is not None:
                bounds = bounds.sel(**{
                    key: coords[key]
                    for key in set(coords).intersection(bounds.dims)})
            if nans is not None and var is None:
                raise ValueError("Need the variable to deal with NaN!")
            elif nans is None:
                pass
            elif nans == 'skip':
                bounds = bounds[~np.isnan(var.values)]
            elif nans == 'only':
                bounds = bounds[np.isnan(var.values)]
            else:
                raise ValueError(
                    "`nans` must be either None, 'skip', or 'only'! "
                    "Not {0}!".format(str(nans)))
            return bounds


Instruction:
Implement a Python 3 function for
checking whether the bounds in the variable attribute are triangular.

Response:
def _check_triangular_bounds(self, var, coords=None, axis='x', nans=None):
        """
        Checks whether the bounds in the variable attribute are triangular

        Parameters
        ----------
        %(CFDecoder.get_cell_node_coord.parameters)s

        Returns
        -------
        bool or None
            True, if unstructered, None if it could not be determined
        xarray.Coordinate or None
            the bounds corrdinate (if existent)"""
        # !!! WILL BE REMOVED IN THE NEAR FUTURE! !!!
        bounds = self.get_cell_node_coord(var, coords, axis=axis,
                                              nans=nans)
        if bounds is not None:
            return bounds.shape[-1] == 3, bounds
        else:
            return None, None


Instruction:
Implement a Python 3 function for
testing if a variable is on an unstructered grid.

Response:
def is_unstructured(self, var):
        """
        Test if a variable is on an unstructered grid

        Parameters
        ----------
        %(CFDecoder.is_triangular.parameters)s

        Returns
        -------
        %(CFDecoder.is_triangular.returns)s

        Notes
        -----
        Currently this is the same as :meth:`is_triangular` method, but may
        change in the future to support hexagonal grids"""
        if str(var.attrs.get('grid_type')) == 'unstructured':
            return True
        xcoord = self.get_x(var)
        if xcoord is not None:
            bounds = self._get_coord_cell_node_coord(xcoord)
            if bounds is not None and bounds.shape[-1] > 2:
                return True


Instruction:
Can you write a function in Python 3 where it
tests if a variable is on a circumpolar grid

Response:
def is_circumpolar(self, var):
        """
        Test if a variable is on a circumpolar grid

        Parameters
        ----------
        %(CFDecoder.is_triangular.parameters)s

        Returns
        -------
        %(CFDecoder.is_triangular.returns)s"""
        xcoord = self.get_x(var)
        return xcoord is not None and xcoord.ndim == 2


Instruction:
Can you generate the documentation for the following Python 3 function
def get_variable_by_axis(self, var, axis, coords=None):
        axis = axis.lower()
        if axis not in list('xyzt'):
            raise ValueError("Axis must be one of X, Y, Z, T, not {0}".format(
                axis))
        # we first check for the dimensions and then for the coordinates
        # attribute
        coords = coords or self.ds.coords
        coord_names = var.attrs.get('coordinates', var.encoding.get(
            'coordinates', '')).split()
        if not coord_names:
            return
        ret = []
        for coord in map(lambda dim: coords[dim], filter(
                lambda dim: dim in coords, chain(
                    coord_names, var.dims))):
            # check for the axis attribute or whether the coordinate is in the
            # list of possible coordinate names
            if (coord.name not in (c.name for c in ret) and
                    (coord.attrs.get('axis', '').lower() == axis or
                     coord.name in getattr(self, axis))):
                ret.append(coord)
        if ret:
            return None if len(ret) > 1 else ret[0]
        # If the coordinates attribute is specified but the coordinate
        # variables themselves have no 'axis' attribute, we interpret the
        # coordinates such that x: -1, y: -2, z: -3
        # Since however the CF Conventions do not determine the order on how
        # the coordinates shall be saved, we try to use a pattern matching
        # for latitude and longitude. This is not very nice, hence it is
        # better to specify the :attr:`x` and :attr:`y` attribute
        tnames = self.t.intersection(coord_names)
        if axis == 'x':
            for cname in filter(lambda cname: re.search('lon', cname),
                                coord_names):
                return coords[cname]
            return coords.get(coord_names[-1])
        elif axis == 'y' and len(coord_names) >= 2:
            for cname in filter(lambda cname: re.search('lat', cname),
                                coord_names):
                return coords[cname]
            return coords.get(coord_names[-2])
        elif (axis == 'z' and len(coord_names) >= 3 and
              coord_names[-3] not in tnames):
            return coords.get(coord_names[-3])
        elif axis == 't' and tnames:
            tname = next(iter(tnames))
            if len(tnames) > 1:
                warn("Found multiple matches for time coordinate in the "
                     "coordinates: %s. I use %s" % (', '.join(tnames), tname),
                     PsyPlotRuntimeWarning)
            return coords.get(tname)

Response: This method returns the coordinate matching the specified axis for the given variable.


Instruction:
Can you create a Python 3 function that
returns the x - coordinate of a variable in the x - dimension of the dataset.

Response:
def get_x(self, var, coords=None):
        """
        Get the x-coordinate of a variable

        This method searches for the x-coordinate in the :attr:`ds`. It first
        checks whether there is one dimension that holds an ``'axis'``
        attribute with 'X', otherwise it looks whether there is an intersection
        between the :attr:`x` attribute and the variables dimensions, otherwise
        it returns the coordinate corresponding to the last dimension of `var`

        Possible types
        --------------
        var: xarray.Variable
            The variable to get the x-coordinate for
        coords: dict
            Coordinates to use. If None, the coordinates of the dataset in the
            :attr:`ds` attribute are used.

        Returns
        -------
        xarray.Coordinate or None
            The y-coordinate or None if it could be found"""
        coords = coords or self.ds.coords
        coord = self.get_variable_by_axis(var, 'x', coords)
        if coord is not None:
            return coord
        return coords.get(self.get_xname(var))


Instruction:
Can you create a Python 3 function that
gets the name of the x - dimension of the variable.

Response:
def get_xname(self, var, coords=None):
        """Get the name of the x-dimension

        This method gives the name of the x-dimension (which is not necessarily
        the name of the coordinate if the variable has a coordinate attribute)

        Parameters
        ----------
        var: xarray.Variables
            The variable to get the dimension for
        coords: dict
            The coordinates to use for checking the axis attribute. If None,
            they are not used

        Returns
        -------
        str
            The coordinate name

        See Also
        --------
        get_x"""
        if coords is not None:
            coord = self.get_variable_by_axis(var, 'x', coords)
            if coord is not None and coord.name in var.dims:
                return coord.name
        dimlist = list(self.x.intersection(var.dims))
        if dimlist:
            if len(dimlist) > 1:
                warn("Found multiple matches for x coordinate in the variable:"
                     "%s. I use %s" % (', '.join(dimlist), dimlist[0]),
                     PsyPlotRuntimeWarning)
            return dimlist[0]
        # otherwise we return the coordinate in the last position
        return var.dims[-1]


Instruction:
Create a Python 3 function to
return the y - coordinate of a variable in the dict.

Response:
def get_y(self, var, coords=None):
        """
        Get the y-coordinate of a variable

        This method searches for the y-coordinate in the :attr:`ds`. It first
        checks whether there is one dimension that holds an ``'axis'``
        attribute with 'Y', otherwise it looks whether there is an intersection
        between the :attr:`y` attribute and the variables dimensions, otherwise
        it returns the coordinate corresponding to the second last dimension of
        `var` (or the last if the dimension of var is one-dimensional)

        Possible types
        --------------
        var: xarray.Variable
            The variable to get the y-coordinate for
        coords: dict
            Coordinates to use. If None, the coordinates of the dataset in the
            :attr:`ds` attribute are used.

        Returns
        -------
        xarray.Coordinate or None
            The y-coordinate or None if it could be found"""
        coords = coords or self.ds.coords
        coord = self.get_variable_by_axis(var, 'y', coords)
        if coord is not None:
            return coord
        return coords.get(self.get_yname(var))


Instruction:
Create a Python 3 function to
get the name of the y - dimension for a variable.

Response:
def get_yname(self, var, coords=None):
        """Get the name of the y-dimension

        This method gives the name of the y-dimension (which is not necessarily
        the name of the coordinate if the variable has a coordinate attribute)

        Parameters
        ----------
        var: xarray.Variables
            The variable to get the dimension for
        coords: dict
            The coordinates to use for checking the axis attribute. If None,
            they are not used

        Returns
        -------
        str
            The coordinate name

        See Also
        --------
        get_y"""
        if coords is not None:
            coord = self.get_variable_by_axis(var, 'y', coords)
            if coord is not None and coord.name in var.dims:
                return coord.name
        dimlist = list(self.y.intersection(var.dims))
        if dimlist:
            if len(dimlist) > 1:
                warn("Found multiple matches for y coordinate in the variable:"
                     "%s. I use %s" % (', '.join(dimlist), dimlist[0]),
                     PsyPlotRuntimeWarning)
            return dimlist[0]
        # otherwise we return the coordinate in the last or second last
        # position
        if self.is_unstructured(var):
            return var.dims[-1]
        return var.dims[-2 if var.ndim > 1 else -1]


Instruction:
Can you implement a function in Python 3 that
returns the z - coordinate of a variable in the dataset.

Response:
def get_z(self, var, coords=None):
        """
        Get the vertical (z-) coordinate of a variable

        This method searches for the z-coordinate in the :attr:`ds`. It first
        checks whether there is one dimension that holds an ``'axis'``
        attribute with 'Z', otherwise it looks whether there is an intersection
        between the :attr:`z` attribute and the variables dimensions, otherwise
        it returns the coordinate corresponding to the third last dimension of
        `var` (or the second last or last if var is two or one-dimensional)

        Possible types
        --------------
        var: xarray.Variable
            The variable to get the z-coordinate for
        coords: dict
            Coordinates to use. If None, the coordinates of the dataset in the
            :attr:`ds` attribute are used.

        Returns
        -------
        xarray.Coordinate or None
            The z-coordinate or None if no z coordinate could be found"""
        coords = coords or self.ds.coords
        coord = self.get_variable_by_axis(var, 'z', coords)
        if coord is not None:
            return coord
        zname = self.get_zname(var)
        if zname is not None:
            return coords.get(zname)
        return None


Instruction:
Implement a function in Python 3 to
get the name of the z-dimension This method gives the name of the z-dimension (which is not necessarily the name of the coordinate if the variable has a coordinate attribute) Parameters ---------- var: xarray.Variables The variable to get the dimension for coords: dict The coordinates to use for checking the axis attribute. If None, they are not used Returns ------- str or None The coordinate name or None if no vertical coordinate could be found See Also -------- get_z

Response:
def get_zname(self, var, coords=None):
        """Get the name of the z-dimension

        This method gives the name of the z-dimension (which is not necessarily
        the name of the coordinate if the variable has a coordinate attribute)

        Parameters
        ----------
        var: xarray.Variables
            The variable to get the dimension for
        coords: dict
            The coordinates to use for checking the axis attribute. If None,
            they are not used

        Returns
        -------
        str or None
            The coordinate name or None if no vertical coordinate could be
            found

        See Also
        --------
        get_z"""
        if coords is not None:
            coord = self.get_variable_by_axis(var, 'z', coords)
            if coord is not None and coord.name in var.dims:
                return coord.name
        dimlist = list(self.z.intersection(var.dims))
        if dimlist:
            if len(dimlist) > 1:
                warn("Found multiple matches for z coordinate in the variable:"
                     "%s. I use %s" % (', '.join(dimlist), dimlist[0]),
                     PsyPlotRuntimeWarning)
            return dimlist[0]
        # otherwise we return the coordinate in the third last position
        is_unstructured = self.is_unstructured(var)
        icheck = -2 if is_unstructured else -3
        min_dim = abs(icheck) if 'variable' not in var.dims else abs(icheck-1)
        if var.ndim >= min_dim and var.dims[icheck] != self.get_tname(
                var, coords):
            return var.dims[icheck]
        return None


Instruction:
Can you generate the documentation for the following Python 3 function
def get_t(self, var, coords=None):
        coords = coords or self.ds.coords
        coord = self.get_variable_by_axis(var, 't', coords)
        if coord is not None:
            return coord
        dimlist = list(self.t.intersection(var.dims).intersection(coords))
        if dimlist:
            if len(dimlist) > 1:
                warn("Found multiple matches for time coordinate in the "
                     "variable: %s. I use %s" % (
                         ', '.join(dimlist), dimlist[0]),
                     PsyPlotRuntimeWarning)
            return coords[dimlist[0]]
        tname = self.get_tname(var)
        if tname is not None:
            return coords.get(tname)
        return None

Response: This method returns the time coordinate of a variable in the dataset.


Instruction:
Can you generate the documentation for the following Python 3 function
def get_tname(self, var, coords=None):
        if coords is not None:
            coord = self.get_variable_by_axis(var, 't', coords)
            if coord is not None and coord.name in var.dims:
                return coord.name
        dimlist = list(self.t.intersection(var.dims))
        if dimlist:
            if len(dimlist) > 1:
                warn("Found multiple matches for t coordinate in the variable:"
                     "%s. I use %s" % (', '.join(dimlist), dimlist[0]),
                     PsyPlotRuntimeWarning)
            return dimlist[0]
        # otherwise we return None
        return None

Response: Get the name of the t - dimension for the variable


Instruction:
How would you explain what the following Python 3 function does
def get_idims(self, arr, coords=None):
        if coords is None:
            coords = arr.coords
        else:
            coords = {
                label: coord for label, coord in six.iteritems(arr.coords)
                if label in coords}
        ret = self.get_coord_idims(coords)
        # handle the coordinates that are not in the dataset
        missing = set(arr.dims).difference(ret)
        if missing:
            warn('Could not get slices for the following dimensions: %r' % (
                missing, ), PsyPlotRuntimeWarning)
        return ret

Response:
Get the coordinates in the dataset as int or slice or list of integer that represent the the
            coordinates in the given array.


Instruction:
Make a summary of the following Python 3 code
def get_coord_idims(self, coords):
        ret = dict(
            (label, get_index_from_coord(coord, self.ds.indexes[label]))
            for label, coord in six.iteritems(coords)
            if label in self.ds.indexes)
        return ret

Response: Get the slicers for the given coordinates from the base dataset.


Instruction:
How would you explain what the following Python 3 function does
def get_plotbounds(self, coord, kind=None, ignore_shape=False):
        if 'bounds' in coord.attrs:
            bounds = self.ds.coords[coord.attrs['bounds']]
            if ignore_shape:
                return bounds.values.ravel()
            if not bounds.shape[:-1] == coord.shape:
                bounds = self.ds.isel(**self.get_idims(coord))
            try:
                return self._get_plotbounds_from_cf(coord, bounds)
            except ValueError as e:
                warn((e.message if six.PY2 else str(e)) +
                     " Bounds are calculated automatically!")
        return self._infer_interval_breaks(coord, kind=kind)

Response: Returns the plotbounds for a given coordinate.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _get_plotbounds_from_cf(coord, bounds):

        if bounds.shape[:-1] != coord.shape or bounds.shape[-1] != 2:
            raise ValueError(
                "Cannot interprete bounds with shape {0} for {1} "
                "coordinate with shape {2}.".format(
                    bounds.shape, coord.name, coord.shape))
        ret = np.zeros(tuple(map(lambda i: i+1, coord.shape)))
        ret[tuple(map(slice, coord.shape))] = bounds[..., 0]
        last_slices = tuple(slice(-1, None) for _ in coord.shape)
        ret[last_slices] = bounds[tuple(chain(last_slices, [1]))]
        return ret

Response: Get the plot bounds for a given coordinate and bounds.


Instruction:
Can you write a function in Python 3 where it
returns the set of triangles for the variable in the current object.

Response:
def get_triangles(self, var, coords=None, convert_radian=True,
                      copy=False, src_crs=None, target_crs=None,
                      nans=None, stacklevel=1):
        """
        Get the triangles for the variable

        Parameters
        ----------
        var: xarray.Variable or xarray.DataArray
            The variable to use
        coords: dict
            Alternative coordinates to use. If None, the coordinates of the
            :attr:`ds` dataset are used
        convert_radian: bool
            If True and the coordinate has units in 'radian', those are
            converted to degrees
        copy: bool
            If True, vertice arrays are copied
        src_crs: cartopy.crs.Crs
            The source projection of the data. If not None, a transformation
            to the given `target_crs` will be done
        target_crs: cartopy.crs.Crs
            The target projection for which the triangles shall be transformed.
            Must only be provided if the `src_crs` is not None.
        %(CFDecoder._check_triangular_bounds.parameters.nans)s

        Returns
        -------
        matplotlib.tri.Triangulation
            The spatial triangles of the variable

        Raises
        ------
        ValueError
            If `src_crs` is not None and `target_crs` is None"""
        warn("The 'get_triangles' method is depreceated and will be removed "
             "soon! Use the 'get_cell_node_coord' method!",
             DeprecationWarning, stacklevel=stacklevel)
        from matplotlib.tri import Triangulation

        def get_vertices(axis):
            bounds = self._check_triangular_bounds(var, coords=coords,
                                                   axis=axis, nans=nans)[1]
            if coords is not None:
                bounds = coords.get(bounds.name, bounds)
            vertices = bounds.values.ravel()
            if convert_radian:
                coord = getattr(self, 'get_' + axis)(var)
                if coord.attrs.get('units') == 'radian':
                    vertices = vertices * 180. / np.pi
            return vertices if not copy else vertices.copy()

        if coords is None:
            coords = self.ds.coords

        xvert = get_vertices('x')
        yvert = get_vertices('y')
        if src_crs is not None and src_crs != target_crs:
            if target_crs is None:
                raise ValueError(
                    "Found %s for the source crs but got None for the "
                    "target_crs!" % (src_crs, ))
            arr = target_crs.transform_points(src_crs, xvert, yvert)
            xvert = arr[:, 0]
            yvert = arr[:, 1]
        triangles = np.reshape(range(len(xvert)), (len(xvert) // 3, 3))
        return Triangulation(xvert, yvert, triangles)


Instruction:
Can you generate the documentation for the following Python 3 function
def _infer_interval_breaks(coord, kind=None):
        if coord.ndim == 1:
            return _infer_interval_breaks(coord)
        elif coord.ndim == 2:
            from scipy.interpolate import interp2d
            kind = kind or rcParams['decoder.interp_kind']
            y, x = map(np.arange, coord.shape)
            new_x, new_y = map(_infer_interval_breaks, [x, y])
            coord = np.asarray(coord)
            return interp2d(x, y, coord, kind=kind, copy=False)(new_x, new_y)

Response: Infer interval breaks from the data in coord.


Instruction:
Given the following Python 3 function, write the documentation
def correct_dims(self, var, dims={}, remove=True):
        method_mapping = {'x': self.get_xname,
                          'z': self.get_zname, 't': self.get_tname}
        dims = dict(dims)
        if self.is_unstructured(var):  # we assume a one-dimensional grid
            method_mapping['y'] = self.get_xname
        else:
            method_mapping['y'] = self.get_yname
        for key in six.iterkeys(dims.copy()):
            if key in method_mapping and key not in var.dims:
                dim_name = method_mapping[key](var, self.ds.coords)
                if dim_name in dims:
                    dims.pop(key)
                else:
                    new_name = method_mapping[key](var)
                    if new_name is not None:
                        dims[new_name] = dims.pop(key)
        # now remove the unnecessary dimensions
        if remove:
            for key in set(dims).difference(var.dims):
                dims.pop(key)
                self.logger.debug(
                    "Could not find a dimensions matching %s in variable %s!",
                    key, var)
        return dims

Response: Expands the dimensions to match the dims in the variable


Instruction:
Write a Python 3 script to
replace the coordinate names through x y z and t with the original dimensions of the original dimensions of the current object.

Response:
def standardize_dims(self, var, dims={}):
        """Replace the coordinate names through x, y, z and t

        Parameters
        ----------
        var: xarray.Variable
            The variable to use the dimensions of
        dims: dict
            The dictionary to use for replacing the original dimensions

        Returns
        -------
        dict
            The dictionary with replaced dimensions"""
        dims = dict(dims)
        name_map = {self.get_xname(var, self.ds.coords): 'x',
                    self.get_yname(var, self.ds.coords): 'y',
                    self.get_zname(var, self.ds.coords): 'z',
                    self.get_tname(var, self.ds.coords): 't'}
        dims = dict(dims)
        for dim in set(dims).intersection(name_map):
            dims[name_map[dim]] = dims.pop(dim)
        return dims


Instruction:
Implement a Python 3 function for
getting the mesh variable for the given variable

Response:
def get_mesh(self, var, coords=None):
        """Get the mesh variable for the given `var`

        Parameters
        ----------
        var: xarray.Variable
            The data source whith the ``'mesh'`` attribute
        coords: dict
            The coordinates to use. If None, the coordinates of the dataset of
            this decoder is used

        Returns
        -------
        xarray.Coordinate
            The mesh coordinate"""
        mesh = var.attrs.get('mesh')
        if mesh is None:
            return None
        if coords is None:
            coords = self.ds.coords
        return coords.get(mesh, self.ds.coords.get(mesh))


Instruction:
Here you have a function in Python 3, explain what it does
def get_triangles(self, var, coords=None, convert_radian=True, copy=False,
                      src_crs=None, target_crs=None, nans=None, stacklevel=1):
        """
        Get the of the given coordinate.

        Parameters
        ----------
        %(CFDecoder.get_triangles.parameters)s

        Returns
        -------
        %(CFDecoder.get_triangles.returns)s

        Notes
        -----
        If the ``'location'`` attribute is set to ``'node'``, a delaunay
        triangulation is performed using the
        :class:`matplotlib.tri.Triangulation` class.

        .. todo::
            Implement the visualization for UGrid data shown on the edge of the
            triangles"""
        warn("The 'get_triangles' method is depreceated and will be removed "
             "soon! Use the 'get_cell_node_coord' method!",
             DeprecationWarning, stacklevel=stacklevel)
        from matplotlib.tri import Triangulation

        if coords is None:
            coords = self.ds.coords

        def get_coord(coord):
            return coords.get(coord, self.ds.coords.get(coord))

        mesh = self.get_mesh(var, coords)
        nodes = self.get_nodes(mesh, coords)
        if any(n is None for n in nodes):
            raise ValueError("Could not find the nodes variables!")
        xvert, yvert = nodes
        xvert = xvert.values
        yvert = yvert.values
        loc = var.attrs.get('location', 'face')
        if loc == 'face':
            triangles = get_coord(
                mesh.attrs.get('face_node_connectivity', '')).values
            if triangles is None:
                raise ValueError(
                    "Could not find the connectivity information!")
        elif loc == 'node':
            triangles = None
        else:
            raise ValueError(
                "Could not interprete location attribute (%s) of mesh "
                "variable %s!" % (loc, mesh.name))

        if convert_radian:
            for coord in nodes:
                if coord.attrs.get('units') == 'radian':
                    coord = coord * 180. / np.pi
        if src_crs is not None and src_crs != target_crs:
            if target_crs is None:
                raise ValueError(
                    "Found %s for the source crs but got None for the "
                    "target_crs!" % (src_crs, ))
            xvert = xvert[triangles].ravel()
            yvert = yvert[triangles].ravel()
            arr = target_crs.transform_points(src_crs, xvert, yvert)
            xvert = arr[:, 0]
            yvert = arr[:, 1]
            if loc == 'face':
                triangles = np.reshape(range(len(xvert)), (len(xvert) // 3,
                                                           3))

        return Triangulation(xvert, yvert, triangles)

Response: Get the triangles of a given variable.


Instruction:
Can you generate the documentation for the following Python 3 function
def get_cell_node_coord(self, var, coords=None, axis='x', nans=None):
        if coords is None:
            coords = self.ds.coords

        idims = self.get_coord_idims(coords)

        def get_coord(coord):
            coord = coords.get(coord, self.ds.coords.get(coord))
            return coord.isel(**{d: sl for d, sl in idims.items()
                                 if d in coord.dims})

        mesh = self.get_mesh(var, coords)
        if mesh is None:
            return
        nodes = self.get_nodes(mesh, coords)
        if not len(nodes):
            raise ValueError("Could not find the nodes variables for the %s "
                             "coordinate!" % axis)
        vert = nodes[0 if axis == 'x' else 1]
        if vert is None:
            raise ValueError("Could not find the nodes variables for the %s "
                             "coordinate!" % axis)
        loc = var.attrs.get('location', 'face')
        if loc == 'node':
            # we assume a triangular grid and use matplotlibs triangulation
            from matplotlib.tri import Triangulation
            xvert, yvert = nodes
            triangles = Triangulation(xvert, yvert)
            if axis == 'x':
                bounds = triangles.x[triangles.triangles]
            else:
                bounds = triangles.y[triangles.triangles]
        elif loc in ['edge', 'face']:
            connectivity = get_coord(
                mesh.attrs.get('%s_node_connectivity' % loc, ''))
            if connectivity is None:
                raise ValueError(
                    "Could not find the connectivity information!")
            connectivity = connectivity.values
            bounds = vert.values[
                np.where(np.isnan(connectivity), connectivity[:, :1],
                         connectivity).astype(int)]
        else:
            raise ValueError(
                "Could not interprete location attribute (%s) of mesh "
                "variable %s!" % (loc, mesh.name))
        dim0 = '__face' if loc == 'node' else var.dims[-1]
        return xr.DataArray(
            bounds,
            coords={key: val for key, val in coords.items()
                    if (dim0, ) == val.dims},
            dims=(dim0, '__bnds', ),
            name=vert.name + '_bnds',  attrs=vert.attrs.copy())

Response: Returns the node coordinates for a variable in the specified axis.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def decode_coords(ds, gridfile=None):
        extra_coords = set(ds.coords)
        for var in six.itervalues(ds.variables):
            if 'mesh' in var.attrs:
                mesh = var.attrs['mesh']
                if mesh not in extra_coords:
                    extra_coords.add(mesh)
                    try:
                        mesh_var = ds.variables[mesh]
                    except KeyError:
                        warn('Could not find mesh variable %s' % mesh)
                        continue
                    if 'node_coordinates' in mesh_var.attrs:
                        extra_coords.update(
                            mesh_var.attrs['node_coordinates'].split())
                    if 'face_node_connectivity' in mesh_var.attrs:
                        extra_coords.add(
                            mesh_var.attrs['face_node_connectivity'])
        if gridfile is not None and not isinstance(gridfile, xr.Dataset):
            gridfile = open_dataset(gridfile)
            ds.update({k: v for k, v in six.iteritems(gridfile.variables)
                       if k in extra_coords})
        if xr_version < (0, 11):
            ds.set_coords(extra_coords.intersection(ds.variables),
                          inplace=True)
        else:
            ds._coord_names.update(extra_coords.intersection(ds.variables))
        return ds

Response: Reimplemented to set the variables as coordinates


Instruction:
Can you write a function in Python 3 where it
gets the variables containing the definition of the nodes

Response:
def get_nodes(self, coord, coords):
        """Get the variables containing the definition of the nodes

        Parameters
        ----------
        coord: xarray.Coordinate
            The mesh variable
        coords: dict
            The coordinates to use to get node coordinates"""
        def get_coord(coord):
            return coords.get(coord, self.ds.coords.get(coord))
        return list(map(get_coord,
                        coord.attrs.get('node_coordinates', '').split()[:2]))


Instruction:
Explain what the following Python 3 code does
def get_x(self, var, coords=None):
        if coords is None:
            coords = self.ds.coords
        # first we try the super class
        ret = super(UGridDecoder, self).get_x(var, coords)
        # but if that doesn't work because we get the variable name in the
        # dimension of `var`, we use the means of the triangles
        if ret is None or ret.name in var.dims:
            bounds = self.get_cell_node_coord(var, axis='x', coords=coords)
            if bounds is not None:
                centers = bounds.mean(axis=-1)
                x = self.get_nodes(self.get_mesh(var, coords), coords)[0]
                try:
                    cls = xr.IndexVariable
                except AttributeError:  # xarray < 0.9
                    cls = xr.Coordinate
                return cls(x.name, centers, attrs=x.attrs.copy())

Response: Get the centers of the triangles in the x - dimension.


Instruction:
Explain what the following Python 3 code does
def start_update(self, draw=None, queues=None):
        if self.plotter is not None:
            return self.plotter.start_update(draw=draw, queues=queues)

Response:
Start an update of the current state of the a
           .


Instruction:
Can you tell what is the following Python 3 function doing
def update(self, fmt={}, replot=False, draw=None, auto_update=False,
               force=False, todefault=False, **kwargs):
        """
        Update the coordinates and the plot

        This method updates all arrays in this list with the given coordinate
        values and formatoptions.

        Parameters
        ----------
        %(InteractiveBase._register_update.parameters)s
        auto_update: bool
            Boolean determining whether or not the :meth:`start_update` method
            is called at the end. This parameter has no effect if the
            :attr:`no_auto_update` attribute is set to ``True``.
        %(InteractiveBase.start_update.parameters.draw)s
        ``**kwargs``
            Any other formatoption that shall be updated (additionally to those
            in `fmt`)

        Notes
        -----
        If the :attr:`no_auto_update` attribute is True and the given
        `auto_update` parameter are is False, the update of the plots are
        registered and conducted at the next call of the :meth:`start_update`
        method or the next call of this method (if the `auto_update` parameter
        is then True).
        """
        fmt = dict(fmt)
        fmt.update(kwargs)

        self._register_update(replot=replot, fmt=fmt, force=force,
                              todefault=todefault)

        if not self.no_auto_update or auto_update:
            self.start_update(draw=draw)

Response:
Update the coordinates and the plot
            in this list.


Instruction:
Make a summary of the following Python 3 code
def names(self):
        ret = set()
        for arr in self:
            if isinstance(arr, InteractiveList):
                ret.update(arr.names)
            else:
                ret.add(arr.name)
        return ret

Response: Returns a set of the variable names in this list


Instruction:
Make a summary of the following Python 3 code
def all_dims(self):
        return [
            _get_dims(arr) if not isinstance(arr, ArrayList) else
            arr.all_dims
            for arr in self]

Response: The dimensions for each of the arrays in this list.


Instruction:
Here you have a function in Python 3, explain what it does
def is_unstructured(self):
        return [
            arr.psy.decoder.is_unstructured(arr)
            if not isinstance(arr, ArrayList) else
            arr.is_unstructured
            for arr in self]

Response: A boolean for each array whether it is unstructured or not


Instruction:
Explain what the following Python 3 code does
def coords_intersect(self):
        return set.intersection(*map(
            set, (getattr(arr, 'coords_intersect', arr.coords) for arr in self)
            ))

Response: Coordinates of the arrays in this list that are used in all arrays


Instruction:
Write a Python 3 function for
returning a new instance with only the arrays that are visualized with a plotter.

Response:
def with_plotter(self):
        """The arrays in this instance that are visualized with a plotter"""
        return self.__class__(
            (arr for arr in self if arr.psy.plotter is not None),
            auto_update=bool(self.auto_update))


Instruction:
Given the following Python 3 function, write the documentation
def arrays(self):
        return list(chain.from_iterable(
            ([arr] if not isinstance(arr, InteractiveList) else arr.arrays
             for arr in self)))

Response: A list of all the data arrays in this list.


Instruction:
Explain what the following Python 3 code does
def rename(self, arr, new_name=True):
        name_in_me = arr.psy.arr_name in self.arr_names
        if not name_in_me:
            return arr, False
        elif name_in_me and not self._contains_array(arr):
            if new_name is False:
                raise ValueError(
                    "Array name %s is already in use! Set the `new_name` "
                    "parameter to None for renaming!" % arr.psy.arr_name)
            elif new_name is True:
                new_name = new_name if isstring(new_name) else 'arr{0}'
                arr.psy.arr_name = self.next_available_name(new_name)
                return arr, True
        return arr, None

Response: Rename an array to find a name that isn t already in the list.


Instruction:
Create a Python 3 function for
returning a copy of the list containing the same attributes and attributes.

Response:
def copy(self, deep=False):
        """Returns a copy of the list

        Parameters
        ----------
        deep: bool
            If False (default), only the list is copied and not the contained
            arrays, otherwise the contained arrays are deep copied"""
        if not deep:
            return self.__class__(self[:], attrs=self.attrs.copy(),
                                  auto_update=not bool(self.no_auto_update))
        else:
            return self.__class__(
                [arr.psy.copy(deep) for arr in self], attrs=self.attrs.copy(),
                auto_update=not bool(self.auto_update))


Instruction:
Create a Python 3 function for
constructing an ArrayList instance from an existing base dataset.

Response:
def from_dataset(cls, base, method='isel', default_slice=None,
                     decoder=None, auto_update=None, prefer_list=False,
                     squeeze=True, attrs=None, load=False, **kwargs):
        """
        Construct an ArrayList instance from an existing base dataset

        Parameters
        ----------
        base: xarray.Dataset
            Dataset instance that is used as reference
        %(InteractiveArray.update.parameters.method)s
        %(InteractiveBase.parameters.auto_update)s
        prefer_list: bool
            If True and multiple variable names pher array are found, the
            :class:`InteractiveList` class is used. Otherwise the arrays are
            put together into one :class:`InteractiveArray`.
        default_slice: indexer
            Index (e.g. 0 if `method` is 'isel') that shall be used for
            dimensions not covered by `dims` and `furtherdims`. If None, the
            whole slice will be used.
        decoder: CFDecoder
            The decoder that shall be used to decoder the `base` dataset
        squeeze: bool, optional
            Default True. If True, and the created arrays have a an axes with
            length 1, it is removed from the dimension list (e.g. an array
            with shape (3, 4, 1, 5) will be squeezed to shape (3, 4, 5))
        attrs: dict, optional
            Meta attributes that shall be assigned to the selected data arrays
            (additional to those stored in the `base` dataset)
        load: bool or dict
            If True, load the data from the dataset using the
            :meth:`xarray.DataArray.load` method. If :class:`dict`, those will
            be given to the above mentioned ``load`` method

        Other Parameters
        ----------------
        %(setup_coords.parameters)s

        Returns
        -------
        ArrayList
            The list with the specified :class:`InteractiveArray` instances
            that hold a reference to the given `base`"""
        try:
            load = dict(load)
        except (TypeError, ValueError):
            def maybe_load(arr):
                return arr.load() if load else arr
        else:
            def maybe_load(arr):
                return arr.load(**load)

        def iter_dims(dims):
            """Split the given dictionary into multiples and iterate over it"""
            if not dims:
                while 1:
                    yield {}
            else:
                dims = OrderedDict(dims)
                keys = dims.keys()
                for vals in zip(*map(cycle, map(safe_list, dims.values()))):
                    yield dict(zip(keys, vals))

        def recursive_selection(key, dims, names):
            names = safe_list(names)
            if len(names) > 1 and prefer_list:
                keys = ('arr%i' % i for i in range(len(names)))
                return InteractiveList(
                    starmap(sel_method, zip(keys, iter_dims(dims), names)),
                    auto_update=auto_update, arr_name=key)
            elif len(names) > 1:
                return sel_method(key, dims, tuple(names))
            else:
                return sel_method(key, dims, names[0])

        def ds2arr(arr):
            base_var = next(var for key, var in arr.variables.items()
                            if key not in arr.coords)
            attrs = base_var.attrs
            arr = arr.to_array()
            if 'coordinates' in base_var.encoding:
                arr.encoding['coordinates'] = base_var.encoding[
                    'coordinates']
            arr.attrs.update(attrs)
            return arr

        if decoder is not None:
            def get_decoder(arr):
                return decoder
        else:
            def get_decoder(arr):
                return CFDecoder.get_decoder(base, arr)

        def add_missing_dimensions(arr):
            # add the missing dimensions to the dataset. This is not anymore
            # done by default from xarray >= 0.9 but we need it to ensure the
            # interactive treatment of DataArrays
            missing = set(arr.dims).difference(base.coords) - {'variable'}
            for dim in missing:
                base[dim] = arr.coords[dim] = np.arange(base.dims[dim])

        if squeeze:
            def squeeze_array(arr):
                return arr.isel(**{dim: 0 for i, dim in enumerate(arr.dims)
                                   if arr.shape[i] == 1})
        else:
            def squeeze_array(arr):
                return arr
        if method == 'isel':
            def sel_method(key, dims, name=None):
                if name is None:
                    return recursive_selection(key, dims, dims.pop('name'))
                elif (isinstance(name, six.string_types) or
                      not utils.is_iterable(name)):
                    arr = base[name]
                else:
                    arr = base[list(name)]
                add_missing_dimensions(arr)
                if not isinstance(arr, xr.DataArray):
                    arr = ds2arr(arr)
                def_slice = slice(None) if default_slice is None else \
                    default_slice
                decoder = get_decoder(arr)
                dims = decoder.correct_dims(arr, dims)
                dims.update({
                    dim: def_slice for dim in set(arr.dims).difference(
                        dims) if dim != 'variable'})
                ret = squeeze_array(arr.isel(**dims))
                # delete the variable dimension for the idims
                dims.pop('variable', None)
                ret.psy.init_accessor(arr_name=key, base=base, idims=dims)
                return maybe_load(ret)
        else:
            def sel_method(key, dims, name=None):
                if name is None:
                    return recursive_selection(key, dims, dims.pop('name'))
                elif (isinstance(name, six.string_types) or
                      not utils.is_iterable(name)):
                    arr = base[name]
                else:
                    arr = base[list(name)]
                add_missing_dimensions(arr)
                if not isinstance(arr, xr.DataArray):
                    arr = ds2arr(arr)
                # idims will be calculated by the array (maybe not the most
                # efficient way...)
                decoder = get_decoder(arr)
                dims = decoder.correct_dims(arr, dims)
                if default_slice is not None:
                    dims.update({
                        key: default_slice for key in set(arr.dims).difference(
                            dims) if key != 'variable'})
                # the sel method does not work with slice objects
                if any(isinstance(idx, slice) for idx in dims.values()):
                    # ignore method argument
                    ret = squeeze_array(arr.sel(**dims))
                else:
                    ret = squeeze_array(arr.sel(method=method, **dims))
                ret.psy.init_accessor(arr_name=key, base=base)
                return maybe_load(ret)
        if 'name' not in kwargs:
            default_names = list(
                key for key in base.variables if key not in base.coords)
            try:
                default_names.sort()
            except TypeError:
                pass
            kwargs['name'] = default_names
        names = setup_coords(**kwargs)
        # check coordinates
        possible_keys = ['t', 'x', 'y', 'z', 'name'] + list(base.dims)
        for key in set(chain(*six.itervalues(names))):
            utils.check_key(key, possible_keys, name='dimension')
        instance = cls(starmap(sel_method, six.iteritems(names)),
                       attrs=base.attrs, auto_update=auto_update)
        # convert to interactive lists if an instance is not
        if prefer_list and any(
                not isinstance(arr, InteractiveList) for arr in instance):
            # if any instance is an interactive list, than convert the others
            if any(isinstance(arr, InteractiveList) for arr in instance):
                for i, arr in enumerate(instance):
                    if not isinstance(arr, InteractiveList):
                        instance[i] = InteractiveList([arr])
            else:  # put everything into one single interactive list
                instance = cls([InteractiveList(instance, attrs=base.attrs,
                                                auto_update=auto_update)])
                instance[0].psy.arr_name = instance[0][0].psy.arr_name
        if attrs is not None:
            for arr in instance:
                arr.attrs.update(attrs)
        return instance


Instruction:
Here you have a function in Python 3, explain what it does
def _get_ds_descriptions_unsorted(
            cls, data, ignore_keys=['attrs', 'plotter'], nums=None):
        """Recursive method to get all the file names or datasets out of a
        dictionary `data` created with the :meth`array_info` method"""
        ds_description = {'ds', 'fname', 'num', 'arr', 'store'}
        if 'ds' in data:
            # make sure that the data set has a number assigned to it
            data['ds'].psy.num
        keys_in_data = ds_description.intersection(data)
        if keys_in_data:
            return {key: data[key] for key in keys_in_data}
        for key in ignore_keys:
            data.pop(key, None)
        func = partial(cls._get_ds_descriptions_unsorted,
                       ignore_keys=ignore_keys, nums=nums)
        return chain(*map(lambda d: [d] if isinstance(d, dict) else d,
                          map(func, six.itervalues(data))))

Response:
Recursive method to get all the file names or datasets out of a
            dictionary data