Instruction:
Write a Python 3 script to
schedule a new measurement.

Response:
def put(self, measurementId):
        """
        Initiates a new measurement. Accepts a json payload with the following attributes;

        * duration: in seconds
        * startTime OR delay: a date in YMD_HMS format or a delay in seconds
        * description: some free text information about the measurement

        :return:
        """
        json = request.get_json()
        try:
            start = self._calculateStartTime(json)
        except ValueError:
            return 'invalid date format in request', 400
        duration = json['duration'] if 'duration' in json else 10
        if start is None:
            # should never happen but just in case
            return 'no start time', 400
        else:
            scheduled, message = self._measurementController.schedule(measurementId, duration, start,
                                                                      description=json.get('description'))
            return message, 200 if scheduled else 400


Instruction:
Can you tell what is the following Python 3 function doing
def _calculateStartTime(self, json):
        start = json['startTime'] if 'startTime' in json else None
        delay = json['delay'] if 'delay' in json else None
        if start is None and delay is None:
            return self._getAbsoluteTime(datetime.datetime.utcnow(), 2)
        elif start is not None:
            target = datetime.datetime.strptime(start, DATETIME_FORMAT)
            if target <= datetime.datetime.utcnow():
                time = self._getAbsoluteTime(datetime.datetime.utcnow(), 2)
                logger.warning('Date requested is in the past (' + start + '), defaulting to ' +
                               time.strftime(DATETIME_FORMAT))
                return time
            else:
                return target
        elif delay is not None:
            return self._getAbsoluteTime(datetime.datetime.utcnow(), delay)
        else:
            return None

Response: Calculates an absolute start time from the json payload.


Instruction:
How would you code a function in Python 3 to
return the absolute time for the specified point in time.

Response:
def _getAbsoluteTime(self, start, delay):
        """
        Adds the delay in seconds to the start time.
        :param start:
        :param delay:
        :return: a datetimem for the specified point in time.
        """
        return start + datetime.timedelta(days=0, seconds=delay)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def delete(self, measurementId):
        message, count, deleted = self._measurementController.delete(measurementId)
        if count == 0:
            return message, 404
        elif deleted is None:
            return message, 500
        else:
            return deleted, 200

Response: Deletes the named measurement.


Instruction:
Explain what the following Python 3 code does
def put(self, measurementId, deviceId):
        logger.info('Starting measurement ' + measurementId + ' for ' + deviceId)
        if self._measurementController.startMeasurement(measurementId, deviceId):
            logger.info('Started measurement ' + measurementId + ' for ' + deviceId)
            return None, 200
        else:
            logger.warning('Failed to start measurement ' + measurementId + ' for ' + deviceId)
            return None, 404

Response: Starts the measurement session from the given device.


Instruction:
Write a Python 3 script for
storing a bunch of data for this measurement session.

Response:
def put(self, measurementId, deviceId):
        """
        Store a bunch of data for this measurement session.
        :param measurementId:
        :param deviceId:
        :return:
        """
        data = request.get_json()
        if data is not None:
            parsedData = json.loads(data)
            logger.debug('Received payload ' + measurementId + '/' + deviceId + ': ' +
                         str(len(parsedData)) + ' records')
            if self._measurementController.recordData(measurementId, deviceId, parsedData):
                return None, 200
            else:
                logger.warning('Unable to record payload ' + measurementId + '/' + deviceId)
                return None, 404
        else:
            logger.error('Invalid data payload received ' + measurementId + '/' + deviceId)
            return None, 400


Instruction:
Given the following Python 3 function, write the documentation
def put(self, measurementId, deviceId):
        payload = request.get_json()
        failureReason = json.loads(payload).get('failureReason') if payload is not None else None
        logger.warning('Failing measurement ' + measurementId + ' for ' + deviceId + ' because ' + str(failureReason))
        if self._measurementController.failMeasurement(measurementId, deviceId, failureReason=failureReason):
            logger.warning('Failed measurement ' + measurementId + ' for ' + deviceId)
            return None, 200
        else:
            logger.error('Unable to fail measurement ' + measurementId + ' for ' + deviceId)
            return None, 404

Response: Fail the measurement for this device.


Instruction:
Make a summary of the following Python 3 code
def put(self, deviceId):
        device = request.get_json()
        logger.debug("Received /devices/" + deviceId + " - " + str(device))
        self._deviceController.accept(deviceId, device)
        return None, 200

Response: Put a new device into the device store.


Instruction:
Can you generate the documentation for the following Python 3 function
def printColsAuto(in_strings, term_width=80, min_pad=1):
    # sanity check
    assert in_strings and len(in_strings)>0, 'Unexpected: '+repr(in_strings)

    # get max width in input
    maxWidth = len(max(in_strings, key=len)) + (2*min_pad) # width with pad
    numCols = term_width//maxWidth # integer div
    # set numCols so we take advantage of the whole line width
    numCols = min(numCols, len(in_strings))

    # easy case - single column or too big
    if numCols < 2:
        # one or some items are too big but print one item per line anyway
        lines = [x.center(term_width) for x in in_strings]
        return '\n'.join(lines)

    # normal case - 2 or more columns
    colWidth = term_width//numCols # integer div
    # colWidth is guaranteed to be larger than all items in input
    retval = ''
    for i in range(len(in_strings)):
        retval+=in_strings[i].center(colWidth)
        if (i+1)%numCols == 0:
            retval += '\n'
    return retval.rstrip()

Response: Print a list of strings centered in columns and lines on the fly.


Instruction:
How would you implement a function in Python 3 that
prints elements of list in cols columns

Response:
def printCols(strlist,cols=5,width=80):

    """Print elements of list in cols columns"""

    # This may exist somewhere in the Python standard libraries?
    # Should probably rewrite this, it is pretty crude.

    nlines = (len(strlist)+cols-1)//cols
    line = nlines*[""]
    for i in range(len(strlist)):
        c, r = divmod(i,nlines)
        nwid = c*width//cols - len(line[r])
        if nwid>0:
            line[r] = line[r] + nwid*" " + strlist[i]
        else:
            line[r] = line[r] + " " + strlist[i]
    for s in line:
        print(s)


Instruction:
Explain what the following Python 3 code does
def stripQuotes(value):

    """Strip single or double quotes off string; remove embedded quote pairs"""

    if value[:1] == '"':
        value = value[1:]
        if value[-1:] == '"':
            value = value[:-1]
        # replace "" with "
        value = re.sub(_re_doubleq2, '"', value)
    elif value[:1] == "'":
        value = value[1:]
        if value[-1:] == "'":
            value = value[:-1]
        # replace '' with '
        value = re.sub(_re_singleq2, "'", value)
    return value

Response: Strip single or double quotes off string ; remove embedded quote pairs


Instruction:
Write a Python 3 script to
take a string as input and splits it into tokens separated by commas ignoring embedded inside quoted sections.

Response:
def csvSplit(line, delim=',', allowEol=True):
    """ Take a string as input (e.g. a line in a csv text file), and break
    it into tokens separated by commas while ignoring commas embedded inside
    quoted sections.  This is exactly what the 'csv' module is meant for, so
    we *should* be using it, save that it has two bugs (described next) which
    limit our use of it.  When these bugs are fixed, this function should be
    forsaken in favor of direct use of the csv module (or similar).

    The basic use case is to split a function signature string, so for:
        afunc(arg1='str1', arg2='str, with, embedded, commas', arg3=7)
    we want a 3 element sequence:
        ["arg1='str1'", "arg2='str, with, embedded, commas'", "arg3=7"]

    but:
    >>> import csv
    >>> y = "arg1='str1', arg2='str, with, embedded, commas', arg3=7"
    >>> rdr = csv.reader( (y,), dialect='excel', quotechar="'", skipinitialspace=True)
    >>> l = rdr.next(); print(len(l), str(l))  # doctest: +SKIP
    6 ["arg1='str1'", "arg2='str", 'with', 'embedded', "commas'", "arg3=7"]

    which we can see is not correct - we wanted 3 tokens.  This occurs in
    Python 2.5.2 and 2.6.  It seems to be due to the text at the start of each
    token ("arg1=") i.e. because the quote isn't for the whole token.  If we
    were to remove the names of the args and the equal signs, it works:

    >>> x = "'str1', 'str, with, embedded, commas', 7"
    >>> rdr = csv.reader( (x,), dialect='excel', quotechar="'", skipinitialspace=True)
    >>> l = rdr.next(); print(len(l), str(l))  # doctest: +SKIP
    3 ['str1', 'str, with, embedded, commas', '7']

    But even this usage is delicate - when we turn off skipinitialspace, it
    fails:

    >>> x = "'str1', 'str, with, embedded, commas', 7"
    >>> rdr = csv.reader( (x,), dialect='excel', quotechar="'")
    >>> l = rdr.next(); print(len(l), str(l))  # doctest: +SKIP
    6 ['str1', " 'str", ' with', ' embedded', " commas'", ' 7']

    So, for now, we'll roll our own.
    """
    # Algorithm:  read chars left to right, go from delimiter to delimiter,
    # but as soon as a single/double/triple quote is hit, scan forward
    # (ignoring all else) until its matching end-quote is found.
    # For now, we will not specially handle escaped quotes.
    tokens = []
    ldl = len(delim)
    keepOnRollin = line is not None and len(line) > 0
    while keepOnRollin:
        tok = _getCharsUntil(line, delim, True, allowEol=allowEol)
        # len of token should always be > 0 because it includes end delimiter
        # except on last token
        if len(tok) > 0:
            # append it, but without the delimiter
            if tok[-ldl:] == delim:
                tokens.append(tok[:-ldl])
            else:
                tokens.append(tok) # tok goes to EOL - has no delimiter
                keepOnRollin = False
            line = line[len(tok):]
        else:
            # This is the case of the empty end token
            tokens.append('')
            keepOnRollin = False
    return tokens


Instruction:
Can you generate the documentation for the following Python 3 function
def rglob(root, pattern):
    # Thanks to Alex Martelli for basics on Stack Overflow
    retlist = []
    if None not in (pattern, root):
        for base, dirs, files in os.walk(root):
            goodfiles = fnmatch.filter(files, pattern)
            retlist.extend(os.path.join(base, f) for f in goodfiles)
    return retlist

Response: Globs the root directory for all files matching the pattern.


Instruction:
How would you implement a function in Python 3 that
sets a file named fname to be writable by user.

Response:
def setWritePrivs(fname, makeWritable, ignoreErrors=False):
    """ Set a file named fname to be writable (or not) by user, with the
    option to ignore errors.  There is nothing ground-breaking here, but I
    was annoyed with having to repeate this little bit of code. """
    privs = os.stat(fname).st_mode
    try:
        if makeWritable:
            os.chmod(fname, privs | stat.S_IWUSR)
        else:
            os.chmod(fname, privs & (~ stat.S_IWUSR))
    except OSError:
        if ignoreErrors:
            pass # just try, don't whine
        else:
            raise


