if not self.connected():<EOL><INDENT>self._ws = create_connection(self.WS_URI)<EOL>message = {<EOL>'<STR_LIT:type>':self.WS_TYPE,<EOL>'<STR_LIT>':self.WS_PRODUCT_ID<EOL>}<EOL>self._ws.send(dumps(message))<EOL>with self._lock:<EOL><INDENT>if not self._thread:<EOL><INDENT>thread = Thread(target=self._keep_alive_thread, args=[])<EOL>thread.start()<EOL><DEDENT><DEDENT><DEDENT>

Connects and subscribes to the WebSocket Feed.


if self.connected():<EOL><INDENT>self._ws.close()<EOL>self._ws = None<EOL><DEDENT>


if self.connected():<EOL><INDENT>return self._format_message(self._ws.recv())<EOL><DEDENT>return None<EOL>

Receive the next message in the sequence.

        :returns: the next message in the sequence, None if not connected
        :rtype: dict


if self._ws:<EOL><INDENT>return self._ws.connected<EOL><DEDENT>return False<EOL>

Checks if we are connected to the WebSocket Feed.

        :returns: True if connected, otherwise False
        :rtype: bool


error_class = _status_code_to_class.get(response.status_code, APIError)<EOL>return error_class(response)<EOL>

Acquires the correct error for a given response.

    :param requests.Response response: HTTP error response
    :returns: the appropriate error for a given response
    :rtype: APIError


url = self.base_url<EOL>if self.URL_TEMPLATE is not None:<EOL><INDENT>url = urlparse.urljoin(<EOL>self.base_url, self.URL_TEMPLATE.format(**self.url_kwargs)<EOL>)<EOL><DEDENT>if not url:<EOL><INDENT>return None<EOL><DEDENT>url_parts = list(urlparse.urlparse(url))<EOL>query = urlparse.parse_qsl(url_parts[<NUM_LIT:4>])<EOL>for k, v in self.url_kwargs.items():<EOL><INDENT>if v is None:<EOL><INDENT>continue<EOL><DEDENT>if "<STR_LIT>".format(k) not in str(self.URL_TEMPLATE):<EOL><INDENT>for i in iterable(v):<EOL><INDENT>query.append((k, i))<EOL><DEDENT><DEDENT><DEDENT>url_parts[<NUM_LIT:4>] = urlencode(query)<EOL>return urlparse.urlunparse(url_parts)<EOL>

A URL that can be used to open the page.

        The URL is formatted from :py:attr:`URL_TEMPLATE`, which is then
        appended to :py:attr:`base_url` unless the template results in an
        absolute URL.

        :return: URL that can be used to open the page.
        :rtype: str


if self.seed_url:<EOL><INDENT>self.driver_adapter.open(self.seed_url)<EOL>self.wait_for_page_to_load()<EOL>return self<EOL><DEDENT>raise UsageError("<STR_LIT>")<EOL>

Open the page.

        Navigates to :py:attr:`seed_url` and calls :py:func:`wait_for_page_to_load`.

        :return: The current page object.
        :rtype: :py:class:`Page`
        :raises: UsageError


self.wait.until(lambda _: self.loaded)<EOL>self.pm.hook.pypom_after_wait_for_page_to_load(page=self)<EOL>return self<EOL>


return True<EOL>

Loaded state of the page.

        By default the driver will try to wait for any page loads to be
        complete, however it's not uncommon for it to return early. To address
        this you can override :py:attr:`loaded` to return ``True`` when the
        page has finished loading.

        :return: ``True`` if page is loaded, else ``False``.
        :rtype: bool

        Usage (Selenium)::

          from pypom import Page
          from selenium.webdriver.common.by import By

          class Mozilla(Page):

              @property
              def loaded(self):
                  body = self.find_element(By.TAG_NAME, 'body')
                  return 'loaded' in body.get_attribute('class')

        Usage (Splinter)::

          from pypom import Page

          class Mozilla(Page):

              def loaded(self):
                  body = self.find_element('tag', 'body')
                  return 'loaded' in body['class']

        Examples::

            # wait for the seed_url value to be in the current URL
            self.seed_url in self.selenium.current_url


warn("<STR_LIT>", DeprecationWarning, stacklevel=<NUM_LIT:2>)<EOL>return self.driver<EOL>


def find_elements(self, strategy, locator):

return self.driver_adapter.find_elements(strategy, locator)<EOL>

Finds elements on the page.

        :param strategy: Location strategy to use. See :py:class:`~selenium.webdriver.common.by.By` or :py:attr:`~pypom.splinter_driver.ALLOWED_STRATEGIES`.
        :param locator: Location of target elements.
        :type strategy: str
        :type locator: str
        :return: List of :py:class:`~selenium.webdriver.remote.webelement.WebElement` or :py:class:`~splinter.element_list.ElementList`
        :rtype: list


def is_element_present(self, strategy, locator):

return self.driver_adapter.is_element_present(strategy, locator)<EOL>

Checks whether an element is present.

        :param strategy: Location strategy to use. See :py:class:`~selenium.webdriver.common.by.By` or :py:attr:`~pypom.splinter_driver.ALLOWED_STRATEGIES`.
        :param locator: Location of target element.
        :type strategy: str
        :type locator: str
        :return: ``True`` if element is present, else ``False``.
        :rtype: bool


def is_element_displayed(self, strategy, locator):

return self.driver_adapter.is_element_displayed(strategy, locator)<EOL>

Checks whether an element is displayed.

        :param strategy: Location strategy to use. See :py:class:`~selenium.webdriver.common.by.By` or :py:attr:`~pypom.splinter_driver.ALLOWED_STRATEGIES`.
        :param locator: Location of target element.
        :type strategy: str
        :type locator: str
        :return: ``True`` if element is displayed, else ``False``.
        :rtype: bool


if self._root is None and self._root_locator is not None:<EOL><INDENT>return self.page.find_element(*self._root_locator)<EOL><DEDENT>return self._root<EOL>

Root element for the page region.

        Page regions should define a root element either by passing this on
        instantiation or by defining a :py:attr:`_root_locator` attribute. To
        reduce the chances of hitting :py:class:`~selenium.common.exceptions.StaleElementReferenceException`
        or similar you should use :py:attr:`_root_locator`, as this is looked up every
        time the :py:attr:`root` property is accessed.


self.wait.until(lambda _: self.loaded)<EOL>self.pm.hook.pypom_after_wait_for_region_to_load(region=self)<EOL>return self<EOL>


def find_element(self, strategy, locator):

return self.driver_adapter.find_element(strategy, locator, root=self.root)<EOL>

Finds an element on the page.

        :param strategy: Location strategy to use. See :py:class:`~selenium.webdriver.common.by.By` or :py:attr:`~pypom.splinter_driver.ALLOWED_STRATEGIES`.
        :param locator: Location of target element.
        :type strategy: str
        :type locator: str
        :return: An element.
        :rytpe: :py:class:`~selenium.webdriver.remote.webelement.WebElement` or :py:class:`~splinter.driver.webdriver.WebDriverElement`


return self.driver_adapter.find_elements(strategy, locator, root=self.root)<EOL>


return self.driver_adapter.is_element_present(strategy, locator, root=self.root)<EOL>


return self.driver_adapter.is_element_displayed(<EOL>strategy, locator, root=self.root<EOL>)<EOL>


return True<EOL>

Loaded state of the page region.

        You may need to initialise your page region before it's ready for you
        to interact with it. If this is the case, you can override
        :py:attr:`loaded` to return ``True`` when the region has finished
        loading.

        :return: ``True`` if page is loaded, else ``False``.
        :rtype: bool

        Usage (Selenium)::

          from pypom import Page, Region
          from selenium.webdriver.common.by import By

          class Mozilla(Page):
              URL_TEMPLATE = 'https://www.mozilla.org/'

              @property
              def newsletter(self):
                  return Newsletter(self)

              class Newsletter(Region):
                  _root_locator = (By.ID, 'newsletter-form')

                  @property
                  def loaded(self):
                      return 'loaded' in self.root.get_attribute('class')

        Usage (Splinter)::

          from pypom import Page, Region

          class Mozilla(Page):
              URL_TEMPLATE = 'https://www.mozilla.org/'

              @property
              def newsletter(self):
                  return Newsletter(self)

              class Newsletter(Region):
                  _root_locator = ('id', 'newsletter-form')

                  @property
                  def loaded(self):
                      return 'loaded' in self.root['class']


Called after waiting for the page to load


Called after waiting for the region to load


Returns a WebDriverWait like property for a given timeout.

        :param timeout: Timeout used by WebDriverWait like calls
        :type timeout: int


Open the page.
        Navigates to :py:attr:`url`


def find_element(strategy, locator, root=None):

Finds an element on the page.

        :param strategy: Location strategy to use (type depends on the driver implementation)
        :param locator: Location of target element.
        :param root: (optional) root node.
        :type strategy: str
        :type locator: str
        :type root: web element object or None.
        :return: web element object
        :rtype: it depends on the driver implementation


def find_elements(strategy, locator, root=None):

Finds elements on the page.

        :param strategy: Location strategy to use (type depends on the driver implementation)
        :param locator: Location of target elements.
        :param root: (optional) root node.
        :type strategy: str
        :type locator: str
        :type root: web element object or None.
        :return: iterable of web element objects
        :rtype: iterable (if depends on the driver implementation)


def is_element_present(strategy, locator, root=None):

Checks whether an element is present.

        :param strategy: Location strategy to use (type depends on the driver implementation)
        :param locator: Location of target element.
        :param root: (optional) root node.
        :type strategy: str
        :type locator: str
        :type root: web element object or None.
        :return: ``True`` if element is present, else ``False``.
        :rtype: bool


def is_element_displayed(strategy, locator, root=None):

Checks whether an element is displayed.

        :param strategy: Location strategy to use (type depends on the driver implementation)
        :param locator: Location of target element.
        :param root: (optional) root node.
        :type strategy: str
        :type locator: str
        :type root: web element object or None.
        :return: ``True`` if element is displayed, else ``False``.
        :rtype: bool


def registerDriver(iface, driver, class_implements=[]):

for class_item in class_implements:<EOL><INDENT>classImplements(class_item, iface)<EOL><DEDENT>component.provideAdapter(factory=driver, adapts=[iface], provides=IDriver)<EOL>

Register driver adapter used by page object


Register the Selenium specific driver implementation.

        This register call is performed by the init module if
        selenium is available.


return WebDriverWait(self.driver, timeout)<EOL>

Returns a WebDriverWait like property for a given timeout.

        :param timeout: Timeout used by WebDriverWait calls
        :type timeout: int


self.driver.get(url)<EOL>


def find_element(self, strategy, locator, root=None):

if root is not None:<EOL><INDENT>return root.find_element(strategy, locator)<EOL><DEDENT>return self.driver.find_element(strategy, locator)<EOL>

Finds an element on the page.

        :param strategy: Location strategy to use. See :py:class:`~selenium.webdriver.common.by.By` for valid values.
        :param locator: Location of target element.
        :param root: (optional) root node.
        :type strategy: str
        :type locator: str
        :type root: str :py:class:`~selenium.webdriver.remote.webelement.WebElement` object or None.
        :return: :py:class:`~selenium.webdriver.remote.webelement.WebElement` object.
        :rtype: selenium.webdriver.remote.webelement.WebElement


def find_elements(self, strategy, locator, root=None):

if root is not None:<EOL><INDENT>return root.find_elements(strategy, locator)<EOL><DEDENT>return self.driver.find_elements(strategy, locator)<EOL>

Finds elements on the page.

        :param strategy: Location strategy to use. See :py:class:`~selenium.webdriver.common.by.By` for valid values.
        :param locator: Location of target elements.
        :param root: (optional) root node.
        :type strategy: str
        :type locator: str
        :type root: str :py:class:`~selenium.webdriver.remote.webelement.WebElement` object or None.
        :return: List of :py:class:`~selenium.webdriver.remote.webelement.WebElement` objects.
        :rtype: list


def is_element_present(self, strategy, locator, root=None):

try:<EOL><INDENT>return self.find_element(strategy, locator, root=root)<EOL><DEDENT>except NoSuchElementException:<EOL><INDENT>return False<EOL><DEDENT>

Checks whether an element is present.

        :param strategy: Location strategy to use. See :py:class:`~selenium.webdriver.common.by.By` for valid values.
        :param locator: Location of target element.
        :param root: (optional) root node.
        :type strategy: str
        :type locator: str
        :type root: str :py:class:`~selenium.webdriver.remote.webelement.WebElement` object or None.
        :return: ``True`` if element is present, else ``False``.
        :rtype: bool


def is_element_displayed(self, strategy, locator, root=None):

try:<EOL><INDENT>return self.find_element(strategy, locator, root=root).is_displayed()<EOL><DEDENT>except NoSuchElementException:<EOL><INDENT>return False<EOL><DEDENT>

Checks whether an element is displayed.

        :param strategy: Location strategy to use. See :py:class:`~selenium.webdriver.common.by.By` for valid values.
        :param locator: Location of target element.
        :param root: (optional) root node.
        :type strategy: str
        :type locator: str
        :type root: str :py:class:`~selenium.webdriver.remote.webelement.WebElement` object or None.
        :return: ``True`` if element is displayed, else ``False``.
        :rtype: bool


registerDriver(<EOL>ISplinter,<EOL>Splinter,<EOL>class_implements=[<EOL>FirefoxWebDriver,<EOL>ChromeWebDriver,<EOL>RemoteWebDriver,<EOL>],<EOL>)<EOL>


self.driver.visit(url)<EOL>


elements = self.find_elements(strategy, locator, root=root)<EOL>return elements and elements.first or None<EOL>

Finds an element on the page.

        :param strategy: Location strategy to use. See pypom.splinter_driver.ALLOWED_STRATEGIES for valid values.
        :param locator: Location of target element.
        :type strategy: str
        :type locator: str
        :return: :py:class:`~splinter.driver.webdriver.WebDriverElement`.
        :rtype: splinter.driver.webdriver.WebDriverElement


node = root or self.driver<EOL>if strategy in ALLOWED_STRATEGIES:<EOL><INDENT>return getattr(node, "<STR_LIT>" + strategy)(locator)<EOL><DEDENT>raise UsageError("<STR_LIT>")<EOL>

Finds elements on the page.

        :param strategy: Location strategy to use. See pypom.splinter_driver.ALLOWED_STRATEGIES for valid values.
        :param locator: Location of target elements.
        :type strategy: str
        :type locator: str
        :return: List of :py:class:`~splinter.driver.webdriver.WebDriverElement`
        :rtype: :py:class:`splinter.element_list.ElementList`


return self.find_element(strategy, locator, root=root) and True or False<EOL>

Checks whether an element is present.

        :param strategy: Location strategy to use. See pypom.splinter_driver.ALLOWED_STRATEGIES for valid values.
        :param locator: Location of target element.
        :type strategy: str
        :type locator: str
        :return: ``True`` if element is present, else ``False``.
        :rtype: bool


element = self.find_element(strategy, locator, root=root)<EOL>return element and element.visible or False<EOL>

Checks whether an element is displayed.

        :param strategy: Location strategy to use. See pypom.splinter_driver.ALLOWED_STRATEGIES for valid values.
        :param locator: Location of target element.
        :type strategy: str
        :type locator: str
        :return: ``True`` if element is displayed, else ``False``.
        :rtype: bool


def __init__(self, south, west, north, east):

self.west = west<EOL>self.south = south<EOL>self.east = east<EOL>self.north = north<EOL>

Initialize query with given bounding box.

:param bbox Bounding box with limit values in format west, south,
east, north.


self.query_parameters = query_parameters<EOL>

Initialize a query for a set of ways satisfying the given parameters.

        :param query_parameters Overpass QL query parameters


def get(self, query, responseformat="<STR_LIT>", verbosity="<STR_LIT:body>", build=True):