Instruction:
How would you explain what the following Python 3 function does
def removeEscapes(value, quoted=0):

    """Remove escapes from in front of quotes (which IRAF seems to
    just stick in for fun sometimes.)  Remove \-newline too.
    If quoted is true, removes all blanks following \-newline
    (which is a nasty thing IRAF does for continuations inside
    quoted strings.)
    XXX Should we remove \\ too?
    """

    i = value.find(r'\"')
    while i>=0:
        value = value[:i] + value[i+1:]
        i = value.find(r'\"',i+1)
    i = value.find(r"\'")
    while i>=0:
        value = value[:i] + value[i+1:]
        i = value.find(r"\'",i+1)
    # delete backslash-newlines
    i = value.find("\\\n")
    while i>=0:
        j = i+2
        if quoted:
            # ignore blanks and tabs following \-newline in quoted strings
            for c in value[i+2:]:
                if c not in ' \t':
                    break
                j = j+1
        value = value[:i] + value[j:]
        i = value.find("\\\n",i+1)
    return value

Response: Remove escapes from in front of quotes.


Instruction:
Create a Python 3 function for
translating CL parameter or variable name to Python - acceptable name

Response:
def translateName(s, dot=0):

    """Convert CL parameter or variable name to Python-acceptable name

    Translate embedded dollar signs to 'DOLLAR'
    Add 'PY' prefix to components that are Python reserved words
    Add 'PY' prefix to components start with a number
    If dot != 0, also replaces '.' with 'DOT'
    """

    s = s.replace('$', 'DOLLAR')
    sparts = s.split('.')
    for i in range(len(sparts)):
        if sparts[i] == "" or sparts[i][0] in string.digits or \
          keyword.iskeyword(sparts[i]):
            sparts[i] = 'PY' + sparts[i]
    if dot:
        return 'DOT'.join(sparts)
    else:
        return '.'.join(sparts)


Instruction:
How would you explain what the following Python 3 function does
def init_tk_default_root(withdraw=True):

    """ In case the _default_root value is required, you may
    safely call this ahead of time to ensure that it has been
    initialized.  If it has already been, this is a no-op.
    """
    if not capable.OF_GRAPHICS:
        raise RuntimeError("Cannot run this command without graphics")

    if not TKNTR._default_root: # TKNTR imported above
        junk = TKNTR.Tk()

    # tkinter._default_root is now populated (== junk)
    retval = TKNTR._default_root
    if withdraw and retval:
        retval.withdraw()

    return retval

Response: Initialize the _default_root value of the TK.


Instruction:
Write a Python 3 script for
reading a line from file while running Tk mainloop.

Response:
def tkreadline(file=None):

    """Read a line from file while running Tk mainloop.

    If the file is not line-buffered then the Tk mainloop will stop
    running after one character is typed.  The function will still work
    but Tk widgets will stop updating.  This should work OK for stdin and
    other line-buffered filehandles.  If file is omitted, reads from
    sys.stdin.

    The file must have a readline method.  If it does not have a fileno
    method (which can happen e.g. for the status line input on the
    graphics window) then the readline method is simply called directly.
    """

    if file is None:
        file = sys.stdin
    if not hasattr(file, "readline"):
        raise TypeError("file must be a filehandle with a readline method")

    # Call tkread now...
    # BUT, if we get in here for something not GUI-related (e.g. terminal-
    # focused code in a sometimes-GUI app) then skip tkread and simply call
    # readline on the input eg. stdin.  Otherwise we'd fail in _TkRead().read()

    try:
        fd = file.fileno()
    except:
        fd = None

    if (fd and capable.OF_GRAPHICS):
        tkread(fd, 0)
        # if EOF was encountered on a tty, avoid reading again because
        # it actually requests more data
        if not select.select([fd],[],[],0)[0]:
            return ''
    return file.readline()


Instruction:
How would you explain what the following Python 3 function does
def launchBrowser(url, brow_bin='mozilla', subj=None):

    if not subj: subj = url

    # Tries to use webbrowser module on most OSes, unless a system command
    # is needed.  (E.g. win, linux, sun, etc)
    if sys.platform not in ('os2warp, iphone'): # try webbrowser w/ everything?
        import webbrowser
        if not webbrowser.open(url):
            print("Error opening URL: "+url)
        else:
            print('Help on "'+subj+'" is now being displayed in a web browser')
        return

    # Go ahead and fork a subprocess to call the correct binary
    pid = os.fork()
    if pid == 0: # child
        if sys.platform == 'darwin':
            if 0 != os.system('open "'+url+'"'): # does not seem to keep '#.*'
                print("Error opening URL: "+url)
        os._exit(0)
#       The following retries if "-remote" doesnt work, opening a new browser
#       cmd = brow_bin+" -remote 'openURL("+url+")' '"+url+"' 1> /dev/null 2>&1"
#       if 0 != os.system(cmd)
#           print "Running "+brow_bin+" for HTML help..."
#           os.execvp(brow_bin,[brow_bin,url])
#       os._exit(0)

    else: # parent
        if not subj:
            subj = url
        print('Help on "'+subj+'" is now being displayed in a browser')

Response: Tries to open a URL in a browser and launches it.


Instruction:
Given the following Python 3 function, write the documentation
def read(self, file, nbytes):
        if not capable.OF_GRAPHICS:
            raise RuntimeError("Cannot run this command without graphics")
        if isinstance(file, int):
            fd = file
        else:
            # Otherwise, assume we have Python file object
            try:
                fd = file.fileno()

            except:
                raise TypeError("file must be an integer or a filehandle/socket")
        init_tk_default_root() # harmless if already done
        self.widget = TKNTR._default_root
        if not self.widget:
            # no Tk widgets yet, so no need for mainloop
            # (shouldnt happen now with init_tk_default_root)
            s = []
            while nbytes>0:
                snew = os.read(fd, nbytes) # returns bytes in PY3K
                if snew:
                    if PY3K: snew = snew.decode('ascii','replace')
                    s.append(snew)
                    nbytes -= len(snew)
                else:
                    # EOF -- just return what we have so far
                    break
            return "".join(s)
        else:
            self.nbytes = nbytes
            self.value = []
            self.widget.tk.createfilehandler(fd,
                                    TKNTR.READABLE | TKNTR.EXCEPTION,
                                    self._read)
            try:
                self.widget.mainloop()
            finally:
                self.widget.tk.deletefilehandler(fd)
            return "".join(self.value)

Response: Read nbytes characters from file while running Tk mainloop


Instruction:
Write a Python 3 script to
read waiting data and terminate Tk mainloop if done

Response:
def _read(self, fd, mask):
        """Read waiting data and terminate Tk mainloop if done"""
        try:
            # if EOF was encountered on a tty, avoid reading again because
            # it actually requests more data
            if select.select([fd],[],[],0)[0]:
                snew = os.read(fd, self.nbytes) # returns bytes in PY3K
                if PY3K: snew = snew.decode('ascii','replace')
                self.value.append(snew)
                self.nbytes -= len(snew)
            else:
                snew = ''
            if (self.nbytes <= 0 or len(snew) == 0) and self.widget:
                # stop the mainloop
                self.widget.quit()
        except OSError:
            raise IOError("Error reading from %s" % (fd,))


Instruction:
Explain what the following Python 3 code does
def loadSignalFromDelimitedFile(filename, timeColumnIdx=0, dataColumnIdx=1, delimiter=',', skipHeader=0) -> Signal:
    data = np.genfromtxt(filename, delimiter=delimiter, skip_header=skipHeader)
    columnCount = data.shape[1]
    if columnCount < timeColumnIdx + 1:
        raise ValueError(
            filename + ' has only ' + columnCount + ' columns,  time values can\'t be at column ' + timeColumnIdx)
    if columnCount < dataColumnIdx + 1:
        raise ValueError(
            filename + ' has only ' + columnCount + ' columns,  data values can\'t be at column ' + dataColumnIdx)

    t = data[:, [timeColumnIdx]]
    samples = data[:, [dataColumnIdx]]
    # calculate fs as the interval between the time samples
    fs = int(round(1 / (np.diff(t, n=1, axis=0).mean()), 0))
    source = Signal(samples.ravel(), fs)
    return source

Response: reads a delimited file and converts it into a Signal instance


Instruction:
How would you code a function in Python 3 to
read a wav file into a Signal and scales it to a range of + 1 to - 1

Response:
def loadSignalFromWav(inputSignalFile, calibrationRealWorldValue=None, calibrationSignalFile=None, start=None,
                      end=None) -> Signal:
    """ reads a wav file into a Signal and scales the input so that the sample are expressed in real world values
    (as defined by the calibration signal).
    :param inputSignalFile: a path to the input signal file
    :param calibrationSignalFile: a path the calibration signal file
    :param calibrationRealWorldValue: the real world value represented by the calibration signal
    :param bitDepth: the bit depth of the input signal, used to rescale the value to a range of +1 to -1
    :returns: a Signal
    """
    inputSignal = readWav(inputSignalFile, start=start, end=end)
    if calibrationSignalFile is not None:
        calibrationSignal = readWav(calibrationSignalFile)
        scalingFactor = calibrationRealWorldValue / np.max(calibrationSignal.samples)
        return Signal(inputSignal.samples * scalingFactor, inputSignal.fs)
    else:
        return inputSignal


Instruction:
Can you implement a function in Python 3 that
reads a wav file into a Seq object

Response:
def readWav(inputSignalFile, selectedChannel=1, start=None, end=None) -> Signal:
    """ reads a wav file into a Signal.
    :param inputSignalFile: a path to the input signal file
    :param selectedChannel: the channel to read.
    :param start: the time to start reading from in HH:mm:ss.SSS format.
    :param end: the time to end reading from in HH:mm:ss.SSS format.
    :returns: Signal.
    """

    def asFrames(time, fs):
        hours, minutes, seconds = (time.split(":"))[-3:]
        hours = int(hours)
        minutes = int(minutes)
        seconds = float(seconds)
        millis = int((3600000 * hours) + (60000 * minutes) + (1000 * seconds))
        return int(millis * (fs / 1000))

    import soundfile as sf
    if start is not None or end is not None:
        info = sf.info(inputSignalFile)
        startFrame = 0 if start is None else asFrames(start, info.samplerate)
        endFrame = None if end is None else asFrames(end, info.samplerate)
        ys, frameRate = sf.read(inputSignalFile, start=startFrame, stop=endFrame)
    else:
        ys, frameRate = sf.read(inputSignalFile)
    return Signal(ys[::selectedChannel], frameRate)