<EOL>if build:<EOL><INDENT>full_query = self._construct_ql_query(<EOL>query, responseformat=responseformat, verbosity=verbosity<EOL>)<EOL><DEDENT>else:<EOL><INDENT>full_query = query<EOL><DEDENT>if self.debug:<EOL><INDENT>logging.getLogger().info(query)<EOL><DEDENT>r = self._get_from_overpass(full_query)<EOL>content_type = r.headers.get("<STR_LIT>")<EOL>if self.debug:<EOL><INDENT>print(content_type)<EOL><DEDENT>if content_type == "<STR_LIT>":<EOL><INDENT>result = []<EOL>reader = csv.reader(StringIO(r.text), delimiter="<STR_LIT:\t>")<EOL>for row in reader:<EOL><INDENT>result.append(row)<EOL><DEDENT>return result<EOL><DEDENT>elif content_type in ("<STR_LIT>", "<STR_LIT>", "<STR_LIT>"):<EOL><INDENT>return r.text<EOL><DEDENT>elif content_type == "<STR_LIT:application/json>":<EOL><INDENT>response = json.loads(r.text)<EOL><DEDENT>if not build:<EOL><INDENT>return response<EOL><DEDENT>if "<STR_LIT>" not in response:<EOL><INDENT>raise UnknownOverpassError("<STR_LIT>")<EOL><DEDENT>overpass_remark = response.get("<STR_LIT>", None)<EOL>if overpass_remark and overpass_remark.startswith("<STR_LIT>"):<EOL><INDENT>raise ServerRuntimeError(overpass_remark)<EOL><DEDENT>if responseformat is not "<STR_LIT>":<EOL><INDENT>return response<EOL><DEDENT>return self._as_geojson(response["<STR_LIT>"])<EOL>

Pass in an Overpass query in Overpass QL.


def search(self, feature_type, regex=False):

raise NotImplementedError()<EOL>


try:<EOL><INDENT>f = open(USB_SYS_PREFIX + path + "<STR_LIT:/>" + name)<EOL>return f.readline().rstrip("<STR_LIT:\n>")<EOL><DEDENT>except IOError:<EOL><INDENT>return None<EOL><DEDENT>

Read attribute from sysfs and return as string


bus_id = device.bus<EOL>dev_id = device.address<EOL>for dirent in os.listdir(USB_SYS_PREFIX):<EOL><INDENT>matches = re.match(USB_PORTS_STR + '<STR_LIT:$>', dirent)<EOL>if matches:<EOL><INDENT>bus_str = readattr(dirent, '<STR_LIT>')<EOL>if bus_str:<EOL><INDENT>busnum = float(bus_str)<EOL><DEDENT>else:<EOL><INDENT>busnum = None<EOL><DEDENT>dev_str = readattr(dirent, '<STR_LIT>')<EOL>if dev_str:<EOL><INDENT>devnum = float(dev_str)<EOL><DEDENT>else:<EOL><INDENT>devnum = None<EOL><DEDENT>if busnum == bus_id and devnum == dev_id:<EOL><INDENT>return str(matches.groups()[<NUM_LIT:1>])<EOL><DEDENT><DEDENT><DEDENT>

Find the port chain a device is plugged on.

This is done by searching sysfs for a device that matches the device
bus/address combination.

Useful when the underlying usb lib does not return device.port_number for
whatever reason.


def set_calibration_data(self, scale=None, offset=None):

if scale is not None and offset is not None:<EOL><INDENT>self._scale = scale<EOL>self._offset = offset<EOL><DEDENT>elif scale is None and offset is None:<EOL><INDENT>self._scale = <NUM_LIT:1.0><EOL>self._offset = <NUM_LIT:0.0><EOL>try:<EOL><INDENT>f = open('<STR_LIT>', '<STR_LIT:r>')<EOL><DEDENT>except IOError:<EOL><INDENT>f = None<EOL><DEDENT>if f:<EOL><INDENT>lines = f.read().split('<STR_LIT:\n>')<EOL>f.close()<EOL>for line in lines:<EOL><INDENT>matches = re.match(CALIB_LINE_STR, line)<EOL>if matches:<EOL><INDENT>bus = int(matches.groups()[<NUM_LIT:0>])<EOL>ports = matches.groups()[<NUM_LIT:1>]<EOL>scale = float(matches.groups()[<NUM_LIT:2>])<EOL>offset = float(matches.groups()[<NUM_LIT:3>])<EOL>if (str(ports) == str(self._ports)) and (str(bus) == str(self._bus)):<EOL><INDENT>self._scale = scale<EOL>self._offset = offset<EOL><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>raise RuntimeError("<STR_LIT>")<EOL><DEDENT>

Set device calibration data based on settings in /etc/temper.conf.


if self._device.product == '<STR_LIT>':<EOL><INDENT>return <NUM_LIT:4><EOL><DEDENT>return (sensor + <NUM_LIT:1>) * <NUM_LIT:2><EOL>

Lookup the number of sensors on the device by product name.


if self._device.product == '<STR_LIT>':<EOL><INDENT>return <NUM_LIT:4><EOL><DEDENT>return None<EOL>

Lookup the offset of the humidity data by product name.


if (self._device.product == '<STR_LIT>') or(self._device.product == '<STR_LIT>'):<EOL><INDENT>return <NUM_LIT:1><EOL><DEDENT>return <NUM_LIT:2><EOL>


return self._sensor_count<EOL>


<EOL>if count not in [<NUM_LIT:1>, <NUM_LIT:2>,]:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>self._sensor_count = int(count)<EOL>

Set number of sensors on the device.

To do: revamp /etc/temper.conf file to include this data.


if self._ports:<EOL><INDENT>return self._ports<EOL><DEDENT>return '<STR_LIT>'<EOL>


if self._bus:<EOL><INDENT>return self._bus<EOL><DEDENT>return '<STR_LIT>'<EOL>


try:<EOL><INDENT>if reset_device:<EOL><INDENT>self._device.reset()<EOL><DEDENT>for interface in [<NUM_LIT:0>,<NUM_LIT:1>]:<EOL><INDENT>if self._device.is_kernel_driver_active(interface):<EOL><INDENT>LOGGER.debug('<STR_LIT>'<EOL>'<STR_LIT>', interface, self._device, self._ports)<EOL>self._device.detach_kernel_driver(interface)<EOL><DEDENT><DEDENT>self._device.set_configuration()<EOL>usb.util.claim_interface(self._device, INTERFACE)<EOL>self._control_transfer(COMMANDS['<STR_LIT>'])<EOL>self._interrupt_read()<EOL>self._control_transfer(COMMANDS['<STR_LIT>'])<EOL>temp_data = self._interrupt_read()<EOL>if self._device.product == '<STR_LIT>':<EOL><INDENT>humidity_data = temp_data<EOL><DEDENT>else:<EOL><INDENT>humidity_data = None<EOL><DEDENT>data = {'<STR_LIT>': temp_data, '<STR_LIT>': humidity_data}<EOL>usb.util.dispose_resources(self._device)<EOL>return data<EOL><DEDENT>except usb.USBError as err:<EOL><INDENT>if not reset_device:<EOL><INDENT>LOGGER.warning("<STR_LIT>", err, self._device)<EOL>return self.get_data(True)<EOL><DEDENT>if "<STR_LIT>" in str(err):<EOL><INDENT>raise Exception(<EOL>"<STR_LIT>"<EOL>"<STR_LIT>")<EOL><DEDENT>else:<EOL><INDENT>LOGGER.error(err)<EOL>raise<EOL><DEDENT><DEDENT>


def get_temperature(self, format='<STR_LIT>', sensor=<NUM_LIT:0>):

results = self.get_temperatures(sensors=[sensor,])<EOL>if format == '<STR_LIT>':<EOL><INDENT>return results[sensor]['<STR_LIT>']<EOL><DEDENT>elif format == '<STR_LIT>':<EOL><INDENT>return results[sensor]['<STR_LIT>']<EOL><DEDENT>elif format == '<STR_LIT>':<EOL><INDENT>return results[sensor]['<STR_LIT>']<EOL><DEDENT>else:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>


_sensors = sensors<EOL>if _sensors is None:<EOL><INDENT>_sensors = list(range(<NUM_LIT:0>, self._sensor_count))<EOL><DEDENT>if not set(_sensors).issubset(list(range(<NUM_LIT:0>, self._sensor_count))):<EOL><INDENT>raise ValueError(<EOL>'<STR_LIT>'<EOL>'<STR_LIT>' % (<EOL>_sensors,<EOL>self._sensor_count,<EOL>list(range(<NUM_LIT:0>, self._sensor_count)),<EOL>)<EOL>)<EOL><DEDENT>data = self.get_data()<EOL>data = data['<STR_LIT>']<EOL>results = {}<EOL>for sensor in _sensors:<EOL><INDENT>offset = self.lookup_offset(sensor)<EOL>celsius = struct.unpack_from('<STR_LIT>', data, offset)[<NUM_LIT:0>] / <NUM_LIT><EOL>celsius = celsius * self._scale + self._offset<EOL>results[sensor] = {<EOL>'<STR_LIT>': self.get_ports(),<EOL>'<STR_LIT>': self.get_bus(),<EOL>'<STR_LIT>': sensor,<EOL>'<STR_LIT>': celsius * <NUM_LIT> + <NUM_LIT>,<EOL>'<STR_LIT>': celsius,<EOL>'<STR_LIT>': celsius * <NUM_LIT:1000>,<EOL>'<STR_LIT>': celsius + <NUM_LIT>,<EOL>}<EOL><DEDENT>return results<EOL>

Get device temperature reading.

Params:
- sensors: optional list of sensors to get a reading for, examples:
  [0,] - get reading for sensor 0
  [0, 1,] - get reading for sensors 0 and 1
  None - get readings for all sensors


_sensors = sensors<EOL>if _sensors is None:<EOL><INDENT>_sensors = list(range(<NUM_LIT:0>, self._sensor_count))<EOL><DEDENT>if not set(_sensors).issubset(list(range(<NUM_LIT:0>, self._sensor_count))):<EOL><INDENT>raise ValueError(<EOL>'<STR_LIT>'<EOL>'<STR_LIT>' % (<EOL>_sensors,<EOL>self._sensor_count,<EOL>list(range(<NUM_LIT:0>, self._sensor_count)),<EOL>)<EOL>)<EOL><DEDENT>data = self.get_data()<EOL>data = data['<STR_LIT>']<EOL>results = {}<EOL>for sensor in _sensors:<EOL><INDENT>offset = self.lookup_humidity_offset(sensor)<EOL>if offset is None:<EOL><INDENT>continue<EOL><DEDENT>humidity = (struct.unpack_from('<STR_LIT>', data, offset)[<NUM_LIT:0>] * <NUM_LIT:32>) / <NUM_LIT><EOL>results[sensor] = {<EOL>'<STR_LIT>': self.get_ports(),<EOL>'<STR_LIT>': self.get_bus(),<EOL>'<STR_LIT>': sensor,<EOL>'<STR_LIT>': humidity,<EOL>}<EOL><DEDENT>return results<EOL>

Get device humidity reading.

Params:
- sensors: optional list of sensors to get a reading for, examples:
  [0,] - get reading for sensor 0
  [0, 1,] - get reading for sensors 0 and 1
  None - get readings for all sensors


LOGGER.debug('<STR_LIT>', data)<EOL>self._device.ctrl_transfer(bmRequestType=<NUM_LIT>, bRequest=<NUM_LIT>,<EOL>wValue=<NUM_LIT>, wIndex=<NUM_LIT>, data_or_wLength=data, timeout=TIMEOUT)<EOL>

Send device a control request with standard parameters and <data> as
payload.


data = self._device.read(ENDPOINT, REQ_INT_LEN, timeout=TIMEOUT)<EOL>LOGGER.debug('<STR_LIT>', data)<EOL>return data<EOL>


pass<EOL>

Does nothing in this device. Other device types may need to do cleanup here.


return self._devices<EOL>

Get a list of all devices attached to this handler


return u"<STR_LIT>"<EOL>


with open(fname) as f:<EOL><INDENT>for line in f:<EOL><INDENT>if line.startswith("<STR_LIT>"):<EOL><INDENT>return eval(line.split("<STR_LIT:=>")[-<NUM_LIT:1>])<EOL><DEDENT><DEDENT><DEDENT>

Parse our source code to get the current version number.


def code_mapping(level, msg, default=<NUM_LIT>):

try:<EOL><INDENT>return code_mappings_by_level[level][msg]<EOL><DEDENT>except KeyError:<EOL><INDENT>pass<EOL><DEDENT>if msg.count('<STR_LIT:">') == <NUM_LIT:2> and '<STR_LIT>' in msg and msg.endswith('<STR_LIT>'):<EOL><INDENT>txt = msg[: msg.index('<STR_LIT>')]<EOL>return code_mappings_by_level[level].get(txt, default)<EOL><DEDENT>return default<EOL>


if not docstring:<EOL><INDENT>return "<STR_LIT>"<EOL><DEDENT>lines = docstring.expandtabs().splitlines()<EOL>indent = sys.maxsize<EOL>for line in lines[<NUM_LIT:1>:]:<EOL><INDENT>stripped = line.lstrip()<EOL>if stripped:<EOL><INDENT>indent = min(indent, len(line) - len(stripped))<EOL><DEDENT><DEDENT>trimmed = [lines[<NUM_LIT:0>].strip()]<EOL>if indent < sys.maxsize:<EOL><INDENT>for line in lines[<NUM_LIT:1>:]:<EOL><INDENT>trimmed.append(line[indent:].rstrip())<EOL><DEDENT><DEDENT>while trimmed and not trimmed[-<NUM_LIT:1>]:<EOL><INDENT>trimmed.pop()<EOL><DEDENT>while trimmed and not trimmed[<NUM_LIT:0>]:<EOL><INDENT>trimmed.pop(<NUM_LIT:0>)<EOL><DEDENT>return "<STR_LIT:\n>".join(trimmed)<EOL>

PEP257 docstring indentation trim function.


<EOL>text = text.strip()<EOL>if len(text) > <NUM_LIT:6> and text[:<NUM_LIT:3>] == text[-<NUM_LIT:3>:] == '<STR_LIT>':<EOL><INDENT>return text[<NUM_LIT:3>:-<NUM_LIT:3>]<EOL><DEDENT>if len(text) > <NUM_LIT:7> and text[:<NUM_LIT:4>] in ('<STR_LIT>', '<STR_LIT>') and text[-<NUM_LIT:3>:] == '<STR_LIT>':<EOL><INDENT>return text[<NUM_LIT:4>:-<NUM_LIT:3>]<EOL><DEDENT>if len(text) > <NUM_LIT:6> and text[:<NUM_LIT:3>] == text[-<NUM_LIT:3>:] == "<STR_LIT>":<EOL><INDENT>return text[<NUM_LIT:3>:-<NUM_LIT:3>]<EOL><DEDENT>if len(text) > <NUM_LIT:7> and text[:<NUM_LIT:4>] in ("<STR_LIT>", "<STR_LIT>") and text[-<NUM_LIT:3>:] == "<STR_LIT>":<EOL><INDENT>return text[<NUM_LIT:4>:-<NUM_LIT:3>]<EOL><DEDENT>if len(text) > <NUM_LIT:2> and text[<NUM_LIT:0>] == text[-<NUM_LIT:1>] == '<STR_LIT:">':<EOL><INDENT>return text[<NUM_LIT:1>:-<NUM_LIT:1>]<EOL><DEDENT>if len(text) > <NUM_LIT:3> and text[:<NUM_LIT:2>] in ('<STR_LIT>', '<STR_LIT>') and text[-<NUM_LIT:1>] == '<STR_LIT:">':<EOL><INDENT>return text[<NUM_LIT:2>:-<NUM_LIT:1>]<EOL><DEDENT>if len(text) > <NUM_LIT:2> and text[<NUM_LIT:0>] == text[-<NUM_LIT:1>] == "<STR_LIT:'>":<EOL><INDENT>return text[<NUM_LIT:1>:-<NUM_LIT:1>]<EOL><DEDENT>if len(text) > <NUM_LIT:3> and text[:<NUM_LIT:2>] in ("<STR_LIT>", "<STR_LIT>") and text[-<NUM_LIT:1>] == "<STR_LIT:'>":<EOL><INDENT>return text[<NUM_LIT:2>:-<NUM_LIT:1>]<EOL><DEDENT>raise ValueError("<STR_LIT>")<EOL>

Remove the quotes delimiting a docstring.


return re.compile(r"<STR_LIT>").sub(r"<STR_LIT>", string).lower()<EOL>


if len(self._fields) != len(args):<EOL><INDENT>raise ValueError(<EOL>"<STR_LIT>".format(<EOL>len(args), len(self._fields), self.__class__.__name__, self._fields<EOL>)<EOL>)<EOL><DEDENT>vars(self).update(zip(self._fields, args))<EOL>


return hash(repr(self))<EOL>


return other and vars(self) == vars(other)<EOL>


kwargs = "<STR_LIT:U+002CU+0020>".join(<EOL>"<STR_LIT>".format(field, getattr(self, field)) for field in self._fields<EOL>)<EOL>return "<STR_LIT>".format(self.__class__.__name__, kwargs)<EOL>


return chain([self], *self.children)<EOL>


full_src = self._source[self._slice]<EOL>def is_empty_or_comment(line):<EOL><INDENT>return line.strip() == "<STR_LIT>" or line.strip().startswith("<STR_LIT:#>")<EOL><DEDENT>filtered_src = dropwhile(is_empty_or_comment, reversed(full_src))<EOL>return "<STR_LIT>".join(reversed(list(filtered_src)))<EOL>

Return the source code for the definition.


out = "<STR_LIT>".format(self._publicity, self._human, self.name)<EOL>if self.skipped_error_codes:<EOL><INDENT>out += "<STR_LIT>".format(self.skipped_error_codes)<EOL><DEDENT>return out<EOL>


return not self.name.startswith("<STR_LIT:_>") or self.name.startswith("<STR_LIT>")<EOL>


return "<STR_LIT>"<EOL>


if self.all is not None:<EOL><INDENT>return self.name in self.all<EOL><DEDENT>else:<EOL><INDENT>return not self.name.startswith("<STR_LIT:_>")<EOL><DEDENT>

Return True iff this function should be considered public.


return (<EOL>self.name.startswith("<STR_LIT>")<EOL>and self.name.endswith("<STR_LIT>")<EOL>and self.name not in VARIADIC_MAGIC_METHODS<EOL>)<EOL>

Return True iff this method is a magic method (e.g., `__str__`).


<EOL>for decorator in self.decorators:<EOL><INDENT>if re.compile(r"<STR_LIT>".format(self.name)).match(decorator.name):<EOL><INDENT>return False<EOL><DEDENT><DEDENT>name_is_public = (<EOL>not self.name.startswith("<STR_LIT:_>")<EOL>or self.name in VARIADIC_MAGIC_METHODS<EOL>or self.is_magic<EOL>)<EOL>return self.parent.is_public and name_is_public<EOL>

Return True iff this method should be considered public.


return (<EOL>not self.name.startswith("<STR_LIT:_>")<EOL>and self.parent.is_class<EOL>and self.parent.is_public<EOL>)<EOL>

Return True iff this class should be considered public.


Exception.__init__(<EOL>self,<EOL>message<EOL>+ textwrap.dedent(<EOL>"""<STR_LIT>"""<EOL>),<EOL>)<EOL>

Initialize the error with a more specific message.


self._generator = tk.generate_tokens(filelike.readline)<EOL>self.current = Token(*next(self._generator, None))<EOL>self.line = self.current.start[<NUM_LIT:0>]<EOL>self.log = log<EOL>self.got_logical_newline = True<EOL>


previous = self.current<EOL>current = self._next_from_generator()<EOL>self.current = None if current is None else Token(*current)<EOL>self.line = self.current.start[<NUM_LIT:0>] if self.current else self.line<EOL>self.got_logical_newline = previous.kind in self.LOGICAL_NEWLINES<EOL>return previous<EOL>


while True:<EOL><INDENT>if self.current is not None:<EOL><INDENT>yield self.current<EOL><DEDENT>else:<EOL><INDENT>return<EOL><DEDENT>self.move()<EOL><DEDENT>


return "<STR_LIT>".format(tk.tok_name[self])<EOL>


super(Token, self).__init__(*args)<EOL>self.kind = TokenKind(self.kind)<EOL>


self.log = log<EOL>self.source = filelike.readlines()<EOL>src = "<STR_LIT>".join(self.source)<EOL>compile(src, filename, "<STR_LIT>")<EOL>self.stream = TokenStream(StringIO(src))<EOL>self.filename = filename<EOL>self.all = None<EOL>self.future_imports = set()<EOL>self._accumulated_decorators = []<EOL>return self.parse_module()<EOL>

Parse the given file-like object and return its Module object.


return self.parse(*args, **kwargs)<EOL>


next_token = self.stream.move()<EOL>assert next_token.kind == kind<EOL>

Consume one token and verify it is of the expected kind.


while self.current is not None:<EOL><INDENT>if self.current.kind == kind and (<EOL>value is None or self.current.value == value<EOL>):<EOL><INDENT>self.consume(kind)<EOL>return<EOL><DEDENT>self.stream.move()<EOL><DEDENT>

Skip tokens in the stream until a certain token kind is reached.

        If `value` is specified, tokens whose values are different will also
        be skipped.


self.log.debug(<EOL>"<STR_LIT>", self.current.kind, self.current.value<EOL>)<EOL>while self.current.kind in (tk.COMMENT, tk.NEWLINE, tk.NL):<EOL><INDENT>self.stream.move()<EOL>self.log.debug(<EOL>"<STR_LIT>",<EOL>self.current.kind,<EOL>self.current.value,<EOL>)<EOL><DEDENT>if self.current.kind == tk.STRING:<EOL><INDENT>docstring = self.current.value<EOL>self.stream.move()<EOL>return docstring<EOL><DEDENT>return None<EOL>

Parse a single docstring and return its value.


name = []<EOL>arguments = []<EOL>at_arguments = False<EOL>while self.current is not None:<EOL><INDENT>self.log.debug(<EOL>"<STR_LIT>",<EOL>self.current.kind,<EOL>self.current.value,<EOL>)<EOL>if self.current.kind == tk.NAME and self.current.value in ["<STR_LIT>", "<STR_LIT:class>"]:<EOL><INDENT>break<EOL><DEDENT>elif self.current.kind == tk.OP and self.current.value == "<STR_LIT:@>":<EOL><INDENT>self._accumulated_decorators.append(<EOL>Decorator("<STR_LIT>".join(name), "<STR_LIT>".join(arguments))<EOL>)<EOL>name = []<EOL>arguments = []<EOL>at_arguments = False<EOL><DEDENT>elif self.current.kind == tk.OP and self.current.value == "<STR_LIT:(>":<EOL><INDENT>at_arguments = True<EOL><DEDENT>elif self.current.kind == tk.OP and self.current.value == "<STR_LIT:)>":<EOL><INDENT>pass<EOL><DEDENT>elif self.current.kind == tk.NEWLINE or self.current.kind == tk.NL:<EOL><INDENT>pass<EOL><DEDENT>else:<EOL><INDENT>if not at_arguments:<EOL><INDENT>name.append(self.current.value)<EOL><DEDENT>else:<EOL><INDENT>arguments.append(self.current.value)<EOL><DEDENT><DEDENT>self.stream.move()<EOL><DEDENT>self._accumulated_decorators.append(<EOL>Decorator("<STR_LIT>".join(name), "<STR_LIT>".join(arguments))<EOL>)<EOL>

Called after first @ is found.

        Parse decorators into self._accumulated_decorators.
        Continue to do so until encountering the 'def' or 'class' start token.


def parse_definitions(self, class_, all=False):

while self.current is not None:<EOL><INDENT>self.log.debug(<EOL>"<STR_LIT>",<EOL>self.current.kind,<EOL>self.current.value,<EOL>)<EOL>self.log.debug("<STR_LIT>", self.stream.got_logical_newline)<EOL>if all and self.current.value == "<STR_LIT>":<EOL><INDENT>self.parse_all()<EOL><DEDENT>elif (<EOL>self.current.kind == tk.OP<EOL>and self.current.value == "<STR_LIT:@>"<EOL>and self.stream.got_logical_newline<EOL>):<EOL><INDENT>self.consume(tk.OP)<EOL>self.parse_decorators()<EOL><DEDENT>elif self.current.value in ["<STR_LIT>", "<STR_LIT:class>"]:<EOL><INDENT>yield self.parse_definition(class_._nest(self.current.value))<EOL><DEDENT>elif self.current.kind == tk.INDENT:<EOL><INDENT>self.consume(tk.INDENT)<EOL>for definition in self.parse_definitions(class_):<EOL><INDENT>yield definition<EOL><DEDENT><DEDENT>elif self.current.kind == tk.DEDENT:<EOL><INDENT>self.consume(tk.DEDENT)<EOL>return<EOL><DEDENT>elif self.current.value == "<STR_LIT>":<EOL><INDENT>self.parse_from_import_statement()<EOL><DEDENT>else:<EOL><INDENT>self.stream.move()<EOL><DEDENT><DEDENT>

Parse multiple definitions and yield them.


assert self.current.value == "<STR_LIT>"<EOL>self.consume(tk.NAME)<EOL>if self.current.value != "<STR_LIT:=>":<EOL><INDENT>raise AllError("<STR_LIT>")<EOL><DEDENT>self.consume(tk.OP)<EOL>if self.current.value not in "<STR_LIT>":<EOL><INDENT>raise AllError("<STR_LIT>")<EOL><DEDENT>self.consume(tk.OP)<EOL>self.all = []<EOL>all_content = "<STR_LIT:(>"<EOL>while self.current.kind != tk.OP or self.current.value not in "<STR_LIT>":<EOL><INDENT>if self.current.kind in (tk.NL, tk.COMMENT):<EOL><INDENT>pass<EOL><DEDENT>elif self.current.kind == tk.STRING or self.current.value == "<STR_LIT:U+002C>":<EOL><INDENT>all_content += self.current.value<EOL><DEDENT>else:<EOL><INDENT>raise AllError(<EOL>"<STR_LIT>".format(<EOL>self.current.kind<EOL>)<EOL>)<EOL><DEDENT>self.stream.move()<EOL><DEDENT>self.consume(tk.OP)<EOL>all_content += "<STR_LIT:)>"<EOL>try:<EOL><INDENT>self.all = eval(all_content, {})<EOL><DEDENT>except BaseException as e:<EOL><INDENT>raise AllError(<EOL>"<STR_LIT>"<EOL>"<STR_LIT>".format(all_content, e)<EOL>)<EOL><DEDENT>

Parse the __all__ definition in a module.


self.log.debug("<STR_LIT>")<EOL>start = self.line<EOL>docstring = self.parse_docstring()<EOL>children = list(self.parse_definitions(Module, all=True))<EOL>assert self.current is None, self.current<EOL>end = self.line<EOL>cls = Module<EOL>if self.filename.endswith("<STR_LIT>"):<EOL><INDENT>cls = Package<EOL><DEDENT>module = cls(<EOL>self.filename,<EOL>self.source,<EOL>start,<EOL>end,<EOL>[],<EOL>docstring,<EOL>children,<EOL>None,<EOL>self.all,<EOL>None,<EOL>"<STR_LIT>",<EOL>)<EOL>for child in module.children:<EOL><INDENT>child.parent = module<EOL><DEDENT>module.future_imports = self.future_imports<EOL>self.log.debug("<STR_LIT>")<EOL>return module<EOL>

Parse a module (and its children) and return a Module object.


start = self.line<EOL>self.consume(tk.NAME)<EOL>name = self.current.value<EOL>self.log.debug("<STR_LIT>", class_.__name__, name)<EOL>self.stream.move()<EOL>if self.current.kind == tk.OP and self.current.value == "<STR_LIT:(>":<EOL><INDENT>parenthesis_level = <NUM_LIT:0><EOL>while True:<EOL><INDENT>if self.current.kind == tk.OP:<EOL><INDENT>if self.current.value == "<STR_LIT:(>":<EOL><INDENT>parenthesis_level += <NUM_LIT:1><EOL><DEDENT>elif self.current.value == "<STR_LIT:)>":<EOL><INDENT>parenthesis_level -= <NUM_LIT:1><EOL>if parenthesis_level == <NUM_LIT:0>:<EOL><INDENT>break<EOL><DEDENT><DEDENT><DEDENT>self.stream.move()<EOL><DEDENT><DEDENT>if self.current.kind != tk.OP or self.current.value != "<STR_LIT::>":<EOL><INDENT>self.leapfrog(tk.OP, value="<STR_LIT::>")<EOL><DEDENT>else:<EOL><INDENT>self.consume(tk.OP)<EOL><DEDENT>if self.current.kind in (tk.NEWLINE, tk.COMMENT):<EOL><INDENT>skipped_error_codes = self.parse_skip_comment()<EOL>self.leapfrog(tk.INDENT)<EOL>assert self.current.kind != tk.INDENT<EOL>docstring = self.parse_docstring()<EOL>decorators = self._accumulated_decorators<EOL>self.log.debug("<STR_LIT>", decorators)<EOL>self._accumulated_decorators = []<EOL>self.log.debug("<STR_LIT>")<EOL>children = list(self.parse_definitions(class_))<EOL>self.log.debug("<STR_LIT>", name)<EOL>end = self.line - <NUM_LIT:1><EOL><DEDENT>else:  <EOL><INDENT>skipped_error_codes = "<STR_LIT>"<EOL>docstring = self.parse_docstring()<EOL>decorators = []  <EOL>children = []<EOL>end = self.line<EOL>self.leapfrog(tk.NEWLINE)<EOL><DEDENT>definition = class_(<EOL>name,<EOL>self.source,<EOL>start,<EOL>end,<EOL>decorators,<EOL>docstring,<EOL>children,<EOL>None,<EOL>skipped_error_codes,<EOL>)<EOL>for child in definition.children:<EOL><INDENT>child.parent = definition<EOL><DEDENT>self.log.debug(<EOL>"<STR_LIT>",<EOL>class_.__name__,<EOL>name,<EOL>self.current.kind,<EOL>self.current.value,<EOL>)<EOL>return definition<EOL>

Parse a definition and return its value in a `class_` object.


skipped_error_codes = "<STR_LIT>"<EOL>if self.current.kind == tk.COMMENT:<EOL><INDENT>if "<STR_LIT>" in self.current.value:<EOL><INDENT>skipped_error_codes = "<STR_LIT>".join(self.current.value.split("<STR_LIT>")[<NUM_LIT:1>:])<EOL><DEDENT>elif self.current.value.startswith("<STR_LIT>"):<EOL><INDENT>skipped_error_codes = "<STR_LIT:all>"<EOL><DEDENT><DEDENT>return skipped_error_codes<EOL>

Parse a definition comment for noqa skips.


def check_current(self, kind=None, value=None):

msg = textwrap.dedent(<EOL>"""<STR_LIT>""".format(<EOL>self=self<EOL>)<EOL>)<EOL>kind_valid = self.current.kind == kind if kind else True<EOL>value_valid = self.current.value == value if value else True<EOL>assert kind_valid and value_valid, msg<EOL>

Verify the current token is of type `kind` and equals `value`.


self.log.debug("<STR_LIT>")<EOL>is_future_import = self._parse_from_import_source()<EOL>self._parse_from_import_names(is_future_import)<EOL>

Parse a 'from x import y' statement.

        The purpose is to find __future__ statements.