Instruction:
How would you explain what the following Python 3 function does
def loadTriAxisSignalFromFile(filename, timeColumnIdx=0, xIdx=1, yIdx=2, zIdx=3, delimiter=',',
                              skipHeader=0) -> TriAxisSignal:
    """
    A factory method for loading a tri axis measurement from a single file.
    :param filename: the file to load from.
    :param timeColumnIdx: the column containing time data.
    :param xIdx: the column containing x axis data.
    :param yIdx: the column containing y axis data.
    :param zIdx: the column containing z axis data.
    :param delimiter: the delimiter.
    :param skipHeader: how many rows of headers to skip.
    :return: the measurement
    """
    return TriAxisSignal(
        x=loadSignalFromDelimitedFile(filename, timeColumnIdx=timeColumnIdx, dataColumnIdx=xIdx,
                                      delimiter=delimiter, skipHeader=skipHeader),
        y=loadSignalFromDelimitedFile(filename, timeColumnIdx=timeColumnIdx, dataColumnIdx=yIdx,
                                      delimiter=delimiter, skipHeader=skipHeader),
        z=loadSignalFromDelimitedFile(filename, timeColumnIdx=timeColumnIdx, dataColumnIdx=zIdx,
                                      delimiter=delimiter, skipHeader=skipHeader))

Response: A factory method for loading a tri axis measurement from a single file.


Instruction:
Can you generate the documentation for the following Python 3 function
def psd(self, ref=None, segmentLengthMultiplier=1, mode=None, **kwargs):

        def analysisFunc(x, nperseg, **kwargs):
            f, Pxx_den = signal.welch(self.samples, self.fs, nperseg=nperseg, detrend=False, **kwargs)
            if ref is not None:
                Pxx_den = librosa.power_to_db(Pxx_den, ref)
            return f, Pxx_den

        if mode == 'cq':
            return self._cq(analysisFunc, segmentLengthMultiplier)
        else:
            return analysisFunc(0, self.getSegmentLength() * segmentLengthMultiplier, **kwargs)

Response: Analyzes the source and returns a PSD.


Instruction:
Make a summary of the following Python 3 code
def spectrum(self, ref=None, segmentLengthMultiplier=1, mode=None, **kwargs):

        def analysisFunc(x, nperseg, **kwargs):
            f, Pxx_spec = signal.welch(self.samples, self.fs, nperseg=nperseg, scaling='spectrum', detrend=False,
                                       **kwargs)
            Pxx_spec = np.sqrt(Pxx_spec)
            # it seems a 3dB adjustment is required to account for the change in nperseg
            if x > 0:
                Pxx_spec = Pxx_spec / (10 ** ((3 * x) / 20))
            if ref is not None:
                Pxx_spec = librosa.amplitude_to_db(Pxx_spec, ref)
            return f, Pxx_spec

        if mode == 'cq':
            return self._cq(analysisFunc, segmentLengthMultiplier)
        else:
            return analysisFunc(0, self.getSegmentLength() * segmentLengthMultiplier, **kwargs)

Response: Analyzes the linear spectrum of the current object.