assert self.current.value == "<STR_LIT>", self.current.value<EOL>self.stream.move()<EOL>is_future_import = self.current.value == "<STR_LIT>"<EOL>self.stream.move()<EOL>while (<EOL>self.current is not None<EOL>and self.current.kind in (tk.DOT, tk.NAME, tk.OP)<EOL>and self.current.value != "<STR_LIT>"<EOL>):<EOL><INDENT>self.stream.move()<EOL><DEDENT>if self.current is None or self.current.value != "<STR_LIT>":<EOL><INDENT>return False<EOL><DEDENT>self.check_current(value="<STR_LIT>")<EOL>assert self.current.value == "<STR_LIT>", self.current.value<EOL>self.stream.move()<EOL>return is_future_import<EOL>

Parse the 'from x import' part in a 'from x import y' statement.

        Return true iff `x` is __future__.


if self.current.value == "<STR_LIT:(>":<EOL><INDENT>self.consume(tk.OP)<EOL>expected_end_kinds = (tk.OP,)<EOL><DEDENT>else:<EOL><INDENT>expected_end_kinds = (tk.NEWLINE, tk.ENDMARKER)<EOL><DEDENT>while self.current.kind not in expected_end_kinds and not (<EOL>self.current.kind == tk.OP and self.current.value == "<STR_LIT:;>"<EOL>):<EOL><INDENT>if self.current.kind != tk.NAME:<EOL><INDENT>self.stream.move()<EOL>continue<EOL><DEDENT>self.log.debug(<EOL>"<STR_LIT>",<EOL>self.current.kind,<EOL>self.current.value,<EOL>)<EOL>if is_future_import:<EOL><INDENT>self.log.debug("<STR_LIT>", self.current.value)<EOL>self.future_imports.add(self.current.value)<EOL><DEDENT>self.consume(tk.NAME)<EOL>self.log.debug(<EOL>"<STR_LIT>",<EOL>self.current.kind,<EOL>self.current.value,<EOL>)<EOL>if self.current.kind == tk.NAME and self.current.value == "<STR_LIT>":<EOL><INDENT>self.consume(tk.NAME)  <EOL>if self.current.kind == tk.NAME:<EOL><INDENT>self.consume(tk.NAME)  <EOL><DEDENT><DEDENT>if self.current.value == "<STR_LIT:U+002C>":<EOL><INDENT>self.consume(tk.OP)<EOL><DEDENT>self.log.debug(<EOL>"<STR_LIT>",<EOL>self.current.kind,<EOL>self.current.value,<EOL>)<EOL><DEDENT>

Parse the 'y' part in a 'from x import y' statement.


def __init__(self, tree, filename="<STR_LIT>", builtins=None):

self.tree = tree<EOL>self.filename = filename<EOL>try:<EOL><INDENT>self.load_source()<EOL>self.err = None<EOL><DEDENT>except Exception as err:<EOL><INDENT>self.source = None<EOL>self.err = err<EOL><DEDENT>


<EOL>if self.err is not None:<EOL><INDENT>assert self.source is None<EOL>msg = "<STR_LIT>" % (<EOL>rst_prefix,<EOL>rst_fail_load,<EOL>"<STR_LIT>" % self.err,<EOL>)<EOL>yield <NUM_LIT:0>, <NUM_LIT:0>, msg, type(self)<EOL>module = []<EOL><DEDENT>try:<EOL><INDENT>module = parse(StringIO(self.source), self.filename)<EOL><DEDENT>except SyntaxError as err:<EOL><INDENT>msg = "<STR_LIT>" % (<EOL>rst_prefix,<EOL>rst_fail_parse,<EOL>"<STR_LIT>" % err,<EOL>)<EOL>yield <NUM_LIT:0>, <NUM_LIT:0>, msg, type(self)<EOL>module = []<EOL><DEDENT>except AllError:<EOL><INDENT>msg = "<STR_LIT>" % (<EOL>rst_prefix,<EOL>rst_fail_all,<EOL>"<STR_LIT>",<EOL>)<EOL>yield <NUM_LIT:0>, <NUM_LIT:0>, msg, type(self)<EOL>module = []<EOL><DEDENT>for definition in module:<EOL><INDENT>if not definition.docstring:<EOL><INDENT>continue<EOL><DEDENT>try:<EOL><INDENT>unindented = trim(dequote_docstring(definition.docstring))<EOL>rst_errors = list(rst_lint.lint(unindented))<EOL><DEDENT>except Exception as err:<EOL><INDENT>msg = "<STR_LIT>" % (<EOL>rst_prefix,<EOL>rst_fail_lint,<EOL>"<STR_LIT>" % (definition.name, err),<EOL>)<EOL>yield definition.start, <NUM_LIT:0>, msg, type(self)<EOL>continue<EOL><DEDENT>for rst_error in rst_errors:<EOL><INDENT>if rst_error.level <= <NUM_LIT:1>:<EOL><INDENT>continue<EOL><DEDENT>msg = rst_error.message.split("<STR_LIT:\n>", <NUM_LIT:1>)[<NUM_LIT:0>]<EOL>code = code_mapping(rst_error.level, msg)<EOL>assert code < <NUM_LIT:100>, code<EOL>code += <NUM_LIT:100> * rst_error.level<EOL>msg = "<STR_LIT>" % (rst_prefix, code, msg)<EOL>yield definition.start + rst_error.line, <NUM_LIT:0>, msg, type(self)<EOL><DEDENT><DEDENT>

Use docutils to check docstrings are valid RST.


if self.filename in self.STDIN_NAMES:<EOL><INDENT>self.filename = "<STR_LIT>"<EOL>if sys.version_info[<NUM_LIT:0>] < <NUM_LIT:3>:<EOL><INDENT>self.source = sys.stdin.read()<EOL><DEDENT>else:<EOL><INDENT>self.source = TextIOWrapper(sys.stdin.buffer, errors="<STR_LIT:ignore>").read()<EOL><DEDENT><DEDENT>else:<EOL><INDENT>handle = tokenize_open(self.filename)<EOL>self.source = handle.read()<EOL>handle.close()<EOL><DEDENT>


return v1 != v2<EOL>


def _ordinal_metric(_v1, _v2, i1, i2, n_v):

if i1 > i2:<EOL><INDENT>i1, i2 = i2, i1<EOL><DEDENT>return (np.sum(n_v[i1:(i2 + <NUM_LIT:1>)]) - (n_v[i1] + n_v[i2]) / <NUM_LIT:2>) ** <NUM_LIT:2><EOL>


def _interval_metric(v1, v2, **_kwargs):

return (v1 - v2) ** <NUM_LIT:2><EOL>


return (((v1 - v2) / (v1 + v2)) ** <NUM_LIT:2>) if v1 + v2 != <NUM_LIT:0> else <NUM_LIT:0><EOL>


def _coincidences(value_counts, value_domain, dtype=np.float64):

value_counts_matrices = value_counts.reshape(value_counts.shape + (<NUM_LIT:1>,))<EOL>pairable = np.maximum(np.sum(value_counts, axis=<NUM_LIT:1>), <NUM_LIT:2>)<EOL>diagonals = np.tile(np.eye(len(value_domain)), (len(value_counts), <NUM_LIT:1>, <NUM_LIT:1>))* value_counts.reshape((value_counts.shape[<NUM_LIT:0>], <NUM_LIT:1>, value_counts.shape[<NUM_LIT:1>]))<EOL>unnormalized_coincidences = value_counts_matrices * value_counts_matrices.transpose((<NUM_LIT:0>, <NUM_LIT:2>, <NUM_LIT:1>)) - diagonals<EOL>return np.sum(np.divide(unnormalized_coincidences, (pairable - <NUM_LIT:1>).reshape((-<NUM_LIT:1>, <NUM_LIT:1>, <NUM_LIT:1>)), dtype=dtype), axis=<NUM_LIT:0>)<EOL>

Coincidence matrix.

    Parameters
    ----------
    value_counts : ndarray, with shape (N, V)
        Number of coders that assigned a certain value to a determined unit, where N is the number of units
        and V is the value count.

    value_domain : array_like, with shape (V,)
        Possible values V the units can take.
        If the level of measurement is not nominal, it must be ordered.

    dtype : data-type
        Result and computation data-type.

    Returns
    -------
    o : ndarray, with shape (V, V)
        Coincidence matrix.


def _random_coincidences(value_domain, n, n_v):

n_v_column = n_v.reshape(-<NUM_LIT:1>, <NUM_LIT:1>)<EOL>return (n_v_column.dot(n_v_column.T) - np.eye(len(value_domain)) * n_v_column) / (n - <NUM_LIT:1>)<EOL>

Random coincidence matrix.

    Parameters
    ----------
    value_domain : array_like, with shape (V,)
        Possible values V the units can take.
        If the level of measurement is not nominal, it must be ordered.

    n : scalar
        Number of pairable values.

    n_v : ndarray, with shape (V,)
        Number of pairable elements for each value.

    Returns
    -------
    e : ndarray, with shape (V, V)
        Random coincidence matrix.


def _distances(value_domain, distance_metric, n_v):

return np.array([[distance_metric(v1, v2, i1=i1, i2=i2, n_v=n_v)<EOL>for i2, v2 in enumerate(value_domain)]<EOL>for i1, v1 in enumerate(value_domain)])<EOL>

Distances of the different possible values.

    Parameters
    ----------
    value_domain : array_like, with shape (V,)
        Possible values V the units can take.
        If the level of measurement is not nominal, it must be ordered.

    distance_metric : callable
        Callable that return the distance of two given values.

    n_v : ndarray, with shape (V,)
        Number of pairable elements for each value.

    Returns
    -------
    d : ndarray, with shape (V, V)
        Distance matrix for each value pair.


return {<EOL>'<STR_LIT>': _nominal_metric,<EOL>'<STR_LIT>': _ordinal_metric,<EOL>'<STR_LIT>': _interval_metric,<EOL>'<STR_LIT>': _ratio_metric,<EOL>}.get(level_of_measurement, level_of_measurement)<EOL>

Distance metric callable of the level of measurement.

    Parameters
    ----------
    level_of_measurement : string or callable
        Steven's level of measurement of the variable.
        It must be one of 'nominal', 'ordinal', 'interval', 'ratio' or a callable.

    Returns
    -------
    metric : callable
        Distance callable.


return list(map(list, zip(*list_of_lists)))<EOL>


return np.array([[sum(<NUM_LIT:1> for rate in unit if rate == v) for v in value_domain] for unit in reliability_data.T])<EOL>

Return the value counts given the reliability data.

    Parameters
    ----------
    reliability_data : ndarray, with shape (M, N)
        Reliability data matrix which has the rate the i coder gave to the j unit, where M is the number of raters
        and N is the unit count.
        Missing rates are represented with `np.nan`.

    value_domain : array_like, with shape (V,)
        Possible values the units can take.

    Returns
    -------
    value_counts : ndarray, with shape (N, V)
        Number of coders that assigned a certain value to a determined unit, where N is the number of units
        and V is the value count.


def alpha(reliability_data=None, value_counts=None, value_domain=None, level_of_measurement='<STR_LIT>',<EOL>dtype=np.float64):

if (reliability_data is None) == (value_counts is None):<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>if value_counts is None:<EOL><INDENT>if type(reliability_data) is not np.ndarray:<EOL><INDENT>reliability_data = np.array(reliability_data)<EOL><DEDENT>value_domain = value_domain or np.unique(reliability_data[~np.isnan(reliability_data)])<EOL>value_counts = _reliability_data_to_value_counts(reliability_data, value_domain)<EOL><DEDENT>else:  <EOL><INDENT>if value_domain:<EOL><INDENT>assert value_counts.shape[<NUM_LIT:1>] == len(value_domain),"<STR_LIT>"<EOL><DEDENT>else:<EOL><INDENT>value_domain = tuple(range(value_counts.shape[<NUM_LIT:1>]))<EOL><DEDENT><DEDENT>distance_metric = _distance_metric(level_of_measurement)<EOL>o = _coincidences(value_counts, value_domain, dtype=dtype)<EOL>n_v = np.sum(o, axis=<NUM_LIT:0>)<EOL>n = np.sum(n_v)<EOL>e = _random_coincidences(value_domain, n, n_v)<EOL>d = _distances(value_domain, distance_metric, n_v)<EOL>return <NUM_LIT:1> - np.sum(o * d) / np.sum(e * d)<EOL>

Compute Krippendorff's alpha.

    See https://en.wikipedia.org/wiki/Krippendorff%27s_alpha for more information.

    Parameters
    ----------
    reliability_data : array_like, with shape (M, N)
        Reliability data matrix which has the rate the i coder gave to the j unit, where M is the number of raters
        and N is the unit count.
        Missing rates are represented with `np.nan`.
        If it's provided then `value_counts` must not be provided.

    value_counts : ndarray, with shape (N, V)
        Number of coders that assigned a certain value to a determined unit, where N is the number of units
        and V is the value count.
        If it's provided then `reliability_data` must not be provided.

    value_domain : array_like, with shape (V,)
        Possible values the units can take.
        If the level of measurement is not nominal, it must be ordered.
        If `reliability_data` is provided, then the default value is the ordered list of unique rates that appear.
        Else, the default value is `list(range(V))`.

    level_of_measurement : string or callable
        Steven's level of measurement of the variable.
        It must be one of 'nominal', 'ordinal', 'interval', 'ratio' or a callable.

    dtype : data-type
        Result and computation data-type.

    Returns
    -------
    alpha : `dtype`
        Scalar value of Krippendorff's alpha of type `dtype`.

    Examples
    --------
    >>> reliability_data = [[np.nan, np.nan, np.nan, np.nan, np.nan, 3, 4, 1, 2, 1, 1, 3, 3, np.nan, 3],
    ...                     [1, np.nan, 2, 1, 3, 3, 4, 3, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan],
    ...                     [np.nan, np.nan, 2, 1, 3, 4, 4, np.nan, 2, 1, 1, 3, 3, np.nan, 4]]
    >>> print(round(alpha(reliability_data=reliability_data, level_of_measurement='nominal'), 6))
    0.691358
    >>> print(round(alpha(reliability_data=reliability_data, level_of_measurement='interval'), 6))
    0.810845
    >>> value_counts = np.array([[1, 0, 0, 0],
    ...                          [0, 0, 0, 0],
    ...                          [0, 2, 0, 0],
    ...                          [2, 0, 0, 0],
    ...                          [0, 0, 2, 0],
    ...                          [0, 0, 2, 1],
    ...                          [0, 0, 0, 3],
    ...                          [1, 0, 1, 0],
    ...                          [0, 2, 0, 0],
    ...                          [2, 0, 0, 0],
    ...                          [2, 0, 0, 0],
    ...                          [0, 0, 2, 0],
    ...                          [0, 0, 2, 0],
    ...                          [0, 0, 0, 0],
    ...                          [0, 0, 1, 1]])
    >>> print(round(alpha(value_counts=value_counts, level_of_measurement='nominal'), 6))
    0.691358
    >>> # The following examples were extracted from
    >>> # https://www.statisticshowto.datasciencecentral.com/wp-content/uploads/2016/07/fulltext.pdf, page 8.
    >>> reliability_data = [[1, 2, 3, 3, 2, 1, 4, 1, 2, np.nan, np.nan, np.nan],
    ...                     [1, 2, 3, 3, 2, 2, 4, 1, 2, 5, np.nan, 3.],
    ...                     [np.nan, 3, 3, 3, 2, 3, 4, 2, 2, 5, 1, np.nan],
    ...                     [1, 2, 3, 3, 2, 4, 4, 1, 2, 5, 1, np.nan]]
    >>> print(round(alpha(reliability_data, level_of_measurement='ordinal'), 3))
    0.815
    >>> print(round(alpha(reliability_data, level_of_measurement='ratio'), 3))
    0.797


global ALLGOOD<EOL>swhlab.loglevel=swhlab.loglevel_SILENT   <EOL>if verbose:<EOL><INDENT>swhlab.loglevel=swhlab.loglevel_DEBUG<EOL><DEDENT>try:<EOL><INDENT>shutil.rmtree('<STR_LIT>') <EOL><DEDENT>except:<EOL><INDENT>pass<EOL><DEDENT>try:<EOL><INDENT>os.mkdir('<STR_LIT>')<EOL><DEDENT>except:<EOL><INDENT>pass<EOL><DEDENT>if os.path.isdir('<STR_LIT>'):<EOL><INDENT>swhlab.plotting.core.IMAGE_SAVE=True<EOL>swhlab.plotting.core.IMAGE_SHOW=False        <EOL>unittest.main()<EOL>if ALLGOOD:<EOL><INDENT>return True<EOL><DEDENT>else:<EOL><INDENT>return False<EOL><DEDENT><DEDENT>else:<EOL><INDENT>print("<STR_LIT>")<EOL>return False<EOL><DEDENT>


with open(fname) as f:<EOL><INDENT>raw=f.read().split("<STR_LIT:\n>")<EOL><DEDENT>efforts=[] <EOL>for line in raw[<NUM_LIT:1>:]:<EOL><INDENT>line=line.strip().split("<STR_LIT:U+002C>")<EOL>date=datetime.datetime.strptime(line[<NUM_LIT:0>], "<STR_LIT>")<EOL>if onlyAfter and date<onlyAfter:<EOL><INDENT>continue<EOL><DEDENT>if len(line)<<NUM_LIT:3>:<EOL><INDENT>continue<EOL><DEDENT>for project in line[<NUM_LIT:2>:]:<EOL><INDENT>project=project.strip()<EOL>if len(project):<EOL><INDENT>efforts.append([date,project])<EOL><DEDENT><DEDENT><DEDENT>return efforts<EOL>

return a list of [stamp, project] elements.


modifiedTime=os.path.getmtime(fname)<EOL>stamp=time.strftime('<STR_LIT>', time.localtime(modifiedTime))<EOL>return stamp<EOL>

return "YYYY-MM-DD" when the file was modified.


with open(resultsFile) as f:<EOL><INDENT>raw=f.read().split("<STR_LIT:\n>")<EOL><DEDENT>foldersByDay={}<EOL>for line in raw:<EOL><INDENT>folder=line.split('<STR_LIT:">')[<NUM_LIT:1>]+"<STR_LIT:\\>"<EOL>line=[]+line.split('<STR_LIT:">')[<NUM_LIT:2>].split("<STR_LIT:U+002CU+0020>")<EOL>for day in line[<NUM_LIT:1>:]:<EOL><INDENT>if not day in foldersByDay:<EOL><INDENT>foldersByDay[day]=[]<EOL><DEDENT>foldersByDay[day]=foldersByDay[day]+[folder]<EOL><DEDENT><DEDENT>nActiveDays=len(foldersByDay)<EOL>dayFirst=sorted(foldersByDay.keys())[<NUM_LIT:0>]<EOL>dayLast=sorted(foldersByDay.keys())[-<NUM_LIT:1>]<EOL>dayFirst=datetime.datetime.strptime(dayFirst, "<STR_LIT>" )<EOL>dayLast=datetime.datetime.strptime(dayLast, "<STR_LIT>" )<EOL>nDays = (dayLast - dayFirst).days + <NUM_LIT:1><EOL>emptyDays=<NUM_LIT:0><EOL>for deltaDays in range(nDays):<EOL><INDENT>day=dayFirst+datetime.timedelta(days=deltaDays)<EOL>stamp=datetime.datetime.strftime(day, "<STR_LIT>" )<EOL>if not stamp in foldersByDay:<EOL><INDENT>foldersByDay[stamp]=[]<EOL>emptyDays+=<NUM_LIT:1><EOL><DEDENT><DEDENT>percActive=nActiveDays/nDays*<NUM_LIT:100><EOL>print("<STR_LIT>"%(nActiveDays,nDays,percActive))<EOL>return foldersByDay<EOL>

returns a dict of active folders with days as keys.


foldersByDay=loadResults(resultsFile)<EOL><INDENT>for day in sorted(list(foldersByDay.keys())):<EOL><INDENT>if time.strptime(day,"<STR_LIT>")<time.strptime("<STR_LIT>","<STR_LIT>"):<EOL><INDENT>del foldersByDay[day]<EOL><DEDENT><DEDENT><DEDENT>html="<STR_LIT>"<EOL>html+="<STR_LIT>"<EOL>html+="<STR_LIT>"<EOL>html+="<STR_LIT>"<EOL>html=html.replace("<STR_LIT>",(time.strftime('<STR_LIT>', time.localtime())))<EOL>html+="<STR_LIT>"*<NUM_LIT:5><EOL>html+="<STR_LIT>"<EOL>html+="<STR_LIT>"<EOL>lastMonth="<STR_LIT>"<EOL>lastYear="<STR_LIT>"<EOL>for day in sorted(list(foldersByDay.keys())):<EOL><INDENT>month=day[:<NUM_LIT:7>]<EOL>year=day[:<NUM_LIT:4>]<EOL>if year!=lastYear:<EOL><INDENT>html+="<STR_LIT>"%year<EOL>lastYear=year<EOL><DEDENT>if month!=lastMonth:<EOL><INDENT>html+="<STR_LIT>"%month<EOL>lastMonth=month<EOL><DEDENT>html+="<STR_LIT>"%(day,day[<NUM_LIT:8>:])<EOL><DEDENT>html+="<STR_LIT>"*<NUM_LIT:5><EOL>html=html.replace("<STR_LIT>","<STR_LIT>")<EOL>html+="<STR_LIT>"<EOL>html+="<STR_LIT>"<EOL>for day in sorted(list(foldersByDay.keys())):<EOL><INDENT>dt=datetime.datetime.strptime(day, "<STR_LIT>" )<EOL>classPrefix="<STR_LIT>"<EOL>if int(dt.weekday())><NUM_LIT:4>:<EOL><INDENT>classPrefix="<STR_LIT>"<EOL><DEDENT>html+="<STR_LIT>"%(day,day)<EOL>title="<STR_LIT>"%(day,DAYSOFWEEK[dt.weekday()])<EOL>html+="<STR_LIT>"%(classPrefix,title)<EOL>html+="<STR_LIT>"%(classPrefix)<EOL>for folder in foldersByDay[day]:<EOL><INDENT>if "<STR_LIT>" in folder:<EOL><INDENT>continue<EOL><DEDENT>if "<STR_LIT>" in folder:<EOL><INDENT>continue<EOL><DEDENT>if "<STR_LIT>" and "<STR_LIT>" in folder:<EOL><INDENT>continue<EOL><DEDENT>if "<STR_LIT>" in folder:<EOL><INDENT>continue<EOL><DEDENT>if "<STR_LIT>" in folder:<EOL><INDENT>continue<EOL><DEDENT>if "<STR_LIT>" in folder:<EOL><INDENT>continue<EOL><DEDENT>html+="<STR_LIT>"%folder<EOL><DEDENT>html+="<STR_LIT>"<EOL><DEDENT>fnameSave=resultsFile+"<STR_LIT>"<EOL>html=html.replace("<STR_LIT>","<STR_LIT>")<EOL>with open(fnameSave,'<STR_LIT:w>') as f:<EOL><INDENT>f.write(HTML_TEMPLATE.replace("<STR_LIT>","<STR_LIT>"+html))<EOL><DEDENT>print("<STR_LIT>",fnameSave)<EOL>

generates HTML report of active folders/days.


assert len(char)==<NUM_LIT:1> and type(char)==str, "<STR_LIT>"<EOL>assert os.path.exists(path), "<STR_LIT>"<EOL>files = sorted(os.listdir(path))<EOL>files = [x for x in files if len(x)><NUM_LIT> and x[<NUM_LIT:4>]+x[<NUM_LIT:7>]+x[<NUM_LIT:10>]=='<STR_LIT>']<EOL>for fname in files:<EOL><INDENT>fname2 = list(fname)<EOL>fname2[<NUM_LIT:11>]=char<EOL>fname2="<STR_LIT>".join(fname2)<EOL>if fname==fname2:<EOL><INDENT>print(fname, "<STR_LIT>", fname2)<EOL><DEDENT>else:<EOL><INDENT>print(fname, "<STR_LIT>", fname2)<EOL><INDENT>fname=os.path.join(path,fname)<EOL>fname2=os.path.join(path,fname2)<EOL>if not os.path.exists(fname2):<EOL><INDENT>os.rename(fname,fname2)<EOL><DEDENT><DEDENT><DEDENT><DEDENT>return<EOL>

Given ABFs and TIFs formatted long style, rename each of them to prefix their number with a different number.

Example: 2017_10_11_0011.abf
Becomes: 2017_10_11_?011.abf
where ? can be any character.


frame the current matplotlib plot with ABF info, and optionally save it.
Note that this is entirely independent of the ABFplot class object.
if saveImage is False, show it instead.

Datatype should be:
    * plot
    * experiment


Load an ABF and get ready to plot stuff.


if plt._pylab_helpers.Gcf.get_num_fig_managers()><NUM_LIT:0> and forceNew is False:<EOL><INDENT>self.log.debug("<STR_LIT>")<EOL>return<EOL><DEDENT>if self.subplot:<EOL><INDENT>self.log.debug("<STR_LIT>")<EOL><DEDENT>else:<EOL><INDENT>self.log.debug("<STR_LIT>")<EOL>plt.figure(figsize=(self.figure_width,self.figure_height))<EOL><DEDENT>


save the existing figure. does not close it.


Add comment lines/text to an existing plot. Defaults to seconds.
Call after a plot has been made, and after margins have been set.


plot every sweep of an ABF file (with comments).


def figure_sweeps(self, offsetX=<NUM_LIT:0>, offsetY=<NUM_LIT:0>):


self.log.debug("<STR_LIT>")<EOL>self.figure()<EOL>plt.plot(self.abf.protoX,self.abf.protoY,color='<STR_LIT:r>')<EOL>self.marginX=<NUM_LIT:0><EOL>self.decorate(protocol=True)<EOL>


IN=INDEX(ABFfolder)<EOL>if analyze:<EOL><INDENT>IN.analyzeAll()<EOL><DEDENT>if convert:<EOL><INDENT>IN.convertImages()<EOL><DEDENT>

Inelegant for now, but lets you manually analyze every ABF in a folder.


Reanalyze data for a single ABF. Also remakes child and parent html.


logging.basicConfig(format=swhlab.logFormat, datefmt=swhlab.logDateFormat, level=swhlab.loglevel)<EOL>self.log = logging.getLogger("<STR_LIT>")<EOL>self.log.setLevel(swhlab.loglevel)<EOL>if not type(ABFfolder) is str or not os.path.isdir(ABFfolder):<EOL><INDENT>self.log.error("<STR_LIT>",ABFfolder)<EOL>return<EOL><DEDENT>else:<EOL><INDENT>self.log.info("<STR_LIT>",ABFfolder)<EOL><DEDENT>self.folder1=os.path.abspath(ABFfolder) <EOL>self.folder2=os.path.abspath(ABFfolder+"<STR_LIT>") <EOL>if not os.path.isdir(self.folder2):<EOL><INDENT>self.log.debug("<STR_LIT>",self.folder2)<EOL>os.mkdir(self.folder2)<EOL><DEDENT>self.scan()<EOL>self.groups=cm.abfGroups(self.folder1) <EOL>self.log.debug("<STR_LIT>",len(self.groups))<EOL>nChildren=[len(x) for x in self.groups.values()]<EOL>self.log.debug("<STR_LIT>",np.average(nChildren))<EOL>self.groupFiles=cm.abfGroupFiles(self.groups,self.folder2)<EOL>nChildrenFiles=[len(x) for x in self.groupFiles.values()]<EOL>self.log.debug("<STR_LIT>",np.average(nChildrenFiles))<EOL>

The SWHLab INDEX class allows a web-browsable index of ABF data.

This is intended to allow:
  * Automatic analysis of ABF files and output of data images
  * Watching of directories and automatic analysis of new ABFs
  * Manipulation and enhancement of micrographs (even multichannel)
  * creation of individual HTML pages for ABFs, cells, and folders

General sequence:
  * convert folder1 TIFs to JPGs
  * analyze data for cells that need it
  * create their individual pages for cells that need it
  * create master index


t1=cm.timeit()<EOL>self.files1=cm.list_to_lowercase(sorted(os.listdir(self.folder1)))<EOL>self.files2=cm.list_to_lowercase(sorted(os.listdir(self.folder2)))<EOL>self.files1abf=[x for x in self.files1 if x.endswith("<STR_LIT>")]<EOL>self.files1abf=cm.list_to_lowercase(cm.abfSort(self.files1abf))<EOL>self.IDs=[x[:-<NUM_LIT:4>] for x in self.files1abf]<EOL>self.log.debug("<STR_LIT>",len(self.files1))<EOL>self.log.debug("<STR_LIT>",len(self.files1abf))<EOL>self.log.debug("<STR_LIT>",len(self.files2))<EOL>self.log.debug("<STR_LIT>",cm.timeit(t1))<EOL>

scan folder1 and folder2 into files1 and files2.
since we are on windows, simplify things by making them all lowercase.
this WILL cause problems on 'nix operating systems.If this is the case,
just run a script to rename every file to all lowercase.


<EOL>exts=['<STR_LIT>','<STR_LIT>']<EOL>for fname in [x for x in self.files1 if cm.ext(x) in exts]:<EOL><INDENT>ID="<STR_LIT>"<EOL>if len(fname)><NUM_LIT:8> and fname[:<NUM_LIT:8>] in self.IDs:<EOL><INDENT>ID=fname[:<NUM_LIT:8>]<EOL><DEDENT>fname2=ID+"<STR_LIT>"+fname<EOL>if not fname2 in self.files2:<EOL><INDENT>self.log.info("<STR_LIT>"%fname2)<EOL>shutil.copy(os.path.join(self.folder1,fname),os.path.join(self.folder2,fname2))<EOL><DEDENT>if not fname[:<NUM_LIT:8>]+"<STR_LIT>" in self.files1:<EOL><INDENT>self.log.error("<STR_LIT>",fname)<EOL><DEDENT><DEDENT>exts=['<STR_LIT>','<STR_LIT>']<EOL>for fname in [x for x in self.files1 if cm.ext(x) in exts]:<EOL><INDENT>ID="<STR_LIT>"<EOL>if len(fname)><NUM_LIT:8> and fname[:<NUM_LIT:8>] in self.IDs:<EOL><INDENT>ID=fname[:<NUM_LIT:8>]<EOL><DEDENT>fname2=ID+"<STR_LIT>"+fname+"<STR_LIT>"<EOL>if not fname2 in self.files2:<EOL><INDENT>self.log.info("<STR_LIT>"%fname2)<EOL>imaging.TIF_to_jpg(os.path.join(self.folder1,fname),saveAs=os.path.join(self.folder2,fname2))<EOL><DEDENT>if not fname[:<NUM_LIT:8>]+"<STR_LIT>" in self.files1:<EOL><INDENT>self.log.error("<STR_LIT>",fname)<EOL><DEDENT><DEDENT>

run this to turn all folder1 TIFs and JPGs into folder2 data.
TIFs will be treated as micrographs and converted to JPG with enhanced
contrast. JPGs will simply be copied over.


analyze every unanalyzed ABF in the folder.


Analye a single ABF: make data, index it.
If called directly, will delete all ID_data_ and recreate it.