Instruction:
Here you have a function in Python 3, explain what it does
def peakSpectrum(self, ref=None, segmentLengthMultiplier=1, mode=None, window='hann'):

        def analysisFunc(x, nperseg):
            freqs, _, Pxy = signal.spectrogram(self.samples,
                                               self.fs,
                                               window=window,
                                               nperseg=int(nperseg),
                                               noverlap=int(nperseg // 2),
                                               detrend=False,
                                               scaling='spectrum')
            Pxy_max = np.sqrt(Pxy.max(axis=-1).real)
            if x > 0:
                Pxy_max = Pxy_max / (10 ** ((3 * x) / 20))
            if ref is not None:
                Pxy_max = librosa.amplitude_to_db(Pxy_max, ref=ref)
            return freqs, Pxy_max

        if mode == 'cq':
            return self._cq(analysisFunc, segmentLengthMultiplier)
        else:
            return analysisFunc(0, self.getSegmentLength() * segmentLengthMultiplier)

Response: Analyzes the peak spectrum of the source and returns the max values per bin per segment.


Instruction:
Make a summary of the following Python 3 code
def spectrogram(self, ref=None, segmentLengthMultiplier=1, window='hann'):
        t, f, Sxx = signal.spectrogram(self.samples,
                                       self.fs,
                                       window=window,
                                       nperseg=self.getSegmentLength() * segmentLengthMultiplier,
                                       detrend=False,
                                       scaling='spectrum')
        Sxx = np.sqrt(Sxx)
        if ref is not None:
            Sxx = librosa.amplitude_to_db(Sxx, ref)
        return t, f, Sxx

Response: Analyses the source to generate a spectrogram of the current state of the object.


Instruction:
Implement a Python 3 function for
returning a copy of the current signal with the low pass applied.

Response:
def lowPass(self, *args):
        """
        Creates a copy of the signal with the low pass applied, args specifed are passed through to _butter.
        :return:
        """
        return Signal(self._butter(self.samples, 'low', *args), fs=self.fs)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def highPass(self, *args):
        return Signal(self._butter(self.samples, 'high', *args), fs=self.fs)

Response: Returns a copy of the current signal with the high pass applied.


Instruction:
Write a Python 3 script to
apply a digital butterworth filter via filtfilt at the specified f3 and order.

Response:
def _butter(self, data, btype, f3=2, order=2):
        """
        Applies a digital butterworth filter via filtfilt at the specified f3 and order. Default values are set to
        correspond to apparently sensible filters that distinguish between vibration and tilt from an accelerometer.
        :param data: the data to filter.
        :param btype: high or low.
        :param f3: the f3 of the filter.
        :param order: the filter order.
        :return: the filtered signal.
        """
        b, a = signal.butter(order, f3 / (0.5 * self.fs), btype=btype)
        y = signal.filtfilt(b, a, data)
        return y


Instruction:
Can you generate the documentation for the following Python 3 function
def _getAnalysis(self, axis, analysis, ref=None):
        cache = self.cache.get(str(ref))
        if cache is None:
            cache = {'x': {}, 'y': {}, 'z': {}, 'sum': {}}
            self.cache[str(ref)] = cache
        if axis in cache:
            data = self.cache['raw'].get(axis, None)
            cachedAxis = cache.get(axis)
            if cachedAxis.get(analysis) is None:
                if axis == 'sum':
                    if self._canSum(analysis):
                        fx, Pxx = self._getAnalysis('x', analysis)
                        fy, Pxy = self._getAnalysis('y', analysis)
                        fz, Pxz = self._getAnalysis('z', analysis)
                        # calculate the sum of the squares with an additional weighting for x and y
                        Psum = (((Pxx * 2.2) ** 2) + ((Pxy * 2.4) ** 2) + (Pxz ** 2)) ** 0.5
                        if ref is not None:
                            Psum = librosa.amplitude_to_db(Psum, ref)
                        cachedAxis[analysis] = (fx, Psum)
                    else:
                        return None
                else:
                    cachedAxis[analysis] = getattr(data.highPass(), analysis)(ref=ref)
            return cachedAxis[analysis]
        else:
            return None

Response: get the analysis on the given axis and cache the result


Instruction:
Given the following Python 3 function, write the documentation
def legal_date(year, month, day):
    '''Checks if a given date is a legal positivist date'''
    try:
        assert year >= 1
        assert 0 < month <= 14
        assert 0 < day <= 28
        if month == 14:
            if isleap(year + YEAR_EPOCH - 1):
                assert day <= 2
            else:
                assert day == 1

    except AssertionError:
        raise ValueError("Invalid Positivist date: ({}, {}, {})".format(year, month, day))

    return True

Response: Checks if a given date is a legal positivist date.


Instruction:
Given the following Python 3 function, write the documentation
def to_jd(year, month, day):
    '''Convert a Positivist date to Julian day count.'''
    legal_date(year, month, day)
    gyear = year + YEAR_EPOCH - 1

    return (
        gregorian.EPOCH - 1 + (365 * (gyear - 1)) +
        floor((gyear - 1) / 4) + (-floor((gyear - 1) / 100)) +
        floor((gyear - 1) / 400) + (month - 1) * 28 + day
    )

Response: Convert a Positivist date to Julian day count.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def from_jd(jd):
    '''Convert a Julian day count to Positivist date.'''
    try:
        assert jd >= EPOCH
    except AssertionError:
        raise ValueError('Invalid Julian day')

    depoch = floor(jd - 0.5) + 0.5 - gregorian.EPOCH

    quadricent = floor(depoch / gregorian.INTERCALATION_CYCLE_DAYS)
    dqc = depoch % gregorian.INTERCALATION_CYCLE_DAYS

    cent = floor(dqc / gregorian.LEAP_SUPPRESSION_DAYS)
    dcent = dqc % gregorian.LEAP_SUPPRESSION_DAYS

    quad = floor(dcent / gregorian.LEAP_CYCLE_DAYS)
    dquad = dcent % gregorian.LEAP_CYCLE_DAYS

    yindex = floor(dquad / gregorian.YEAR_DAYS)
    year = (
        quadricent * gregorian.INTERCALATION_CYCLE_YEARS +
        cent * gregorian.LEAP_SUPPRESSION_YEARS +
        quad * gregorian.LEAP_CYCLE_YEARS + yindex
    )

    if yindex == 4:
        yearday = 365
        year = year - 1

    else:
        yearday = (
            depoch -
            quadricent * gregorian.INTERCALATION_CYCLE_DAYS -
            cent * gregorian.LEAP_SUPPRESSION_DAYS -
            quad * gregorian.LEAP_CYCLE_DAYS -
            yindex * gregorian.YEAR_DAYS
        )

    month = floor(yearday / 28)

    return (year - YEAR_EPOCH + 2, month + 1, int(yearday - (month * 28)) + 1)

Response: Convert a Julian day count to Positivist date.


Instruction:
Can you write a function in Python 3 where it
returns the name of the month and day for a given date.

Response:
def dayname(year, month, day):
    '''
    Give the name of the month and day for a given date.

    Returns:
        tuple month_name, day_name
    '''
    legal_date(year, month, day)

    yearday = (month - 1) * 28 + day

    if isleap(year + YEAR_EPOCH - 1):
        dname = data.day_names_leap[yearday - 1]
    else:
        dname = data.day_names[yearday - 1]

    return MONTHS[month - 1], dname


Instruction:
Create a Python 3 function to
return True if the lastUpdateTime is more than maxAge seconds ago.

Response:
def hasExpired(self):
        """
        :return: true if the lastUpdateTime is more than maxAge seconds ago.
        """
        return (datetime.datetime.utcnow() - self.lastUpdateTime).total_seconds() > self.maxAgeSeconds


Instruction:
How would you implement a function in Python 3 that
adds the named device to the store.

Response:
def accept(self, deviceId, device):
        """
        Adds the named device to the store.
        :param deviceId:
        :param device:
        :return:
        """
        storedDevice = self.devices.get(deviceId)
        if storedDevice is None:
            logger.info('Initialising device ' + deviceId)
            storedDevice = Device(self.maxAgeSeconds)
            storedDevice.deviceId = deviceId
            # this uses an async handler to decouple the recorder put (of the data) from the analyser handling that data
            # thus the recorder will become free as soon as it has handed off the data. This means delivery is only
            # guaranteed as long as the analyser stays up but this is not a system that sits on top of a bulletproof
            # message bus so unlucky :P
            storedDevice.dataHandler = AsyncHandler('analyser', CSVLogger('analyser', deviceId, self.dataDir))
        else:
            logger.debug('Pinged by device ' + deviceId)
        storedDevice.payload = device
        storedDevice.lastUpdateTime = datetime.datetime.utcnow()
        # TODO if device has FAILED, do something?
        self.devices.update({deviceId: storedDevice})
        self.targetStateController.updateDeviceState(storedDevice.payload)


Instruction:
Implement a Python 3 function for
returning a list of the devices in the given state.

Response:
def getDevices(self, status=None):
        """
        The devices in the given state or all devices is the arg is none.
        :param status: the state to match against.
        :return: the devices
        """
        return [d for d in self.devices.values() if status is None or d.payload.get('status') == status]


Instruction:
Make a summary of the following Python 3 code
def getDevice(self, id):
        return next(iter([d for d in self.devices.values() if d.deviceId == id]), None)

Response: get the named device.


Instruction:
Can you write a function in Python 3 where it
schedules the requested measurement session with all INITIALISED devices.

Response:
def scheduleMeasurement(self, measurementId, duration, start):
        """
        Schedules the requested measurement session with all INITIALISED devices.
        :param measurementId:
        :param duration:
        :param start:
        :return: a dict of device vs status.
        """
        # TODO subtract 1s from start and format
        results = {}
        for device in self.getDevices(RecordingDeviceStatus.INITIALISED.name):
            logger.info('Sending measurement ' + measurementId + ' to ' + device.payload['serviceURL'])
            try:
                resp = self.httpclient.put(device.payload['serviceURL'] + '/measurements/' + measurementId,
                                           json={'duration': duration, 'at': start.strftime(DATETIME_FORMAT)})
                logger.info('Response for ' + measurementId + ' from ' + device.payload['serviceURL'] + ' is ' +
                            str(resp.status_code))
                results[device] = resp.status_code
            except Exception as e:
                logger.exception(e)
                results[device] = 500
        return results


Instruction:
Explain what the following Python 3 code does
def patch(self):
        # TODO block until all devices have updated?
        json = request.get_json()
        logger.info("Updating target state with " + str(json))
        self._targetStateController.updateTargetState(json)
        return None, 200

Response: Updates the target state with the current state of the target.


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

    if name_list and name_list[0] == '@':
        value = name_list[1:]
        if not os.path.exists(value):
            log.warning('The file %s does not exist' % value)
            return
        try:
            return [v.strip() for v in open(value, 'r').readlines()]
        except IOError as e:
            log.warning('reading %s failed: %s; ignoring this file' %
                        (value, e))
    else:
        return [v.strip() for v in name_list.split(',')]

Response: Parse a comma - separated list of values or a filename starting with @


Instruction:
Can you tell what is the following Python 3 function doing
def _mmInit(self):
        # cache references to speed up loop a bit
        mmkeys = {}
        mmkeysGet = mmkeys.setdefault
        minkeylength = self.minkeylength
        for key in self.data.keys():
            # add abbreviations as short as minkeylength
            # always add at least one entry (even for key="")
            lenkey = len(key)
            start = min(minkeylength,lenkey)
            for i in range(start,lenkey+1):
                mmkeysGet(key[0:i],[]).append(key)
        self.mmkeys = mmkeys

Response: Create the minimum match dictionary of keys


Instruction:
Can you generate a brief explanation for the following Python 3 code
def resolve(self, key, keylist):
        raise AmbiguousKeyError("Ambiguous key "+ repr(key) +
                ", could be any of " + str(sorted(keylist)))

Response: Hook to resolve ambiguities in selected keys


Instruction:
Make a summary of the following Python 3 code
def add(self, key, item):
        mmkeys = self.mmkeys
        if mmkeys is not None and not (key in self.data):
            # add abbreviations as short as minkeylength
            # always add at least one entry (even for key="")
            lenkey = len(key)
            start = min(self.minkeylength,lenkey)
            # cache references to speed up loop a bit
            mmkeysGet = mmkeys.setdefault
            for i in range(start,lenkey+1):
                mmkeysGet(key[0:i],[]).append(key)
        self.data[key] = item

Response: Add a new key - item pair to the dictionary.


Instruction:
How would you explain what the following Python 3 function does
def get(self, key, failobj=None, exact=0):
        if not exact:
            key = self.getfullkey(key,new=1)
        return self.data.get(key,failobj)

Response: Returns the value of the object with the given key.


Instruction:
Make a summary of the following Python 3 code
def _has(self, key, exact=0):
        if not exact:
            key = self.getfullkey(key,new=1)
        return key in self.data

Response: Returns True if the key is in the cache False otherwise.


Instruction:
Implement a Python 3 function for
returning a list of all the matching values for key and containing a single entry for unambiguous matches and multiple entries for ambiguous matches and multiple entries for ambiguous matches.

Response:
def getall(self, key, failobj=None):
        """Returns a list of all the matching values for key,
        containing a single entry for unambiguous matches and
        multiple entries for ambiguous matches."""
        if self.mmkeys is None: self._mmInit()
        k = self.mmkeys.get(key)
        if not k: return failobj
        return list(map(self.data.get, k))


Instruction:
Implement a function in Python 3 to
return a list of the full key names for all the matching values for key.

Response:
def getallkeys(self, key, failobj=None):
        """Returns a list of the full key names (not the items)
        for all the matching values for key.  The list will
        contain a single entry for unambiguous matches and
        multiple entries for ambiguous matches."""
        if self.mmkeys is None: self._mmInit()
        return self.mmkeys.get(key, failobj)


Instruction:
Write a Python 3 script to
return a single entry from the cache if the key is not found or is ambiguous

Response:
def get(self, key, failobj=None, exact=0):

        """Returns failobj if key is not found or is ambiguous"""

        if not exact:
            try:
                key = self.getfullkey(key)
            except KeyError:
                return failobj
        return self.data.get(key,failobj)


Instruction:
Create a Python 3 function to
return true if the key is found in the data.

Response:
def _has(self, key, exact=0):

        """Returns false if key is not found or is ambiguous"""

        if not exact:
            try:
                key = self.getfullkey(key)
                return 1
            except KeyError:
                return 0
        else:
            return key in self.data


Instruction:
Write a Python 3 function for
returning true if this parameter is learned by the user.

Response:
def isLearned(self, mode=None):
        """Return true if this parameter is learned

        Hidden parameters are not learned; automatic parameters inherit
        behavior from package/cl; other parameters are learned.
        If mode is set, it determines how automatic parameters behave.
        If not set, cl.mode parameter determines behavior.
        """
        if "l" in self.mode: return 1
        if "h" in self.mode: return 0
        if "a" in self.mode:
            if mode is None: mode = 'ql' # that is, iraf.cl.mode
            if "h" in mode and "l" not in mode:
                return 0
        return 1


Instruction:
Here you have a function in Python 3, explain what it does
def get(self, field=None, index=None, lpar=0, prompt=1, native=0, mode="h"):

        if field and field != "p_value":
            # note p_value comes back to this routine, so shortcut that case
            return self._getField(field,native=native,prompt=prompt)

        # may prompt for value if prompt flag is set
        if prompt: self._optionalPrompt(mode)

        if index is not None:
            raise SyntaxError("Parameter "+self.name+" is not an array")

        if native:
            rv = self.value
        else:
            rv = self.toString(self.value)
        return rv

Response: Return value of this parameter as a string or in native format.


Instruction:
Make a summary of the following Python 3 code
def set(self, value, field=None, index=None, check=1):

        if index is not None:
            raise SyntaxError("Parameter "+self.name+" is not an array")

        if field:
            self._setField(value,field,check=check)
        else:
            if check:
                self.value = self.checkValue(value)
            else:
                self.value = self._coerceValue(value)
            self.setChanged()

Response: Set value of this parameter from a string or other value.


Instruction:
Write a Python 3 script for
checking and converts a parameter value. Returns an exception if the value is not permitted for this parameter.

Response:
def checkValue(self,value,strict=0):
        """Check and convert a parameter value.

        Raises an exception if the value is not permitted for this
        parameter.  Otherwise returns the value (converted to the
        right type.)
        """
        v = self._coerceValue(value,strict)
        return self.checkOneValue(v,strict)


Instruction:
Explain what the following Python 3 code does
def checkOneValue(self,v,strict=0):
        if v in [None, INDEF] or (isinstance(v,str) and v[:1] == ")"):
            return v
        elif v == "":
            # most parameters treat null string as omitted value
            return None
        elif self.choice is not None and v not in self.choiceDict:
            schoice = list(map(self.toString, self.choice))
            schoice = "|".join(schoice)
            raise ValueError("Parameter %s: "
                    "value %s is not in choice list (%s)" %
                    (self.name, str(v), schoice))
        elif (self.min not in [None, INDEF] and v<self.min):
            raise ValueError("Parameter %s: "
                    "value `%s' is less than minimum `%s'" %
                    (self.name, str(v), str(self.min)))
        elif (self.max not in [None, INDEF] and v>self.max):
            raise ValueError("Parameter %s: "
                    "value `%s' is greater than maximum `%s'" %
                    (self.name, str(v), str(self.max)))
        return v

Response: Checks a single value to see if it is in range or choice list.


Instruction:
Make a summary of the following Python 3 code
def dpar(self, cl=1):
        sval = self.toString(self.value, quoted=1)
        if not cl:
            if sval == "": sval = "None"
        s = "%s = %s" % (self.name, sval)
        return s

Response: Return a dpar - style executable assignment for the current parameter.


Instruction:
Can you tell what is the following Python 3 function doing
def pretty(self,verbose=0):
        # split prompt lines and add blanks in later lines to align them
        plines = self.prompt.split('\n')
        for i in range(len(plines)-1): plines[i+1] = 32*' ' + plines[i+1]
        plines = '\n'.join(plines)
        namelen = min(len(self.name), 12)
        pvalue = self.get(prompt=0,lpar=1)
        alwaysquoted = ['s', 'f', '*gcur', '*imcur', '*ukey', 'pset']
        if self.type in alwaysquoted and self.value is not None: pvalue = '"' + pvalue + '"'
        if self.mode == "h":
            s = "%13s = %-15s %s" % ("("+self.name[:namelen],
                                    pvalue+")", plines)
        else:
            s = "%13s = %-15s %s" % (self.name[:namelen],
                                    pvalue, plines)
        if not verbose: return s

        if self.choice is not None:
            s = s + "\n" + 32*" " + "|"
            nline = 33
            for i in range(len(self.choice)):
                sch = str(self.choice[i]) + "|"
                s = s + sch
                nline = nline + len(sch) + 1
                if nline > 80:
                    s = s + "\n" + 32*" " + "|"
                    nline = 33
        elif self.min not in [None, INDEF] or self.max not in [None, INDEF]:
            s = s + "\n" + 32*" "
            if self.min not in [None, INDEF]:
                s = s + str(self.min) + " <= "
            s = s + self.name
            if self.max not in [None, INDEF]:
                s = s + " <= " + str(self.max)
        return s

Response: Return pretty list description of parameter


Instruction:
Write a Python 3 script for
returning par format string for this parameter.

Response:
def save(self, dolist=0):
        """Return .par format string for this parameter

        If dolist is set, returns fields as a list of strings.  Default
        is to return a single string appropriate for writing to a file.
        """
        quoted = not dolist
        fields = 7*[""]
        fields[0] = self.name
        fields[1] = self.type
        fields[2] = self.mode
        fields[3] = self.toString(self.value,quoted=quoted)
        if self.choice is not None:
            schoice = list(map(self.toString, self.choice))
            schoice.insert(0,'')
            schoice.append('')
            fields[4] = repr('|'.join(schoice))
        elif self.min not in [None,INDEF]:
            fields[4] = self.toString(self.min,quoted=quoted)
        if self.max not in [None,INDEF]:
            fields[5] = self.toString(self.max,quoted=quoted)
        if self.prompt:
            if quoted:
                sprompt = repr(self.prompt)
            else:
                sprompt = self.prompt
            # prompt can have embedded newlines (which are printed)
            sprompt = sprompt.replace(r'\012', '\n')
            sprompt = sprompt.replace(r'\n', '\n')
            fields[6] = sprompt
        # delete trailing null parameters
        for i in [6,5,4]:
            if fields[i] != "": break
            del fields[i]
        if dolist:
            return fields
        else:
            return ','.join(fields)


Instruction:
Explain what the following Python 3 code does
def _setChoice(self,s,strict=0):
        clist = _getChoice(s,strict)
        self.choice = list(map(self._coerceValue, clist))
        self._setChoiceDict()

Response: Set the choice parameter from string s


Instruction:
Here you have a function in Python 3, explain what it does
def _setChoiceDict(self):
        # value is name of choice parameter (same as key)
        self.choiceDict = {}
        for c in self.choice: self.choiceDict[c] = c

Response: Create dictionary for choice list


Instruction:
How would you implement a function in Python 3 that
gets the p_filename field for this parameter

Response:
def _getPFilename(self,native,prompt):
        """Get p_filename field for this parameter

        Same as get for non-list params
        """
        return self.get(native=native,prompt=prompt)


Instruction:
How would you code a function in Python 3 to
get a parameter field value

Response:
def _getField(self, field, native=0, prompt=1):
        """Get a parameter field value"""
        try:
            # expand field name using minimum match
            field = _getFieldDict[field]
        except KeyError as e:
            # re-raise the exception with a bit more info
            raise SyntaxError("Cannot get field " + field +
                    " for parameter " + self.name + "\n" + str(e))
        if field == "p_value":
            # return value of parameter
            # Note that IRAF returns the filename for list parameters
            # when p_value is used.  I consider this a bug, and it does
            # not appear to be used by any cl scripts or SPP programs
            # in either IRAF or STSDAS.  It is also in conflict with
            # the IRAF help documentation.  I am making p_value exactly
            # the same as just a simple CL parameter reference.
            return self.get(native=native,prompt=prompt)
        elif field == "p_name": return self.name
        elif field == "p_xtype": return self.type
        elif field == "p_type": return self._getPType()
        elif field == "p_mode": return self.mode
        elif field == "p_prompt": return self.prompt
        elif field == "p_scope": return self.scope
        elif field == "p_default" or field == "p_filename":
            # these all appear to be equivalent -- they just return the
            # current PFilename of the parameter (which is the same as the value
            # for non-list parameters, and is the filename for list parameters)
            return self._getPFilename(native,prompt)
        elif field == "p_maximum":
            if native:
                return self.max
            else:
                return self.toString(self.max)
        elif field == "p_minimum":
            if self.choice is not None:
                if native:
                    return self.choice
                else:
                    schoice = list(map(self.toString, self.choice))
                    return "|" + "|".join(schoice) + "|"
            else:
                if native:
                    return self.min
                else:
                    return self.toString(self.min)
        else:
            # XXX unimplemented fields:
            # p_length: maximum string length in bytes -- what to do with it?
            raise RuntimeError("Program bug in IrafPar._getField()\n" +
                    "Requested field " + field + " for parameter " + self.name)


Instruction:
Explain what the following Python 3 code does
def _setField(self, value, field, check=1):
        try:
            # expand field name using minimum match
            field = _setFieldDict[field]
        except KeyError as e:
            raise SyntaxError("Cannot set field " + field +
                    " for parameter " + self.name + "\n" + str(e))
        if field == "p_prompt":
            self.prompt = irafutils.removeEscapes(irafutils.stripQuotes(value))
        elif field == "p_value":
            self.set(value,check=check)
        elif field == "p_filename":
            # this is only relevant for list parameters (*imcur, *gcur, etc.)
            self.set(value,check=check)
        elif field == "p_scope":
            self.scope = value
        elif field == "p_maximum":
            self.max = self._coerceOneValue(value)
        elif field == "p_minimum":
            if isinstance(value,str) and '|' in value:
                self._setChoice(irafutils.stripQuotes(value))
            else:
                self.min = self._coerceOneValue(value)
        elif field == "p_mode":
            # not doing any type or value checking here -- setting mode is
            # rare, so assume that it is being done correctly
            self.mode = irafutils.stripQuotes(value)
        else:
            raise RuntimeError("Program bug in IrafPar._setField()" +
                    "Requested field " + field + " for parameter " + self.name)

Response: Set a parameter field value


Instruction:
Can you create a Python 3 function that
returns par format string for this parameter.

Response:
def save(self, dolist=0):
        """Return .par format string for this parameter

        If dolist is set, returns fields as a list of strings.  Default
        is to return a single string appropriate for writing to a file.
        """
        quoted = not dolist
        array_size = 1
        for d in self.shape:
            array_size = d*array_size
        ndim = len(self.shape)
        fields = (7+2*ndim+len(self.value))*[""]
        fields[0] = self.name
        fields[1] = self.type
        fields[2] = self.mode
        fields[3] = str(ndim)
        next = 4
        for d in self.shape:
            fields[next] = str(d); next += 1
            fields[next] = '1';    next += 1
        nvstart = 7+2*ndim
        if self.choice is not None:
            schoice = list(map(self.toString, self.choice))
            schoice.insert(0,'')
            schoice.append('')
            fields[nvstart-3] = repr('|'.join(schoice))
        elif self.min not in [None,INDEF]:
            fields[nvstart-3] = self.toString(self.min,quoted=quoted)
        # insert an escaped line break before min field
        if quoted:
            fields[nvstart-3] = '\\\n' + fields[nvstart-3]
        if self.max not in [None,INDEF]:
            fields[nvstart-2] = self.toString(self.max,quoted=quoted)
        if self.prompt:
            if quoted:
                sprompt = repr(self.prompt)
            else:
                sprompt = self.prompt
            # prompt can have embedded newlines (which are printed)
            sprompt = sprompt.replace(r'\012', '\n')
            sprompt = sprompt.replace(r'\n', '\n')
            fields[nvstart-1] = sprompt
        for i in range(len(self.value)):
            fields[nvstart+i] = self.toString(self.value[i],quoted=quoted)
        # insert an escaped line break before value fields
        if dolist:
            return fields
        else:
            fields[nvstart] = '\\\n' + fields[nvstart]
            return ','.join(fields)


Instruction:
Given the following Python 3 function, write the documentation
def dpar(self, cl=1):
        sval = list(map(self.toString, self.value, len(self.value)*[1]))
        for i in range(len(sval)):
            if sval[i] == "":
                sval[i] = "None"
        s = "%s = [%s]" % (self.name, ', '.join(sval))
        return s

Response: Return dpar - style executable assignment for the current parameter.


Instruction:
How would you code a function in Python 3 to
return value of this parameter as a string or in native format.

Response:
def get(self, field=None, index=None, lpar=0, prompt=1, native=0, mode="h"):
        """Return value of this parameter as a string (or in native format
        if native is non-zero.)"""

        if field: return self._getField(field,native=native,prompt=prompt)

        # may prompt for value if prompt flag is set
        #XXX should change _optionalPrompt so we prompt for each element of
        #XXX the array separately?  I think array parameters are
        #XXX not useful as non-hidden params.

        if prompt: self._optionalPrompt(mode)

        if index is not None:
            sumindex = self._sumindex(index)
            try:
                if native:
                    return self.value[sumindex]
                else:
                    return self.toString(self.value[sumindex])
            except IndexError:
                # should never happen
                raise SyntaxError("Illegal index [" + repr(sumindex) +
                        "] for array parameter " + self.name)
        elif native:
            # return object itself for an array because it is
            # indexable, can have values assigned, etc.
            return self
        else:
            # return blank-separated string of values for array
            return str(self)


Instruction:
How would you code a function in Python 3 to
set value of this parameter from a string or other value.

Response:
def set(self, value, field=None, index=None, check=1):
        """Set value of this parameter from a string or other value.
        Field is optional parameter field (p_prompt, p_minimum, etc.)
        Index is optional array index (zero-based).  Set check=0 to
        assign the value without checking to see if it is within
        the min-max range or in the choice list."""
        if index is not None:
            sumindex = self._sumindex(index)
            try:
                value = self._coerceOneValue(value)
                if check:
                    self.value[sumindex] = self.checkOneValue(value)
                else:
                    self.value[sumindex] = value
                return
            except IndexError:
                # should never happen
                raise SyntaxError("Illegal index [" + repr(sumindex) +
                        "] for array parameter " + self.name)
        if field:
            self._setField(value,field,check=check)
        else:
            if check:
                self.value = self.checkValue(value)
            else:
                self.value = self._coerceValue(value)
            self.setChanged()


Instruction:
Create a Python 3 function to
check and convert a parameter value.

Response:
def checkValue(self,value,strict=0):
        """Check and convert a parameter value.

        Raises an exception if the value is not permitted for this
        parameter.  Otherwise returns the value (converted to the
        right type.)
        """
        v = self._coerceValue(value,strict)
        for i in range(len(v)):
            self.checkOneValue(v[i],strict=strict)
        return v


Instruction:
Can you generate the documentation for the following Python 3 function
def _sumindex(self, index=None):
        try:
            ndim = len(index)
        except TypeError:
            # turn index into a 1-tuple
            index = (index,)
            ndim = 1
        if len(self.shape) != ndim:
            raise ValueError("Index to %d-dimensional array %s has too %s dimensions" %
                (len(self.shape), self.name, ["many","few"][len(self.shape) > ndim]))
        sumindex = 0
        for i in range(ndim-1,-1,-1):
            index1 = index[i]
            if index1 < 0 or index1 >= self.shape[i]:
                raise ValueError("Dimension %d index for array %s is out of bounds (value=%d)" %
                    (i+1, self.name, index1))
            sumindex = index1 + sumindex*self.shape[i]
        return sumindex

Response: Convert tuple index to 1 - D index into value


Instruction:
Write a Python 3 script to
coerce parameter to appropriate type.

Response:
def _coerceValue(self,value,strict=0):
        """Coerce parameter to appropriate type

        Should accept None or null string.  Must be an array.
        """
        try:
            if isinstance(value,str):
                # allow single blank-separated string as input
                value = value.split()
            if len(value) != len(self.value):
                raise IndexError
            v = len(self.value)*[0]
            for i in range(len(v)):
                v[i] = self._coerceOneValue(value[i],strict)
            return v
        except (IndexError, TypeError):
            raise ValueError("Value must be a " + repr(len(self.value)) +
                    "-element array for " + self.name)


Instruction:
How would you explain what the following Python 3 function does
def _setChoiceDict(self):
        # value is full name of choice parameter
        self.choiceDict = minmatch.MinMatchDict()
        for c in self.choice: self.choiceDict.add(c, c)

Response: Create min - match dictionary for choice list


Instruction:
How would you implement a function in Python 3 that
checks initial attributes to make sure they are legal

Response:
def _checkAttribs(self, strict):
        """Check initial attributes to make sure they are legal"""
        if self.min:
            warning("Minimum value not allowed for boolean-type parameter " +
                    self.name, strict)
            self.min = None
        if self.max:
            if not self.prompt:
                warning("Maximum value not allowed for boolean-type parameter " +
                                self.name + " (probably missing comma)",
                                strict)
                # try to recover by assuming max string is prompt
                self.prompt = self.max
            else:
                warning("Maximum value not allowed for boolean-type parameter " +
                        self.name, strict)
            self.max = None
        if self.choice:
            warning("Choice values not allowed for boolean-type parameter " +
                    self.name, strict)
            self.choice = None


Instruction:
Can you create a Python 3 function that
checks initial attributes to make sure they are legal

Response:
def _checkAttribs(self, strict):
        """Check initial attributes to make sure they are legal"""
        if self.choice:
            warning("Choice values not allowed for real-type parameter " +
                    self.name, strict)
            self.choice = None


Instruction:
Create a Python 3 function to
update the device with the given data.

Response:
def patch(self, deviceId):
        """
        Updates the device with the given data. Supports a json payload like
        {
            fs: newFs
            samplesPerBatch: samplesPerBatch
            gyroEnabled: true
            gyroSensitivity: 500
            accelerometerEnabled: true
            accelerometerSensitivity: 2
        }
        A heartbeat is sent on completion of the request to ensure the analyser gets a rapid update.
        :return: the device and 200 if the update was ok, 400 if not.
        """
        try:
            device = self.recordingDevices.get(deviceId)
            if device.status == RecordingDeviceStatus.INITIALISED:
                errors = self._handlePatch(device)
                if len(errors) == 0:
                    return device, 200
                else:
                    return device, 500
            else:
                return device, 400
        finally:
            logger.info("Sending adhoc heartbeat on device state update")
            self.heartbeater.sendHeartbeat()


Instruction:
Implement a Python 3 function for
checking if this is a legal date in the Gregorian calendar

Response:
def legal_date(year, month, day):
    '''Check if this is a legal date in the Gregorian calendar'''
    if month == 2:
        daysinmonth = 29 if isleap(year) else 28
    else:
        daysinmonth = 30 if month in HAVE_30_DAYS else 31

    if not (0 < day <= daysinmonth):
        raise ValueError("Month {} doesn't have a day {}".format(month, day))

    return True


Instruction:
Make a summary of the following Python 3 code
def from_jd(jd):
    '''Return Gregorian date in a (Y, M, D) tuple'''
    wjd = floor(jd - 0.5) + 0.5
    depoch = wjd - EPOCH

    quadricent = floor(depoch / INTERCALATION_CYCLE_DAYS)
    dqc = depoch % INTERCALATION_CYCLE_DAYS

    cent = floor(dqc / LEAP_SUPPRESSION_DAYS)
    dcent = dqc % LEAP_SUPPRESSION_DAYS

    quad = floor(dcent / LEAP_CYCLE_DAYS)
    dquad = dcent % LEAP_CYCLE_DAYS

    yindex = floor(dquad / YEAR_DAYS)
    year = (
        quadricent * INTERCALATION_CYCLE_YEARS +
        cent * LEAP_SUPPRESSION_YEARS +
        quad * LEAP_CYCLE_YEARS + yindex
    )

    if not (cent == 4 or yindex == 4):
        year += 1

    yearday = wjd - to_jd(year, 1, 1)

    leap = isleap(year)

    if yearday < 58 + leap:
        leap_adj = 0
    elif leap:
        leap_adj = 1
    else:
        leap_adj = 2

    month = floor((((yearday + leap_adj) * 12) + 373) / 367)
    day = int(wjd - to_jd(year, month, 1)) + 1

    return (year, month, day)

Response: Return Gregorian date in a ( Y M D ) tuple


Instruction:
Write a Python 3 script for
storing a new item in the cache if it is allowed in the hinge points. Returns True if it is stored False otherwise.

Response:
def storeFromHinge(self, name, hingePoints):
        """
        Stores a new item in the cache if it is allowed in.
        :param name: the name.
        :param hingePoints: the hinge points.
        :return: true if it is stored.
        """
        if name not in self._cache:
            if self._valid(hingePoints):
                self._cache[name] = {'name': name, 'type': 'hinge', 'hinge': hingePoints}
                self.writeCache()
                return True
        return False


Instruction:
How would you explain what the following Python 3 function does
def storeFromWav(self, uploadCacheEntry, start, end):
        prefix = uploadCacheEntry['name'] + '_' + start + '_' + end
        match = next((x for x in self._cache.values() if x['type'] == 'wav' and x['name'].startswith(prefix)), None)
        if match is None:
            cached = [
                {
                    'name': prefix + '_' + n,
                    'analysis': n,
                    'start': start,
                    'end': end,
                    'type': 'wav',
                    'filename': uploadCacheEntry['name']
                } for n in ['spectrum', 'peakSpectrum']
            ]
            for cache in cached:
                self._cache[cache['name']] = cache
            self.writeCache()
            return True
        return False

Response: Stores a new item in the cache.


Instruction:
Can you implement a function in Python 3 that
deletes the named entry in the cache.

Response:
def delete(self, name):
        """
        Deletes the named entry in the cache.
        :param name: the name.
        :return: true if it is deleted.
        """
        if name in self._cache:
            del self._cache[name]
            self.writeCache()
            # TODO clean files
            return True
        return False


Instruction:
Can you generate a brief explanation for the following Python 3 code
def analyse(self, name):
        if name in self._cache:
            target = self._cache[name]
            if target['type'] == 'wav':
                signal = self._uploadController.loadSignal(target['filename'],
                                                           start=target['start'] if target['start'] != 'start' else None,
                                                           end=target['end'] if target['end'] != 'end' else None)
                if signal is not None:
                    # TODO allow user defined window
                    return getattr(signal, target['analysis'])(ref=1.0)
                else:
                    return None, 404
                pass
            elif target['type'] == 'hinge':
                hingePoints = np.array(target['hinge']).astype(np.float64)
                x = hingePoints[:, 1]
                y = hingePoints[:, 0]
                # extend as straight line from 0 to 500
                if x[0] != 0:
                    x = np.insert(x, 0, 0.0000001)
                    y = np.insert(y, 0, y[0])
                if x[-1] != 500:
                    x = np.insert(x, len(x), 500.0)
                    y = np.insert(y, len(y), y[-1])
                # convert the y axis dB values into a linear value
                y = 10 ** (y / 10)
                # perform a logspace interpolation
                f = self.log_interp1d(x, y)
                # remap to 0-500
                xnew = np.linspace(x[0], x[-1], num=500, endpoint=False)
                # and convert back to dB
                return xnew, 10 * np.log10(f(xnew))
            else:
                logger.error('Unknown target type with name ' + name)
        return None

Response: This function reads the specified file and returns the frequency and Pxx analysis of the file.


Instruction:
Can you write a function in Python 3 where it
performs a log space 1d interpolation.

Response:
def log_interp1d(self, xx, yy, kind='linear'):
        """
        Performs a log space 1d interpolation.
        :param xx: the x values.
        :param yy: the y values.
        :param kind: the type of interpolation to apply (as per scipy interp1d)
        :return: the interpolation function.
        """
        logx = np.log10(xx)
        logy = np.log10(yy)
        lin_interp = interp1d(logx, logy, kind=kind)
        log_interp = lambda zz: np.power(10.0, lin_interp(np.log10(zz)))
        return log_interp


Instruction:
Write a Python 3 script to
retrieve the Julian date equivalent for this date

Response:
def to_jd(year, month, day):
    "Retrieve the Julian date equivalent for this date"
    return day + (month - 1) * 30 + (year - 1) * 365 + floor(year / 4) + EPOCH - 1


Instruction:
Can you generate the documentation for the following Python 3 function
def from_jd(jdc):
    "Create a new date from a Julian date."
    cdc = floor(jdc) + 0.5 - EPOCH
    year = floor((cdc - floor((cdc + 366) / 1461)) / 365) + 1

    yday = jdc - to_jd(year, 1, 1)

    month = floor(yday / 30) + 1
    day = yday - (month - 1) * 30 + 1
    return year, month, day

Response: Create a new date from a Julian date.


Instruction:
Create a Python 3 function to
compute the roll angle at the target position based on the Colin Cox algorithm.

Response:
def troll(roll, dec, v2, v3):
    """ Computes the roll angle at the target position based on::

            the roll angle at the V1 axis(roll),
            the dec of the target(dec), and
            the V2/V3 position of the aperture (v2,v3) in arcseconds.

        Based on the algorithm provided by Colin Cox that is used in
        Generic Conversion at STScI.
    """
    # Convert all angles to radians
    _roll = DEGTORAD(roll)
    _dec = DEGTORAD(dec)
    _v2 = DEGTORAD(v2 / 3600.)
    _v3 = DEGTORAD(v3 / 3600.)

    # compute components
    sin_rho = sqrt((pow(sin(_v2),2)+pow(sin(_v3),2)) - (pow(sin(_v2),2)*pow(sin(_v3),2)))
    rho = asin(sin_rho)
    beta = asin(sin(_v3)/sin_rho)
    if _v2 < 0: beta = pi - beta
    gamma = asin(sin(_v2)/sin_rho)
    if _v3 < 0: gamma = pi - gamma
    A = pi/2. + _roll - beta
    B = atan2( sin(A)*cos(_dec), (sin(_dec)*sin_rho - cos(_dec)*cos(rho)*cos(A)))

    # compute final value
    troll = RADTODEG(pi - (gamma+B))

    return troll


Instruction:
Can you generate a brief explanation for the following Python 3 code
def print_archive(self,format=True):
        if len(list(self.orig_wcs.keys())) > 0:
            block  = 'Original WCS keywords for ' + self.rootname+ '\n'
            block += '    backed up on '+repr(self.orig_wcs['WCSCDATE'])+'\n'
            if not format:
                for key in self.wcstrans.keys():
                    block += key.upper() + " = " + repr(self.get_archivekw(key)) + '\n'
                block = 'PA_V3: '+repr(self.pa_obs)+'\n'

            else:
                block += 'CD_11  CD_12: '+repr(self.get_archivekw('CD1_1'))+'  '+repr(self.get_archivekw('CD1_2')) +'\n'
                block += 'CD_21  CD_22: '+repr(self.get_archivekw('CD2_1'))+'  '+repr(self.get_archivekw('CD2_2')) +'\n'
                block += 'CRVAL       : '+repr(self.get_archivekw('CRVAL1'))+'  '+repr(self.get_archivekw('CRVAL2')) + '\n'
                block += 'CRPIX       : '+repr(self.get_archivekw('CRPIX1'))+'  '+repr(self.get_archivekw('CRPIX2')) + '\n'
                block += 'NAXIS       : '+repr(int(self.get_archivekw('NAXIS1')))+'  '+repr(int(self.get_archivekw('NAXIS2'))) + '\n'
                block += 'Plate Scale : '+repr(self.get_archivekw('pixel scale'))+'\n'
                block += 'ORIENTAT    : '+repr(self.get_archivekw('ORIENTAT'))+'\n'

            print(block)

Response: Prints out the archived WCS keywords.


Instruction:
Can you generate the documentation for the following Python 3 function
def set_pscale(self):
        if self.new:
            self.pscale = 1.0
        else:
            self.pscale = self.compute_pscale(self.cd11,self.cd21)

Response: Compute the pixel scale based on active WCS values.


Instruction:
Make a summary of the following Python 3 code
def compute_pscale(self,cd11,cd21):
        return N.sqrt(N.power(cd11,2)+N.power(cd21,2)) * 3600.

Response: Compute the pixel scale based on active WCS values.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def set_orient(self):
        self.orient = RADTODEG(N.arctan2(self.cd12,self.cd22))

Response: Return the computed orientation based on CD matrix.


Instruction:
Implement a Python 3 function for
updating the WCS of a specific entry in the WCS.

Response:
def updateWCS(self, pixel_scale=None, orient=None,refpos=None,refval=None,size=None):
        """
        Create a new CD Matrix from the absolute pixel scale
        and reference image orientation.
        """
        # Set up parameters necessary for updating WCS
        # Check to see if new value is provided,
        # If not, fall back on old value as the default

        _updateCD = no
        if orient is not None and orient != self.orient:
            pa = DEGTORAD(orient)
            self.orient = orient
            self._orient_lin = orient
            _updateCD = yes
        else:
            # In case only pixel_scale was specified
            pa = DEGTORAD(self.orient)

        if pixel_scale is not None and pixel_scale != self.pscale:
            _ratio = pixel_scale / self.pscale
            self.pscale = pixel_scale
            _updateCD = yes
        else:
            # In case, only orient was specified
            pixel_scale = self.pscale
            _ratio = None

        # If a new plate scale was given,
        # the default size should be revised accordingly
        # along with the default reference pixel position.
        # Added 31 Mar 03, WJH.
        if _ratio is not None:
            self.naxis1 /= _ratio
            self.naxis2 /= _ratio
            self.crpix1 = self.naxis1/2.
            self.crpix2 = self.naxis2/2.

        # However, if the user provides a given size,
        # set it to use that no matter what.
        if size is not None:
            self.naxis1 = size[0]
            self.naxis2 = size[1]

        # Insure that naxis1,2 always return as integer values.
        self.naxis1 = int(self.naxis1)
        self.naxis2 = int(self.naxis2)

        if refpos is not None:
            self.crpix1 = refpos[0]
            self.crpix2 = refpos[1]
        if self.crpix1 is None:
            self.crpix1 = self.naxis1/2.
            self.crpix2 = self.naxis2/2.

        if refval is not None:
            self.crval1 = refval[0]
            self.crval2 = refval[1]

        # Reset WCS info now...
        if _updateCD:
            # Only update this should the pscale or orientation change...
            pscale = pixel_scale / 3600.

            self.cd11 = -pscale * N.cos(pa)
            self.cd12 = pscale * N.sin(pa)
            self.cd21 = self.cd12
            self.cd22 = -self.cd11

        # Now make sure that all derived values are really up-to-date based
        # on these changes
        self.update()


Instruction:
Can you tell what is the following Python 3 function doing
def scale_WCS(self,pixel_scale,retain=True):
        ''' Scale the WCS to a new pixel_scale. The 'retain' parameter
        [default value: True] controls whether or not to retain the original
        distortion solution in the CD matrix.
        '''
        _ratio = pixel_scale / self.pscale

        # Correct the size of the image and CRPIX values for scaled WCS
        self.naxis1 /= _ratio
        self.naxis2 /= _ratio
        self.crpix1 = self.naxis1/2.
        self.crpix2 = self.naxis2/2.

        if retain:
            # Correct the WCS while retaining original distortion information
            self.cd11 *= _ratio
            self.cd12 *= _ratio
            self.cd21 *= _ratio
            self.cd22 *= _ratio
        else:
            pscale = pixel_scale / 3600.
            self.cd11 = -pscale * N.cos(pa)
            self.cd12 = pscale * N.sin(pa)
            self.cd21 = self.cd12
            self.cd22 = -self.cd11

        # Now make sure that all derived values are really up-to-date based
        # on these changes
        self.update()

Response: Scale the WCS to a new pixel_scale. The retain parameter controls whether or not to retain the original WCS.


Instruction:
Make a summary of the following Python 3 code
def rotateCD(self,orient):
        # Determine where member CRVAL position falls in ref frame
        # Find out whether this needs to be rotated to align with
        # reference frame.

        _delta = self.get_orient() - orient
        if _delta == 0.:
            return

        # Start by building the rotation matrix...
        _rot = fileutil.buildRotMatrix(_delta)
        # ...then, rotate the CD matrix and update the values...
        _cd = N.array([[self.cd11,self.cd12],[self.cd21,self.cd22]],dtype=N.float64)
        _cdrot = N.dot(_cd,_rot)
        self.cd11 = _cdrot[0][0]
        self.cd12 = _cdrot[0][1]
        self.cd21 = _cdrot[1][0]
        self.cd22 = _cdrot[1][1]
        self.orient = orient

Response: Rotates the WCS CD matrix to new orientation given by orient.


Instruction:
Can you tell what is the following Python 3 function doing
def write(self,fitsname=None,wcs=None,archive=True,overwrite=False,quiet=True):
        ## Start by making sure all derived values are in sync with CD matrix
        self.update()

        image = self.rootname
        _fitsname = fitsname

        if image.find('.fits') < 0 and _fitsname is not None:
            # A non-FITS image was provided, and openImage made a copy
            # Update attributes to point to new copy instead
            self.geisname = image
            image = self.rootname = _fitsname

        # Open image as writable FITS object
        fimg = fileutil.openImage(image, mode='update', fitsname=_fitsname)

        _root,_iextn = fileutil.parseFilename(image)
        _extn = fileutil.getExtn(fimg,_iextn)

        # Write out values to header...
        if wcs:
            _wcsobj = wcs
        else:
            _wcsobj = self

        for key in _wcsobj.wcstrans.keys():
            _dkey = _wcsobj.wcstrans[key]
            if _dkey != 'pscale':
                _extn.header[key] = _wcsobj.__dict__[_dkey]

        # Close the file
        fimg.close()
        del fimg
        if archive:
            self.write_archive(fitsname=fitsname,overwrite=overwrite,quiet=quiet)

Response: Write out the values of the WCS keywords to the file.


Instruction:
Make a summary of the following Python 3 code
def restore(self):
        # If there are no backup keys, do nothing...
        if len(list(self.backup.keys())) == 0:
            return
        for key in self.backup.keys():
            if key != 'WCSCDATE':
                self.__dict__[self.wcstrans[key]] = self.orig_wcs[self.backup[key]]

        self.update()

Response:
Reset the active WCS keywords to values stored in the the
            backup keywords.


Instruction:
Can you implement a function in Python 3 that
creates backup copies of the WCS keywords with the given prepended string.

Response:
def archive(self,prepend=None,overwrite=no,quiet=yes):
        """ Create backup copies of the WCS keywords with the given prepended
            string.
            If backup keywords are already present, only update them if
            'overwrite' is set to 'yes', otherwise, do warn the user and do nothing.
            Set the WCSDATE at this time as well.
        """
        # Verify that existing backup values are not overwritten accidentally.
        if len(list(self.backup.keys())) > 0 and overwrite == no:
            if not quiet:
                print('WARNING: Backup WCS keywords already exist! No backup made.')
                print('         The values can only be overridden if overwrite=yes.')
            return

        # Establish what prepend string to use...
        if prepend is None:
            if self.prepend is not None:
                _prefix = self.prepend
            else:
                _prefix = DEFAULT_PREFIX
        else:
            _prefix = prepend

        # Update backup and orig_wcs dictionaries
        # We have archive keywords and a defined prefix
        # Go through and append them to self.backup
        self.prepend = _prefix
        for key in self.wcstrans.keys():
            if key != 'pixel scale':
                _archive_key = self._buildNewKeyname(key,_prefix)
            else:
                _archive_key = self.prepend.lower()+'pscale'
#            if key != 'pixel scale':
            self.orig_wcs[_archive_key] = self.__dict__[self.wcstrans[key]]
            self.backup[key] = _archive_key
            self.revert[_archive_key] = key

        # Setup keyword to record when these keywords were backed up.
        self.orig_wcs['WCSCDATE']= fileutil.getLTime()
        self.backup['WCSCDATE'] = 'WCSCDATE'
        self.revert['WCSCDATE'] = 'WCSCDATE'


Instruction:
Write a Python 3 script for
extracting a copy of WCS keywords from an open file header and set the prefix used for those keywords.

Response:
def read_archive(self,header,prepend=None):
        """ Extract a copy of WCS keywords from an open file header,
            if they have already been created and remember the prefix
            used for those keywords. Otherwise, setup the current WCS
            keywords as the archive values.
        """
        # Start by looking for the any backup WCS keywords to
        # determine whether archived values are present and to set
        # the prefix used.
        _prefix = None
        _archive = False
        if header is not None:
            for kw in header.items():
                if kw[0][1:] in self.wcstrans.keys():
                    _prefix = kw[0][0]
                    _archive = True
                    break

        if not _archive:
            self.archive(prepend=prepend)
            return

        # We have archive keywords and a defined prefix
        # Go through and append them to self.backup
        if _prefix is not None:
            self.prepend = _prefix
        else:
            self.prepend = DEFAULT_PREFIX

        for key in self.wcstrans.keys():
            _archive_key = self._buildNewKeyname(key,_prefix)
            if key!= 'pixel scale':
                if _archive_key in header:
                    self.orig_wcs[_archive_key] = header[_archive_key]
                else:
                    self.orig_wcs[_archive_key] = header[key]
                self.backup[key] = _archive_key
                self.revert[_archive_key] = key

        # Establish plate scale value
        _cd11str = self.prepend+'CD1_1'
        _cd21str = self.prepend+'CD2_1'
        pscale = self.compute_pscale(self.orig_wcs[_cd11str],self.orig_wcs[_cd21str])
        _archive_key = self.prepend.lower()+'pscale'
        self.orig_wcs[_archive_key] = pscale
        self.backup['pixel scale'] = _archive_key
        self.revert[_archive_key] = 'pixel scale'

        # Setup keyword to record when these keywords were backed up.
        if 'WCSCDATE' in header:
            self.orig_wcs['WCSCDATE'] = header['WCSCDATE']
        else:
            self.orig_wcs['WCSCDATE'] = fileutil.getLTime()
        self.backup['WCSCDATE'] = 'WCSCDATE'
        self.revert['WCSCDATE'] = 'WCSCDATE'


Instruction:
Implement a Python 3 function for
writing out the WCS keywords to the archive.

Response:
def write_archive(self,fitsname=None,overwrite=no,quiet=yes):
        """ Saves a copy of the WCS keywords from the image header
            as new keywords with the user-supplied 'prepend'
            character(s) prepended to the old keyword names.

            If the file is a GEIS image and 'fitsname' is not None, create
            a FITS copy and update that version; otherwise, raise
            an Exception and do not update anything.

        """
        _fitsname = fitsname

        # Open image in update mode
        #    Copying of GEIS images handled by 'openImage'.
        fimg = fileutil.openImage(self.rootname,mode='update',fitsname=_fitsname)
        if self.rootname.find('.fits') < 0 and _fitsname is not None:
            # A non-FITS image was provided, and openImage made a copy
            # Update attributes to point to new copy instead
            self.geisname = self.rootname
            self.rootname = _fitsname

        # extract the extension ID being updated
        _root,_iextn = fileutil.parseFilename(self.rootname)
        _extn = fileutil.getExtn(fimg,_iextn)
        if not quiet:
            print('Updating archive WCS keywords for ',_fitsname)

        # Write out values to header...
        for key in self.orig_wcs.keys():
            _comment = None
            _dkey = self.revert[key]

            # Verify that archive keywords will not be overwritten,
            # unless overwrite=yes.
            _old_key = key in _extn.header
            if  _old_key == True and overwrite == no:
                if not quiet:
                    print('WCS keyword',key,' already exists! Not overwriting.')
                continue

            # No archive keywords exist yet in file, or overwrite=yes...
            # Extract the value for the original keyword
            if _dkey in _extn.header:

                # Extract any comment string for the keyword as well
                _indx_key = _extn.header.index(_dkey)
                _full_key = _extn.header.cards[_indx_key]
                if not quiet:
                    print('updating ',key,' with value of: ',self.orig_wcs[key])
                _extn.header[key] = (self.orig_wcs[key], _full_key.comment)

        key = 'WCSCDATE'
        if key not in _extn.header:
            # Print out history keywords to record when these keywords
            # were backed up.
            _extn.header[key] = (self.orig_wcs[key], "Time WCS keywords were copied.")

        # Close the now updated image
        fimg.close()
        del fimg


Instruction:
Explain what the following Python 3 code does
def createReferenceWCS(self,refname,overwrite=yes):
        hdu = self.createWcsHDU()
        # If refname already exists, delete it to make way for new file
        if os.path.exists(refname):
            if overwrite==yes:
                # Remove previous version and re-create with new header
                os.remove(refname)
                hdu.writeto(refname)
            else:
                # Append header to existing file
                wcs_append = True
                oldhdu = fits.open(refname, mode='append')
                for e in oldhdu:
                    if 'extname' in e.header and e.header['extname'] == 'WCS':
                        wcs_append = False
                if wcs_append == True:
                    oldhdu.append(hdu)
                oldhdu.close()
                del oldhdu
        else:
            # No previous file, so generate new one from scratch
            hdu.writeto(refname)

        # Clean up
        del hdu

Response:
Create a new WCS file for the NEW
            specified image.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def createWcsHDU(self):
        hdu = fits.ImageHDU()
        hdu.header['EXTNAME'] = 'WCS'
        hdu.header['EXTVER'] = 1
        # Now, update original image size information
        hdu.header['WCSAXES'] = (2, "number of World Coordinate System axes")
        hdu.header['NPIX1'] = (self.naxis1, "Length of array axis 1")
        hdu.header['NPIX2'] = (self.naxis2, "Length of array axis 2")
        hdu.header['PIXVALUE'] = (0.0, "values of pixels in array")

        # Write out values to header...
        excluded_keys = ['naxis1','naxis2']
        for key in self.wcskeys:
            _dkey = self.wcstrans[key]
            if _dkey not in excluded_keys:
                hdu.header[key] = self.__dict__[_dkey]

        return hdu

Response: Create a new WCS HDU that can be used to populate a reference WCS HDU.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def main(args=None):
    logger = cfg.configureLogger()
    for root, dirs, files in os.walk(cfg.dataDir):
        for dir in dirs:
            newDir = os.path.join(root, dir)
            try:
                os.removedirs(newDir)
                logger.info("Deleted empty dir " + str(newDir))
            except:
                pass

    if cfg.useTwisted:
        import logging
        logger = logging.getLogger('analyser.twisted')
        from twisted.internet import reactor
        from twisted.web.resource import Resource
        from twisted.web import static, server
        from twisted.web.wsgi import WSGIResource
        from twisted.application import service
        from twisted.internet import endpoints

        class ReactApp:
            """
            Handles the react app (excluding the static dir).
            """

            def __init__(self, path):
                # TODO allow this to load when in debug mode even if the files don't exist
                self.publicFiles = {f: static.File(os.path.join(path, f)) for f in os.listdir(path) if
                                    os.path.exists(os.path.join(path, f))}
                self.indexHtml = ReactIndex(os.path.join(path, 'index.html'))

            def getFile(self, path):
                """
                overrides getChild so it always just serves index.html unless the file does actually exist (i.e. is an
                icon or something like that)
                """
                return self.publicFiles.get(path.decode('utf-8'), self.indexHtml)

        class ReactIndex(static.File):
            """
            a twisted File which overrides getChild so it always just serves index.html (NB: this is a bit of a hack,
            there is probably a more correct way to do this but...)
            """

            def getChild(self, path, request):
                return self

        class FlaskAppWrapper(Resource):
            """
            wraps the flask app as a WSGI resource while allow the react index.html (and its associated static content)
            to be served as the default page.
            """

            def __init__(self):
                super().__init__()
                self.wsgi = WSGIResource(reactor, reactor.getThreadPool(), app)
                import sys
                if getattr(sys, 'frozen', False):
                    # pyinstaller lets you copy files to arbitrary locations under the _MEIPASS root dir
                    uiRoot = sys._MEIPASS
                else:
                    # release script moves the ui under the analyser package because setuptools doesn't seem to include
                    # files from outside the package
                    uiRoot = os.path.dirname(__file__)
                logger.info('Serving ui from ' + str(uiRoot))
                self.react = ReactApp(os.path.join(uiRoot, 'ui'))
                self.static = static.File(os.path.join(uiRoot, 'ui', 'static'))

            def getChild(self, path, request):
                """
                Overrides getChild to allow the request to be routed to the wsgi app (i.e. flask for the rest api
                calls),
                the static dir (i.e. for the packaged css/js etc), the various concrete files (i.e. the public
                dir from react-app) or to index.html (i.e. the react app) for everything else.
                :param path:
                :param request:
                :return:
                """
                if path == b'api':
                    request.prepath.pop()
                    request.postpath.insert(0, path)
                    return self.wsgi
                elif path == b'static':
                    return self.static
                else:
                    return self.react.getFile(path)

            def render(self, request):
                return self.wsgi.render(request)

        application = service.Application('analyser')
        site = server.Site(FlaskAppWrapper())
        endpoint = endpoints.TCP4ServerEndpoint(reactor, cfg.getPort(), interface='0.0.0.0')
        endpoint.listen(site)
        reactor.run()
    else:
        # get config from a flask standard place not our config yml
        app.run(debug=cfg.runInDebug(), host='0.0.0.0', port=cfg.getPort())

Response: This is the main entry point for the react app.


Instruction:
Can you tell what is the following Python 3 function doing
def leap(year, method=None):
    '''
    Determine if this is a leap year in the FR calendar using one of three methods: 4, 100, 128
    (every 4th years, every 4th or 400th but not 100th, every 4th but not 128th)
    '''

    method = method or 'equinox'

    if year in (3, 7, 11):
        return True
    elif year < 15:
        return False

    if method in (4, 'continuous') or (year <= 16 and method in (128, 'madler', 4, 'continuous')):
        return year % 4 == 3

    elif method in (100, 'romme'):
        return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0

    elif method in (128, 'madler'):
        return year % 4 == 0 and year % 128 != 0

    elif method == 'equinox':
        # Is equinox on 366th day after (year, 1, 1)
        startjd = to_jd(year, 1, 1, method='equinox')
        if premier_da_la_annee(startjd + 367) - startjd == 366.0:
            return True
    else:
        raise ValueError("Unknown leap year method. Try: continuous, romme, madler or equinox")

    return False

Response: Determine if this is a leap year in the FR calendar.


Instruction:
How would you explain what the following Python 3 function does
def premier_da_la_annee(jd):
    '''Determine the year in the French revolutionary calendar in which a given Julian day falls.
    Returns Julian day number containing fall equinox (first day of the FR year)'''
    p = ephem.previous_fall_equinox(dublin.from_jd(jd))
    previous = trunc(dublin.to_jd(p) - 0.5) + 0.5

    if previous + 364 < jd:
        # test if current day is the equinox if the previous equinox was a long time ago
        n = ephem.next_fall_equinox(dublin.from_jd(jd))
        nxt = trunc(dublin.to_jd(n) - 0.5) + 0.5

        if nxt <= jd:
            return nxt

    return previous

Response: Determine the year in the French revolutionary calendar in which a given Julian day falls.


Instruction:
Explain what the following Python 3 code does
def to_jd(year, month, day, method=None):
    '''Obtain Julian day from a given French Revolutionary calendar date.'''
    method = method or 'equinox'

    if day < 1 or day > 30:
        raise ValueError("Invalid day for this calendar")

    if month > 13:
        raise ValueError("Invalid month for this calendar")

    if month == 13 and day > 5 + leap(year, method=method):
        raise ValueError("Invalid day for this month in this calendar")

    if method == 'equinox':
        return _to_jd_equinox(year, month, day)

    else:
        return _to_jd_schematic(year, month, day, method)

Response: Obtain Julian day from a given French Revolutionary calendar date.