if os.path.splitext(fname)[<NUM_LIT:1>].lower() in ['<STR_LIT>','<STR_LIT>']:<EOL><INDENT>html='<STR_LIT>'%(fname,fname)<EOL>if "<STR_LIT>" in fname:<EOL><INDENT>html=html.replace('<STR_LIT>','<STR_LIT>')<EOL><DEDENT>if "<STR_LIT>" in fname:<EOL><INDENT>html=html.replace('<STR_LIT>','<STR_LIT>')<EOL><DEDENT>if "<STR_LIT>" in fname:<EOL><INDENT>html=html.replace('<STR_LIT>','<STR_LIT>')<EOL><DEDENT><DEDENT>elif os.path.splitext(fname)[<NUM_LIT:1>].lower() in ['<STR_LIT>','<STR_LIT>']:<EOL><INDENT>html='<STR_LIT>'%fname<EOL><DEDENT>else:<EOL><INDENT>html='<STR_LIT>'%fname<EOL><DEDENT>return html<EOL>

return appropriate HTML determined by file extension.


if type(abfID) is str:<EOL><INDENT>abfID=[abfID]<EOL><DEDENT>for thisABFid in cm.abfSort(abfID):<EOL><INDENT>parentID=cm.parent(self.groups,thisABFid)<EOL>saveAs=os.path.abspath("<STR_LIT>"%(self.folder2,parentID))<EOL>if overwrite is False and os.path.basename(saveAs) in self.files2:<EOL><INDENT>continue<EOL><DEDENT>filesByType=cm.filesByType(self.groupFiles[parentID])<EOL>html="<STR_LIT>"<EOL>html+='<STR_LIT>'<EOL>html+='<STR_LIT>'%parentID<EOL>html+='<STR_LIT>'%os.path.abspath(self.folder1+"<STR_LIT:/>"+parentID+"<STR_LIT>")<EOL>html+='<STR_LIT>'<EOL>catOrder=["<STR_LIT>","<STR_LIT>","<STR_LIT>","<STR_LIT>"]<EOL>categories=cm.list_order_by(filesByType.keys(),catOrder)<EOL>for category in [x for x in categories if len(filesByType[x])]:<EOL><INDENT>if category=='<STR_LIT>':<EOL><INDENT>html+="<STR_LIT>"<EOL><DEDENT>elif category=='<STR_LIT>':<EOL><INDENT>html+="<STR_LIT>"<EOL><DEDENT>elif category=='<STR_LIT>':<EOL><INDENT>html+="<STR_LIT>"<EOL><DEDENT>elif category=='<STR_LIT>':<EOL><INDENT>html+="<STR_LIT>"<EOL><DEDENT>else:<EOL><INDENT>html+="<STR_LIT>"<EOL><DEDENT>for fname in filesByType[category]:<EOL><INDENT>html+=self.htmlFor(fname)<EOL><DEDENT>html+='<STR_LIT>'*<NUM_LIT:3><EOL><DEDENT>print("<STR_LIT>",saveAs,'<STR_LIT>')<EOL>style.save(html,saveAs,launch=launch)<EOL><DEDENT>

generate a generic flat file html for an ABF parent. You could give
this a single ABF ID, its parent ID, or a list of ABF IDs.
If a child ABF is given, the parent will automatically be used.


if type(abfID) is str:<EOL><INDENT>abfID=[abfID]<EOL><DEDENT>for thisABFid in cm.abfSort(abfID):<EOL><INDENT>parentID=cm.parent(self.groups,thisABFid)<EOL>saveAs=os.path.abspath("<STR_LIT>"%(self.folder2,parentID))<EOL>if overwrite is False and os.path.basename(saveAs) in self.files2:<EOL><INDENT>continue<EOL><DEDENT>filesByType=cm.filesByType(self.groupFiles[parentID])<EOL>html="<STR_LIT>"<EOL>html+='<STR_LIT>'<EOL>html+='<STR_LIT>'%parentID<EOL>html+='<STR_LIT>'%os.path.abspath(self.folder1+"<STR_LIT:/>"+parentID+"<STR_LIT>")<EOL>html+='<STR_LIT>'<EOL>for fname in filesByType['<STR_LIT>']:<EOL><INDENT>html+=self.htmlFor(fname)<EOL><DEDENT>print("<STR_LIT>",saveAs,'<STR_LIT>')<EOL>style.save(html,saveAs,launch=launch)<EOL><DEDENT>

create ID_plot.html of just intrinsic properties.


byExt={"<STR_LIT>":[],"<STR_LIT>":[],"<STR_LIT>":[]} <EOL>for fname in fnames:<EOL><INDENT>ext = os.path.splitext(fname)[<NUM_LIT:1>].replace("<STR_LIT:.>",'<STR_LIT>').lower()<EOL>if not ext in byExt.keys():<EOL><INDENT>byExt[ext]=[]<EOL><DEDENT>byExt[ext]=byExt[ext]+[fname]<EOL><DEDENT>return byExt<EOL>

given a list of files, return a dict organized by extension.


IDs=[]<EOL>filesByExt = filesByExtension(fnames)<EOL>for abfFname in filesByExt['<STR_LIT>']:<EOL><INDENT>ID=os.path.splitext(abfFname)[<NUM_LIT:0>]<EOL>for picFname in filesByExt['<STR_LIT>']+filesByExt['<STR_LIT>']:<EOL><INDENT>if picFname.startswith(ID):<EOL><INDENT>IDs.append(ID)<EOL>break<EOL><DEDENT><DEDENT><DEDENT>return smartSort(IDs)<EOL>

given a list of files, return a list of cells by their ID.
A cell is indicated when an ABF name matches the start of another file.

Example:
    123456.abf
    123456-whatever.tif


byCell={}<EOL>fnames=smartSort(fnames)<EOL>days = list(set([elem[:<NUM_LIT:5>] for elem in fnames if elem.endswith("<STR_LIT>")])) <EOL>for day in smartSort(days):<EOL><INDENT>parent=None<EOL>for i,fname in enumerate([elem for elem in fnames if elem.startswith(day) and elem.endswith("<STR_LIT>")]):<EOL><INDENT>ID=os.path.splitext(fname)[<NUM_LIT:0>]<EOL>if len([x for x in fnames if x.startswith(ID)])-<NUM_LIT:1>:<EOL><INDENT>parent=ID<EOL><DEDENT>if not parent in byCell:<EOL><INDENT>byCell[parent]=[]<EOL><DEDENT>byCell[parent]=byCell[parent]+[fname]<EOL><DEDENT><DEDENT>return byCell<EOL>

given files and cells, return a dict of files grouped by cell.


self.log = logging.getLogger("<STR_LIT>")<EOL>self.log.setLevel(loglevel)<EOL>if not os.path.isdir(abfFolder):<EOL><INDENT>self.log.error("<STR_LIT>",abfFolder)<EOL><DEDENT>else:<EOL><INDENT>self.folderScan(abfFolder)<EOL><DEDENT>

This class allows indexing of ABFs in directories.

Cell organization:
    Experiments are intended to place all their ABFs in the same
    directory, with a new cell designated by a file ending in .TIF
    matching the same name of a file ending in .abf.

Naming convension:
    abfFolder (./) has the ABFs
        fnames - all the files in this folder
        abfnames - all the abf files in this folder
        cells - all the cell IDs
    abfFolder2 (./swhlab/) has data generated by these scripts
        fnames2 - all the files in this folder

Notes:
    the term ID is used to define the name of a cell as the filename
    of its first abf without the abf extension. i.e., 16o01009


if abfFolder is None and '<STR_LIT>' in dir(self):<EOL><INDENT>abfFolder=self.abfFolder<EOL><DEDENT>else:<EOL><INDENT>self.abfFolder=abfFolder<EOL><DEDENT>self.abfFolder=os.path.abspath(self.abfFolder)<EOL>self.log.info("<STR_LIT>",self.abfFolder)<EOL>if not os.path.exists(self.abfFolder):<EOL><INDENT>self.log.error("<STR_LIT>",abfFolder)<EOL>return<EOL><DEDENT>self.abfFolder2=os.path.abspath(self.abfFolder+"<STR_LIT>")<EOL>if not os.path.exists(self.abfFolder2):<EOL><INDENT>self.log.error("<STR_LIT>")            <EOL>os.mkdir(self.abfFolder2)<EOL><DEDENT>self.fnames=os.listdir(self.abfFolder)<EOL>self.fnames2=os.listdir(self.abfFolder2)<EOL>self.log.debug("<STR_LIT>",len(self.fnames))<EOL>self.log.debug("<STR_LIT>",len(self.fnames2))<EOL>self.fnamesByExt = filesByExtension(self.fnames)<EOL>if not "<STR_LIT>" in self.fnamesByExt.keys():<EOL><INDENT>self.log.error("<STR_LIT>")<EOL><DEDENT>self.log.debug("<STR_LIT>",len(self.fnamesByExt["<STR_LIT>"]))<EOL>self.cells=findCells(self.fnames) <EOL>self.log.debug("<STR_LIT>"%len(self.cells))<EOL>self.fnamesByCell = filesByCell(self.fnames,self.cells) <EOL>self.log.debug("<STR_LIT>"%str([len(self.fnamesByCell[elem]) for elem in self.fnamesByCell]))<EOL>

populate class properties relating to files in the folder.


self.makePics() <EOL>html='<STR_LIT>'%os.path.basename(self.abfFolder)<EOL>for ID in smartSort(self.fnamesByCell.keys()):<EOL><INDENT>link='<STR_LIT>'<EOL>if ID+"<STR_LIT>" in self.fnames2:<EOL><INDENT>link='<STR_LIT>'%ID<EOL><DEDENT>html+=('<STR_LIT>'%(link,ID)) <EOL>if showChildren:<EOL><INDENT>for fname in self.fnamesByCell[ID]:<EOL><INDENT>thisID=os.path.splitext(fname)[<NUM_LIT:0>]<EOL>files2=[x for x in self.fnames2 if x.startswith(thisID) and not x.endswith("<STR_LIT>")]<EOL>html+='<STR_LIT>'%thisID <EOL>if len(files2):<EOL><INDENT>html+='<STR_LIT>'%len(files2) <EOL><DEDENT>html+='<STR_LIT>'<EOL><DEDENT>html+="<STR_LIT>"<EOL><DEDENT><DEDENT>style.save(html,self.abfFolder2+"<STR_LIT>")<EOL>self.html_index_splash() <EOL>style.frames(self.abfFolder2+"<STR_LIT>",launch=launch)<EOL>

generate list of cells with links. keep this simple.
automatically generates splash page and regnerates frames.


html="""<STR_LIT>"""%version.__version__<EOL>for parent in smartSort(self.fnamesByCell.keys()):<EOL><INDENT>html+='<STR_LIT>'%(parent,parent)<EOL>for child in self.fnamesByCell[parent]:<EOL><INDENT>fullpath=os.path.join(self.abfFolder,child)<EOL>protocol = swhlab.swh_abf.abfProtocol(fullpath)<EOL>html+='<STR_LIT>'%(fullpath,protocol)<EOL><DEDENT><DEDENT>style.save(html,self.abfFolder2+"<STR_LIT>")<EOL>return<EOL>


if not ID in self.cells:<EOL><INDENT>self.log.error("<STR_LIT>",ID)<EOL>return<EOL><DEDENT>htmlFname=os.path.abspath(self.abfFolder2+"<STR_LIT:/>"+ID+"<STR_LIT>")<EOL>html="<STR_LIT>"%ID<EOL>npics=<NUM_LIT:0><EOL>for childID in [os.path.splitext(x)[<NUM_LIT:0>] for x in self.fnamesByCell[ID]]:<EOL><INDENT>pics=[x for x in self.fnames2 if x.startswith(childID) and os.path.splitext(x)[<NUM_LIT:1>].lower() in ["<STR_LIT>","<STR_LIT>"]]<EOL>html+="<STR_LIT>"%(os.path.abspath(self.abfFolder+'<STR_LIT:/>'+childID+"<STR_LIT>"))<EOL>for i,pic in enumerate(pics):<EOL><INDENT>html+='<STR_LIT>'%(pic,pic)<EOL>npics+=<NUM_LIT:1><EOL><DEDENT>html+="<STR_LIT>"<EOL><DEDENT>style.save(html,htmlFname)<EOL>self.log.info("<STR_LIT>",htmlFname,npics)<EOL>

generate ./swhlab/xxyxxzzz.html for a single given abf.
Input can be an ABF file path of ABF ID.


return<EOL>

Single page generator designed for easy gruop comparisons.


for fname in smartSort(self.cells):<EOL><INDENT>if template=="<STR_LIT>":<EOL><INDENT>self.html_single_fixed(fname)<EOL><DEDENT>else:<EOL><INDENT>self.html_single_basic(fname)<EOL><DEDENT><DEDENT>

generate a data view for every ABF in the project folder.


rescanNeeded=False<EOL>for fname in smartSort(self.fnames):<EOL><INDENT>if fname in self.fnames2:<EOL><INDENT>continue<EOL><DEDENT>ext=os.path.splitext(fname)[<NUM_LIT:1>].lower()<EOL>if ext in ["<STR_LIT>","<STR_LIT>"]:<EOL><INDENT>if not fname in self.abfFolder2:<EOL><INDENT>self.log.debug("<STR_LIT>",fname)<EOL>shutil.copy(os.path.join(self.abfFolder,fname),os.path.join(self.abfFolder2,fname))<EOL>rescanNeeded=True<EOL><DEDENT><DEDENT>if ext in ["<STR_LIT>","<STR_LIT>"]:<EOL><INDENT>if not fname+"<STR_LIT>" in self.fnames2:<EOL><INDENT>self.log.debug("<STR_LIT>",fname)<EOL>swhlab.swh_image.TIF_to_jpg(os.path.join(self.abfFolder,fname),saveAs=os.path.join(self.abfFolder2,fname+"<STR_LIT>"))<EOL>rescanNeeded=True<EOL><DEDENT><DEDENT><DEDENT>if rescanNeeded:<EOL><INDENT>self.log.debug("<STR_LIT>")<EOL>self.log.debug("<STR_LIT>")<EOL>self.folderScan()<EOL><DEDENT>

convert every .image we find to a ./swhlab/ image


html="""<STR_LIT>"""%(menuWidth)<EOL>with open(fname,'<STR_LIT:w>') as f:<EOL><INDENT>f.write(html)<EOL><DEDENT>if launch:<EOL><INDENT>webbrowser.open(fname)<EOL><DEDENT>

create and save a two column frames HTML file.


html=html_top+html+html_bot<EOL>html=html.replace("<STR_LIT>",swhlab.common.datetimeToString())<EOL>if fname is None:<EOL><INDENT>fname = tempfile.gettempdir()+"<STR_LIT>"<EOL>launch=True<EOL><DEDENT>fname=os.path.abspath(fname)<EOL>with open(fname,'<STR_LIT:w>') as f:<EOL><INDENT>f.write(html)<EOL><DEDENT>global stylesheetSaved<EOL>stylesheetPath=os.path.join(os.path.dirname(fname),"<STR_LIT>")<EOL>if not os.path.exists(stylesheetPath) or stylesheetSaved is False:<EOL><INDENT>with open(stylesheetPath,'<STR_LIT:w>') as f:<EOL><INDENT>f.write(stylesheet)<EOL>stylesheetSaved=True<EOL><DEDENT><DEDENT>if launch:<EOL><INDENT>webbrowser.open(fname)<EOL><DEDENT>

wrap HTML in a top and bottom (with css) and save to disk.


def TIF_to_jpg(fnameTiff, overwrite=False, saveAs="<STR_LIT>"):

given a TIF taken by our cameras, make it a pretty labeled JPG.

if the filename contains "f10" or "f20", add appropraite scale bars.

automatic contrast adjustment is different depending on if its a DIC
image or fluorescent image (which is detected automatically).


for fname in sorted(glob.glob(path+"<STR_LIT>")):<EOL><INDENT>print(fname)<EOL>TIF_to_jpg(fname)<EOL><DEDENT>

run TIF_to_jpg() on every TIF of a folder.


check out the arguments and figure out what to do.


Is=np.where(data>threshold)[<NUM_LIT:0>]<EOL>Is=np.concatenate(([<NUM_LIT:0>],Is))<EOL>Ds=Is[:-<NUM_LIT:1>]-Is[<NUM_LIT:1>:]+<NUM_LIT:1><EOL>return Is[np.where(Ds)[<NUM_LIT:0>]+<NUM_LIT:1>]<EOL>

return a list of Is where the data first crosses above threshold.


def kernel_gaussian(size=<NUM_LIT:100>, sigma=None, forwardOnly=False):

return a 1d gassuan array of a given size and sigma.
If sigma isn't given, it will be 1/10 of the size, which is usually good.
Note that this is fully numpy, and doesn't use scipy.


if filterSize is None:<EOL><INDENT>filterSize=len(data)/<NUM_LIT:10><EOL><DEDENT>kernel=kernel_gaussian(size=filterSize)<EOL>data=convolve(data,kernel) <EOL>return data<EOL>

minimal complexity low-pass filtering.
Filter size is how "wide" the filter will be.
Sigma will be 1/10 of this filter width.
If filter size isn't given, it will be 1/10 of the data size.


This applies a kernel to a signal through convolution and returns the result.

Some magic is done at the edges so the result doesn't apprach zero:
    1. extend the signal's edges with len(kernel)/2 duplicated values
    2. perform the convolution ('same' mode)
    3. slice-off the ends we added
    4. return the same number of points as the original


while sec:<EOL><INDENT>print("<STR_LIT>",sec,"<STR_LIT>")<EOL>sec-=<NUM_LIT:1><EOL>time.sleep(<NUM_LIT:1>)<EOL><DEDENT>

wait a given number of seconds until returning.


halt everything until user input. Use this sparingly.


exc_type, exc_obj, exc_tb = sys.exc_info()<EOL>s="<STR_LIT>"<EOL>s+="<STR_LIT>"%os.path.split(exc_tb.tb_frame.f_code.co_filename)[<NUM_LIT:1>]<EOL>s+="<STR_LIT>"%exc_tb.tb_lineno<EOL>s+="<STR_LIT>"%exc_type<EOL>return s<EOL>

when you "except Exception as e", give me the e and I'll give you a string.


try:<EOL><INDENT>if str(__IPYTHON__):<EOL><INDENT>return True<EOL><DEDENT><DEDENT>except:<EOL><INDENT>return False<EOL><DEDENT>

returns True if running in an Ipython interpreter.


if timer is None:<EOL><INDENT>return time.time()<EOL><DEDENT>else:<EOL><INDENT>took=time.time()-timer<EOL>if took<<NUM_LIT:1>:<EOL><INDENT>return "<STR_LIT>"%(took*<NUM_LIT>)<EOL><DEDENT>elif took<<NUM_LIT>:<EOL><INDENT>return "<STR_LIT>"%(took)<EOL><DEDENT>else:<EOL><INDENT>return "<STR_LIT>"%(took/<NUM_LIT>)<EOL><DEDENT><DEDENT>

simple timer. returns a time object, or a string.


l=list(l)<EOL>if value in l:<EOL><INDENT>l.remove(value)<EOL>l.insert(<NUM_LIT:0>,value)<EOL><DEDENT>return l<EOL>

if the value is in the list, move it to the front and return it.


l=list(l)<EOL>if value in l:<EOL><INDENT>l.remove(value)<EOL>l.append(value)<EOL><DEDENT>return l<EOL>

if the value is in the list, move it to the back and return it.


l=list(l)<EOL>for item in firstItems[::-<NUM_LIT:1>]: <EOL><INDENT>if item in l:<EOL><INDENT>l.remove(item)<EOL>l.insert(<NUM_LIT:0>,item)<EOL><DEDENT><DEDENT>return l<EOL>

given a list and a list of items to be first, return the list in the
    same order except that it begins with each of the first items.


return [x.lower() for x in l if type(x) is str]<EOL>

given a list of strings, make them all lowercase.


if "<STR_LIT:.>" in fname:<EOL><INDENT>return os.path.splitext(fname)[<NUM_LIT:1>]<EOL><DEDENT>return fname<EOL>


IDs=list(IDs)<EOL>monO=[]<EOL>monN=[]<EOL>monD=[]<EOL>good=[]<EOL>for ID in IDs:<EOL><INDENT>if ID is None:<EOL><INDENT>continue<EOL><DEDENT>if '<STR_LIT:o>' in ID:<EOL><INDENT>monO.append(ID)<EOL><DEDENT>elif '<STR_LIT:n>' in ID:<EOL><INDENT>monN.append(ID)<EOL><DEDENT>elif '<STR_LIT:d>' in ID:<EOL><INDENT>monD.append(ID)<EOL><DEDENT>else:<EOL><INDENT>good.append(ID)<EOL><DEDENT><DEDENT>return sorted(good)+sorted(monO)+sorted(monN)+sorted(monD)<EOL>

given a list of goofy ABF names, return it sorted intelligently.
This places things like 16o01001 after 16901001.


<EOL>files=False<EOL>if type(abfFolder) is str and os.path.isdir(abfFolder):<EOL><INDENT>files=abfSort(os.listdir(abfFolder))<EOL><DEDENT>elif type(abfFolder) is list:<EOL><INDENT>files=abfSort(abfFolder)<EOL><DEDENT>assert type(files) is list<EOL>files=list_to_lowercase(files)<EOL>abfs, IDs, others, parents, days = [],[],[],[],[]<EOL>for fname in files:<EOL><INDENT>if fname.endswith("<STR_LIT>"):<EOL><INDENT>abfs.append(fname)<EOL>IDs.append(fname[:-<NUM_LIT:4>])<EOL>days.append(fname[:<NUM_LIT:5>])<EOL><DEDENT>else:<EOL><INDENT>others.append(fname)<EOL><DEDENT><DEDENT>for ID in IDs:<EOL><INDENT>for fname in others:<EOL><INDENT>if fname.startswith(ID):<EOL><INDENT>parents.append(ID)<EOL><DEDENT><DEDENT><DEDENT>parents=abfSort(set(parents)) <EOL>days=abfSort(set(days)) <EOL>groups={}<EOL>for day in days:<EOL><INDENT>parent=None<EOL>for fname in [x for x in abfs if x.startswith(day)]:<EOL><INDENT>ID=fname[:-<NUM_LIT:4>]<EOL>if ID in parents:<EOL><INDENT>parent=ID<EOL><DEDENT>if not parent in groups.keys():<EOL><INDENT>groups[parent]=[]<EOL><DEDENT>groups[parent].extend([ID])<EOL><DEDENT><DEDENT>return groups<EOL>

Given a folder path or list of files, return groups (dict) by cell.

Rules which define parents (cells):
    * assume each cell has one or several ABFs
    * that cell can be labeled by its "ID" or "parent" ABF (first abf)
    * the ID is just the filename of the first abf without .abf
    * if any file starts with an "ID", that ID becomes a parent.
    * examples could be 16o14044.TIF or 16o14044-cell1-stuff.jpg
    * usually this is done by saving a pic of the cell with same filename

Returns a dict of "parent IDs" representing the "children"
    groups["16o14041"] = ["16o14041","16o14042","16o14043"]

From there, getting children files is trivial. Just find all files in
the same folder whose filenames begin with one of the children.


assert os.path.exists(folder)<EOL>files=os.listdir(folder)<EOL>group2={}<EOL>for parent in groups.keys():<EOL><INDENT>if not parent in group2.keys():<EOL><INDENT>group2[parent]=[]<EOL><DEDENT>for ID in groups[parent]:<EOL><INDENT>for fname in [x.lower() for x in files if ID in x.lower()]:<EOL><INDENT>group2[parent].extend([fname])<EOL><DEDENT><DEDENT><DEDENT>return group2<EOL>

when given a dictionary where every key contains a list of IDs, replace
the keys with the list of files matching those IDs. This is how you get a
list of files belonging to each child for each parent.


if ID in groups.keys():<EOL><INDENT>return ID <EOL><DEDENT>if not ID in groups.keys():<EOL><INDENT>for actualParent in groups.keys():<EOL><INDENT>if ID in groups[actualParent]:<EOL><INDENT>return actualParent <EOL><DEDENT><DEDENT><DEDENT>return None<EOL>

given a groups dictionary and an ID, return its actual parent ID.


features=["<STR_LIT>","<STR_LIT>","<STR_LIT:data>","<STR_LIT>","<STR_LIT>"]<EOL>files={}<EOL>for feature in features:<EOL><INDENT>files[feature]=[]<EOL><DEDENT>for fname in fileList:<EOL><INDENT>other=True<EOL>for feature in features:<EOL><INDENT>if "<STR_LIT:_>"+feature+"<STR_LIT:_>" in fname:<EOL><INDENT>files[feature].extend([fname])<EOL>other=False<EOL><DEDENT><DEDENT>if other:<EOL><INDENT>files['<STR_LIT>'].extend([fname])<EOL><DEDENT><DEDENT>return files<EOL>

given a list of files, return them as a dict sorted by type:
    * plot, tif, data, other


<EOL>path=os.path.expanduser("<STR_LIT>")+"<STR_LIT>" <EOL>if not os.path.exists(path):<EOL><INDENT>print("<STR_LIT>",path)<EOL>os.mkdir(path)<EOL><DEDENT>return os.path.abspath(path)<EOL>


fname=userFolder()+"<STR_LIT>"<EOL>if os.path.exists(fname):<EOL><INDENT>abfFname=open(fname).read().strip()<EOL>if os.path.exists(abfFname) or abfFname.endswith("<STR_LIT>"):<EOL><INDENT>return abfFname<EOL><DEDENT><DEDENT>return os.path.abspath(os.sep)<EOL>


fname=userFolder()+"<STR_LIT>"<EOL>with open(fname,'<STR_LIT:w>') as f:<EOL><INDENT>f.write(os.path.abspath(abfFname))<EOL><DEDENT>return<EOL>


import tkinter as tk<EOL>from tkinter import filedialog<EOL>root = tk.Tk() <EOL>root.withdraw() <EOL>root.wm_attributes('<STR_LIT>', <NUM_LIT:1>) <EOL>fname = filedialog.askopenfilename(title = "<STR_LIT>",<EOL>filetypes=[('<STR_LIT>', '<STR_LIT>')],<EOL>initialdir=os.path.dirname(abfFname_Load()))<EOL>if fname.endswith("<STR_LIT>"):<EOL><INDENT>abfFname_Save(fname)<EOL>return fname<EOL><DEDENT>else:<EOL><INDENT>print("<STR_LIT>")<EOL>return None<EOL><DEDENT>

Launch an ABF file selection file dialog.
This is smart, and remembers (through reboots) where you last were.


import tkinter as tk<EOL>from tkinter import filedialog<EOL>root = tk.Tk() <EOL>root.withdraw() <EOL>root.wm_attributes('<STR_LIT>', <NUM_LIT:1>) <EOL>fname = filedialog.askdirectory(title = "<STR_LIT>",<EOL>initialdir=os.path.dirname(abfFname_Load()))<EOL>if len(fname)><NUM_LIT:3>:<EOL><INDENT>abfFname_Save(fname+"<STR_LIT>")<EOL>return fname<EOL><DEDENT>else:<EOL><INDENT>print("<STR_LIT>")<EOL>return None<EOL><DEDENT>

Launch a folder selection dialog.
This is smart, and remembers (through reboots) where you last were.


if not '<STR_LIT>' in swhlab.__file__:<EOL><INDENT>print("<STR_LIT>",<EOL>os.path.dirname(swhlab.__file__))<EOL>return <EOL><DEDENT>while len(tryPath)><NUM_LIT:5>:<EOL><INDENT>sp=tryPath+"<STR_LIT>" <EOL>if os.path.isdir(sp) and os.path.exists(sp+"<STR_LIT>"):<EOL><INDENT>if not os.path.dirname(tryPath) in sys.path:<EOL><INDENT>sys.path.insert(<NUM_LIT:0>,os.path.dirname(tryPath))<EOL><DEDENT>print("<STR_LIT:#>"*<NUM_LIT>)<EOL>print("<STR_LIT>")<EOL>print("<STR_LIT:#>"*<NUM_LIT>)<EOL><DEDENT>tryPath=os.path.dirname(tryPath)<EOL><DEDENT>return<EOL>

if the module is in this path, load it from the local folder.


fname=os.path.abspath(fname)<EOL>basename=os.path.basename(fname)<EOL>return os.path.splitext(basename)[<NUM_LIT:0>]<EOL>

given a filename, return the ABFs ID string.


f=open(fname,'<STR_LIT:rb>')<EOL>raw=f.read(<NUM_LIT:30>*<NUM_LIT:1000>) <EOL>f.close()<EOL>raw=raw.decode("<STR_LIT:utf-8>","<STR_LIT:ignore>")<EOL>raw=raw.split("<STR_LIT>")[<NUM_LIT:1>].split("<STR_LIT>")[<NUM_LIT:0>]<EOL>protocol = os.path.basename(raw) <EOL>protocolID = protocol.split("<STR_LIT:U+0020>")[<NUM_LIT:0>] <EOL>return protocolID<EOL>

Determine the protocol used to record an ABF file


given the bytestring ABF header, make and launch HTML.


def __init__(self, fname, createFolder=False):

logging.basicConfig(format=swhlab.logFormat, datefmt=swhlab.logDateFormat, level=swhlab.loglevel)<EOL>self.log = logging.getLogger("<STR_LIT>")<EOL>self.log.setLevel(swhlab.loglevel)<EOL>if "<STR_LIT>" in str(fname):<EOL><INDENT>self.log.debug("<STR_LIT>")<EOL>for item in sorted(dir(fname)):<EOL><INDENT>try:<EOL><INDENT>setattr(self,item,getattr(fname,item))<EOL><DEDENT>except:<EOL><INDENT>pass<EOL><DEDENT><DEDENT>return<EOL><DEDENT>self.log.debug("<STR_LIT:_>"*<NUM_LIT>)<EOL>self.log.info("<STR_LIT>",swhlab.__version__,str(fname))<EOL>if not os.path.exists(str(fname)):<EOL><INDENT>self.log.error("<STR_LIT>")<EOL>return<EOL><DEDENT>self.ABFreader = io.AxonIO(filename=fname)<EOL>self.ABFblock = self.ABFreader.read_block(lazy=False, cascade=True)<EOL>self.header=self.ABFreader.read_header()<EOL>self.protocomment=abfProtocol(fname) <EOL>self.ID=abfIDfromFname(fname) <EOL>self.filename=os.path.abspath(fname) <EOL>self.fileID=os.path.abspath(os.path.splitext(self.filename)[<NUM_LIT:0>]) <EOL>self.outFolder=os.path.abspath(os.path.dirname(fname)+"<STR_LIT>") <EOL>self.outPre=os.path.join(self.outFolder,self.ID)+'<STR_LIT:_>' <EOL>self.sweeps=self.ABFblock.size["<STR_LIT>"] <EOL>self.timestamp=self.ABFblock.rec_datetime <EOL>self.holding = self.header['<STR_LIT>'][<NUM_LIT:0>]['<STR_LIT>'] <EOL>self.derivative=False <EOL>self.setsweep() <EOL>self.comments_load() <EOL>self.kernel=None <EOL>if createFolder:<EOL><INDENT>self.output_touch() <EOL><DEDENT>self.log.debug("<STR_LIT>"%self.protocomment)<EOL>

Load an ABF and makes its stats and sweeps easily available.

Arguments:
    fname - filename of an ABF object
    createFolder - if True, the ./swhlab/ folder will be created


def setsweep(self, sweep=<NUM_LIT:0>, channel=<NUM_LIT:0>):

try:<EOL><INDENT>sweep=int(sweep)<EOL><DEDENT>except:<EOL><INDENT>self.log.error("<STR_LIT>",sweep)<EOL>return<EOL><DEDENT>if sweep<<NUM_LIT:0>:<EOL><INDENT>sweep=self.sweeps-<NUM_LIT:1>-sweep <EOL><DEDENT>sweep=max(<NUM_LIT:0>,min(sweep,self.sweeps-<NUM_LIT:1>)) <EOL>if '<STR_LIT>' in dir(self) and self.sweep == sweep and self.derivative is False:<EOL><INDENT>self.log.debug("<STR_LIT>",sweep)<EOL>return<EOL><DEDENT>self.channels=self.ABFblock.segments[sweep].size["<STR_LIT>"]<EOL>if self.channels><NUM_LIT:1> and sweep==<NUM_LIT:0>:<EOL><INDENT>self.log.info("<STR_LIT>") <EOL><DEDENT>self.trace = self.ABFblock.segments[sweep].analogsignals[channel]<EOL>self.sweep=sweep <EOL>self.channel=channel <EOL>self.rate = int(self.trace.sampling_rate) <EOL>self.period = float(<NUM_LIT:1>/self.rate) <EOL>self.pointsPerSec = int(self.rate) <EOL>self.pointsPerMs = int(self.rate/<NUM_LIT>) <EOL>self.sweepSize = len(self.trace) <EOL>self.sweepInterval = self.trace.duration.magnitude <EOL>self.sweepLength = float(self.trace.t_stop-self.trace.t_start) <EOL>self.length = self.sweepLength*self.sweeps <EOL>self.lengthMinutes = self.length/<NUM_LIT> <EOL>if str(self.trace.dimensionality) == '<STR_LIT>':<EOL><INDENT>self.units,self.units2="<STR_LIT>","<STR_LIT>"<EOL>self.unitsD,self.unitsD2="<STR_LIT>","<STR_LIT>"<EOL>self.protoUnits,self.protoUnits2="<STR_LIT>","<STR_LIT>"<EOL><DEDENT>elif str(self.trace.dimensionality) == '<STR_LIT>':<EOL><INDENT>self.units,self.units2="<STR_LIT>","<STR_LIT>"<EOL>self.unitsD,self.unitsD2="<STR_LIT>","<STR_LIT>"<EOL>self.protoUnits,self.protoUnits2="<STR_LIT>","<STR_LIT>"<EOL><DEDENT>else:<EOL><INDENT>self.units,self.units2="<STR_LIT:?>","<STR_LIT>"<EOL>self.unitsD,self.unitsD2="<STR_LIT:?>","<STR_LIT>"<EOL><DEDENT>self.sweepY = self.trace.magnitude <EOL>self.sweepT = self.trace.times.magnitude <EOL>self.sweepStart = float(self.trace.t_start) <EOL>self.sweepX2 = self.sweepT-self.trace.t_start.magnitude <EOL>self.sweepX = self.sweepX2+sweep*self.sweepInterval <EOL>if self.derivative:<EOL><INDENT>self.log.debug("<STR_LIT>")<EOL>self.sweepD=self.sweepY[<NUM_LIT:1>:]-self.sweepY[:-<NUM_LIT:1>] <EOL>self.sweepD=np.insert(self.sweepD,<NUM_LIT:0>,self.sweepD[<NUM_LIT:0>]) <EOL>self.sweepD/=(self.period*<NUM_LIT:1000>) <EOL><DEDENT>else:<EOL><INDENT>self.sweepD=[<NUM_LIT:0>] <EOL><DEDENT>self.generate_protocol()<EOL>

set the sweep and channel of an ABF. Both start at 0.


return range(self.sweeps)<EOL>


for sweep in range(self.sweeps):<EOL><INDENT>self.setsweep(sweep)<EOL>yield self.sweep<EOL><DEDENT>


self.comment_times,self.comment_sweeps,self.comment_tags=[],[],[]<EOL>self.comments=<NUM_LIT:0> <EOL>self.comment_text="<STR_LIT>"<EOL>try:<EOL><INDENT>self.comment_tags = list(self.ABFblock.segments[<NUM_LIT:0>].eventarrays[<NUM_LIT:0>].annotations['<STR_LIT>'])<EOL>self.comment_times = list(self.ABFblock.segments[<NUM_LIT:0>].eventarrays[<NUM_LIT:0>].times/self.trace.itemsize)<EOL>self.comment_sweeps = list(self.comment_times)<EOL><DEDENT>except:<EOL><INDENT>for events in self.ABFblock.segments[<NUM_LIT:0>].events: <EOL><INDENT>self.comment_tags = events.annotations['<STR_LIT>'].tolist()<EOL>self.comment_times = np.array(events.times.magnitude/self.trace.itemsize)<EOL>self.comment_sweeps = self.comment_times/self.sweepInterval<EOL><DEDENT><DEDENT>for i,c in enumerate(self.comment_tags):<EOL><INDENT>self.comment_tags[i]=c.decode("<STR_LIT:utf-8>")<EOL><DEDENT>

read the header and populate self with information about comments


Recreate the command stimulus (protocol) for the current sweep.
It's not stored point by point (that's a waste of time and memory!)
Instead it's stored as a few (x,y) points which can be easily graphed.

TODO: THIS
for segment in abf.ABFreader.read_protocol():
    for analogsignal in segment.analogsignals:
        print(analogsignal)
        plt.plot(analogsignal)
        plt.show()
        plt.close('all')


self.setsweep(sweep)<EOL>return list(self.protoX),list(self.protoY)<EOL>

given a sweep, return the protocol as [Xs,Ys].
This is good for plotting/recreating the protocol trace.
There may be duplicate numbers.


self.setsweep(sweep)<EOL>return list(self.protoSeqX),list(self.protoSeqY)<EOL>

given a sweep, return the protocol as condensed sequence.
This is better for comparing similarities and determining steps.
There should be no duplicate numbers.


print("<STR_LIT>") <EOL>return <NUM_LIT:0><EOL>

return an array of command values at a time point (in sec).
Useful for things like generating I/V curves.


alternative to the existing abf protocol stuff
return the start/stop time of an epoch.
Epoch start at zero.
A=0, B=1, C=2, D=3, ...


if setsweep:<EOL><INDENT>self.setsweep(setsweep)<EOL><DEDENT>if t2 is None or t2>self.sweepLength:<EOL><INDENT>t2=self.sweepLength<EOL>self.log.debug("<STR_LIT>",t2)<EOL><DEDENT>t1=max(t1,<NUM_LIT:0>)<EOL>if t1>t2:<EOL><INDENT>self.log.error("<STR_LIT>")<EOL>return False<EOL><DEDENT>I1,I2=int(t1*self.pointsPerSec),int(t2*self.pointsPerSec)<EOL>if I1==I2:<EOL><INDENT>return np.nan<EOL><DEDENT>return np.average(self.sweepY[I1:I2])<EOL>

return the average of part of the current sweep.


if sweepLast is None:<EOL><INDENT>sweepLast=self.sweeps-<NUM_LIT:1><EOL><DEDENT>nSweeps=sweepLast-sweepFirst+<NUM_LIT:1><EOL>runningSum=np.zeros(len(self.sweepY))<EOL>self.log.debug("<STR_LIT>",sweepFirst,sweepLast)<EOL>for sweep in np.arange(nSweeps)+sweepFirst:<EOL><INDENT>self.setsweep(sweep)<EOL>runningSum+=self.sweepY.flatten()<EOL><DEDENT>average=runningSum/nSweeps<EOL>return average<EOL>

Return a sweep which is the average of multiple sweeps.
For now, standard deviation is lost.


def kernel_gaussian(self, sizeMS, sigmaMS=None, forwardOnly=False):

sigmaMS=sizeMS/<NUM_LIT:10> if sigmaMS is None else sigmaMS<EOL>size,sigma=sizeMS*self.pointsPerMs,sigmaMS*self.pointsPerMs<EOL>self.kernel=swhlab.common.kernel_gaussian(size,sigma,forwardOnly)<EOL>return self.kernel<EOL>


assert self.kernel is not None<EOL>return swhlab.common.convolve(self.sweepY,self.kernel)<EOL>

Get the filtered sweepY of the current sweep.
Only works if self.kernel has been generated.


return self.sweepY-self.sweepYfiltered()<EOL>

return the sweep with sweepYfiltered subtracted from it.


<EOL>m1=<NUM_LIT:0> if m1 is None else self.pointsPerSec*m1<EOL>m2=-<NUM_LIT:1> if m2 is None else self.pointsPerSec*m2<EOL>Y=self.sweepYsmartbase()[int(m1):int(m2)]<EOL>nBins=<NUM_LIT:1000><EOL>hist,bins=np.histogram(Y,bins=nBins,range=[-biggestEvent,biggestEvent],density=True)<EOL>histSmooth=swhlab.common.lowpass(hist)<EOL>peakI=np.where(histSmooth==max(histSmooth))[<NUM_LIT:0>][<NUM_LIT:0>]<EOL>hist=np.roll(hist,int(nBins/<NUM_LIT:2>-peakI))<EOL>histSmooth=np.roll(histSmooth,int(nBins/<NUM_LIT:2>-peakI))<EOL>downward,upward=np.split(histSmooth,<NUM_LIT:2>)<EOL>downward=downward[::-<NUM_LIT:1>]<EOL>diff=np.sum(upward-downward)<EOL>diff=diff/(len(Y)/self.pointsPerSec)<EOL>return diff<EOL>

Calculates the net difference between positive/negative phasic events
Returns return the phasic difference value of the current sweep.

Arguments:
    biggestEvent (int): the size of the largest event anticipated
    m1 (int, optional): the time (sec) to start analyzing
    m2 (int, optional): the time (sec) to end analyzing

Example:
    abf=swhlab.ABF(abfFile)
    abf.kernel=abf.kernel_gaussian(sizeMS=500) # kernel for smart baseline
    diff=[]
    for sweep in abf.setsweeps():
        print("Sweep",sweep)
        diff.append(analyzeSweep(abf,plot=True,label="sweep %d"%sweep))
    print(diff)


if not os.path.exists(self.outFolder):<EOL><INDENT>self.log.debug("<STR_LIT>",self.outFolder)<EOL>os.mkdir(self.outFolder)<EOL><DEDENT>


for fname in glob.glob(self.outPre+"<STR_LIT:*>"):<EOL><INDENT>print("<STR_LIT>",fname)<EOL><DEDENT>pass<EOL>

delete all ./swhlab/ data related to this ABF.


Generate HTML containing information about NeoIO objects.
This is useful when trying to figure out how to extract data from ABFs.


abf=ABF(theABF)<EOL>abf.log.info("<STR_LIT>")<EOL>ap=AP(abf)<EOL>ap.detect()<EOL>abf.derivative=True<EOL>plt.figure(figsize=(SQUARESIZE,SQUARESIZE))<EOL>ax1=plt.subplot(<NUM_LIT>)<EOL>plt.ylabel(abf.units2)<EOL>ax2=plt.subplot(<NUM_LIT>,sharey=ax1)<EOL>ax3=plt.subplot(<NUM_LIT>)<EOL>plt.ylabel(abf.unitsD2)<EOL>ax4=plt.subplot(<NUM_LIT>,sharey=ax3)<EOL>for sweep in range(abf.sweeps):<EOL><INDENT>abf.setsweep(sweep)<EOL>ax1.plot(abf.sweepX,abf.sweepY,color='<STR_LIT:b>',lw=<NUM_LIT>)<EOL>ax2.plot(abf.sweepX,abf.sweepY,color='<STR_LIT:b>')<EOL>ax3.plot(abf.sweepX,abf.sweepD,color='<STR_LIT:r>',lw=<NUM_LIT>)<EOL>ax4.plot(abf.sweepX,abf.sweepD,color='<STR_LIT:r>')<EOL><DEDENT>for ax in [ax1,ax2,ax3,ax4]: <EOL><INDENT>ax.margins(<NUM_LIT:0>,<NUM_LIT>)<EOL>ax.grid(alpha=<NUM_LIT>)<EOL><DEDENT>for ax in [ax3,ax4]: <EOL><INDENT>ax.axhline(-<NUM_LIT:100>,color='<STR_LIT:r>',alpha=<NUM_LIT>,ls="<STR_LIT>",lw=<NUM_LIT:2>)<EOL><DEDENT>for ax in [ax2,ax4]: <EOL><INDENT>ax.get_yaxis().set_visible(False)<EOL><DEDENT>if len(ap.APs):<EOL><INDENT>firstAP=ap.APs[<NUM_LIT:0>]["<STR_LIT:T>"]<EOL>ax2.axis([firstAP-<NUM_LIT>,firstAP+<NUM_LIT>,None,None])<EOL>ax4.axis([firstAP-<NUM_LIT>,firstAP+<NUM_LIT>,None,None])<EOL><DEDENT>if len(ap.APs):<EOL><INDENT>firstAP=ap.APs[<NUM_LIT:0>]<EOL>msg="<STR_LIT:\n>".join(["<STR_LIT>"%(x,str(firstAP[x])) for x in sorted(firstAP.keys()) if not "<STR_LIT:I>" in x[-<NUM_LIT:2>:]])<EOL>plt.subplot(<NUM_LIT>)<EOL>plt.gca().text(<NUM_LIT>, <NUM_LIT>, msg, transform= plt.gca().transAxes, fontsize=<NUM_LIT:10>, verticalalignment='<STR_LIT>', family='<STR_LIT>')<EOL><DEDENT>plt.tight_layout()<EOL>frameAndSave(abf,"<STR_LIT>")<EOL>plt.close('<STR_LIT:all>')<EOL>

protocol: IC ramp for AP shape analysis.


protocol: gain function of some sort. step size and start at are pA.


abf=ABF(theABF)<EOL>abf.log.info("<STR_LIT>")<EOL>ap=AP(abf)<EOL>avgVoltagePerSweep = [];<EOL>times = []<EOL>for sweep in abf.setsweeps():<EOL><INDENT>avgVoltagePerSweep.append(abf.average(<NUM_LIT:0>,<NUM_LIT:3>))<EOL>times.append(abf.sweepStart/<NUM_LIT>)<EOL><DEDENT>M1,M2=<NUM_LIT>,<NUM_LIT><EOL>ap.detect_time1, ap.detect_time2 = M1,M2<EOL>ap.detect()<EOL>apsPerSweepCos=[len(x) for x in ap.get_bySweep()]<EOL>M1,M2=<NUM_LIT:0>,<NUM_LIT:10><EOL>ap.detect_time1, ap.detect_time2 = M1,M2<EOL>ap.detect()<EOL>apsPerSweepRamp=[len(x) for x in ap.get_bySweep()]<EOL>plt.figure(figsize=(<NUM_LIT:8>,<NUM_LIT:8>))<EOL>plt.subplot(<NUM_LIT>)<EOL>plt.grid(ls='<STR_LIT>',alpha=<NUM_LIT>)<EOL>plt.plot(times,avgVoltagePerSweep,'<STR_LIT>')<EOL>plt.ylabel("<STR_LIT>")<EOL>comment_lines(abf)<EOL>plt.subplot(<NUM_LIT>)<EOL>plt.grid(ls='<STR_LIT>',alpha=<NUM_LIT>)<EOL>plt.plot(times,apsPerSweepCos,'<STR_LIT>')<EOL>plt.ylabel("<STR_LIT>")<EOL>comment_lines(abf)<EOL>plt.subplot(<NUM_LIT>)<EOL>plt.grid(ls='<STR_LIT>',alpha=<NUM_LIT>)<EOL>plt.plot(times,apsPerSweepRamp,'<STR_LIT>')<EOL>plt.ylabel("<STR_LIT>")<EOL>comment_lines(abf)<EOL>plt.tight_layout()<EOL>frameAndSave(abf,"<STR_LIT>")<EOL>plt.close('<STR_LIT:all>')<EOL>


experiment: generic VC time course experiment.