<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import flatten from 'lodash/flatten';
import sortBy from 'lodash/sortBy';
import groupBy from 'lodash/groupBy';
import omit from 'lodash/omit';
import Fuse from 'fuse.js';

// Components
import Tabs from 'components/ui/Tabs';
import Tag from 'components/ui/Tag';
import Icon from 'components/ui/Icon';

import CheckboxGroup from 'components/form/CheckboxGroup';

class SearchComponent extends React.Component {
  static propTypes = {
    open: PropTypes.bool,
    list: PropTypes.array,
    options: PropTypes.object,
    selected: PropTypes.object,
    tab: PropTypes.string,
    search: PropTypes.string,

    // CALLBACKS
    onChangeOpen: PropTypes.func,
    onChangeTab: PropTypes.func,
    onChangeSearch: PropTypes.func,
    onToggleSelected: PropTypes.func,
    onChangeSelected: PropTypes.func,
    onResetSelected: PropTypes.func
  };

  constructor(props) {
    super(props);

    const { list } = props;

    this.fuse = new Fuse(list, {
      keys: [{
        name: 'label',
        weight: 0.6
      }, {
        name: 'synonyms',
        weight: 0.3
      }, {
        name: 'id',
        weight: 0.1
      }],
      threshold: 0.2,
      minMatchCharLength: 2
    });
  }

  state = {
    index: 0,
    value: '',
    filteredList: [],
    groupedFilteredList: {}
  }

  // UI EVENTS:
  // - onScreenClick
  // - onScreenKeyup
  // - onToggleOpen
  // - onKeyArrow
  // - onChangeTab
  // - onChangeSearch
  onScreenClick = (e) => {
    const el = document.querySelector('.c-dataset-search');
    const clickOutside = el && el.contains && !el.contains(e.target);

    if (clickOutside) {
      this.onToggleOpen(false);
    }
  }

  onScreenKeyup = (e) => {
    switch (e.keyCode) {
      case 27:
        this.onToggleOpen(false);
        break;

      // ENTER
      case 13:
        this.onKeyEnter();
        break;

      // ARROWS
      case 38:
        this.onKeyArrow('up');
        break;

      case 40:
        this.onKeyArrow('down');
        break;

      default:
        return true;
    }
  }

  onToggleOpen = (to) => {
    requestAnimationFrame(() => {
      if (to) {
        window.addEventListener('click', this.onScreenClick);
        window.addEventListener('keyup', this.onScreenKeyup);
      } else {
        window.removeEventListener('click', this.onScreenClick);
        window.removeEventListener('keyup', this.onScreenKeyup);
        this.setState({
          index: 0,
          value: '',
          filteredList: [],
          groupedFilteredList: {}
        });
        if (this.input) this.input.blur();
      }
    });

    this.props.onChangeOpen(to);
  }

  onKeyArrow = (direction) => {
    const { index, filteredList } = this.state;
    if (direction === 'up') {
      this.setState({
        index: (index !== 0) ? index - 1 : filteredList.length
      });
    }

    if (direction === 'down') {
      this.setState({
        index: (index !== filteredList.length) ? index + 1 : 0
      });
    }
  }

  onKeyEnter = () => {
    const tabs = this.getTabs();
    const { value, index, groupedFilteredList } = this.state;

    if (index === 0) {
      this.props.onChangeSearch(value);
    }

    if (index !== 0) {
      const filteredList = flatten(Object.keys(groupedFilteredList).map(g =>
        groupedFilteredList[g]));

      const tag = filteredList[index - 1];
      const tab = (tabs.find((t) => {
        const labels = (tag && tag.labels) || [];
        return t.type === labels[1];
      }) || {}).value || 'custom';

      this.props.onToggleSelected({
        tag,
        tab
      });
    }

    this.onToggleOpen(false);
  }

  onListItemMouseOver = (index) => {
    this.setState({ index });
  }

  onChangeTab = (t) => {
    const { tab } = this.props;
    if (t === tab) {
      this.onToggleOpen(false);
    } else {
      this.props.onChangeTab(t);
    }
  }

  onChangeSearch = (e) => {
    const { value } = e.currentTarget;

    const filteredList = (value.length > 2) ? sortBy(this.fuse.search(value), 'label') : [];

    this.setState({
      index: 0,
      value,
      filteredList,
      groupedFilteredList: omit(groupBy(filteredList, (l) => {
        const group = l.labels && l.labels[1];
        return group || 'undefined';
      }), ['undefined', 'GEOGRAPHY'])
    });
  }

  // HELPERS
  getTabs = () => {
    const {
      options, selected
    } = this.props;

    return Object
      .keys(options)
      .filter((o) => {
        if (o === 'custom') {
          return selected.custom.length;
        }
        return o !== 'custom';
      })
      .map(o => ({
        label: options[o].label,
        value: options[o].value,
        type: options[o].type,
        ...selected[o].length && { number: selected[o].length }
      }));
  }

  render() {
    const { open, search, options, selected, tab, list } = this.props;
    const { index, value, groupedFilteredList } = this.state;

    let groupedFilteredListIndex = 0;

    const tabs = this.getTabs();

    const mainArr = options[tab].list;
    const secondaryArr = selected[tab]
      .filter(s => !options[tab].list.find(l => l.id === s))
      .map(s => list.find(l => l.id === s));

    const selectedAllArr = flatten(Object.keys(selected).map(s =>
      selected[s].map((c) => {
        const result = list.find(o => o.id === c) ||
          mainArr.find(a => a.id === c);
        return { ...result, tab: s };
      })));

    return (

        {/* Search */}

          <button
            className={classnames({
              'search-icon': true,
              '-search': true
            })}
          >
            <Icon name="icon-search" className="-small" />
          </button>

          <input
            ref={(c) => { this.input = c; }}
            className={classnames({
              'search-input': true,
              '-open': open
            })}
            type="search"
            placeholder="Search and filter datasets"
            value={value}
            onClick={() => this.onToggleOpen(true)}
            onChange={this.onChangeSearch}
          />

          <button
            className={classnames({
              'search-icon': true,
              '-arrow': true,
              '-open': open
            })}
            onClick={() => this.onToggleOpen(!open)}
          >
            <Icon name="icon-arrow-down-2" className="-small" />
          </button>

        {/* Dropdown */}
        {open && !value &&

            <Tabs
              className="-dark -no-margin"
              options={tabs}
              defaultSelected={tab}
              selected={tab}
              onChange={this.onChangeTab}
            />

              {!!mainArr.length &&
                <CheckboxGroup
                  name="mainArr"
                  selected={selected[tab]}
                  className="mainArr-checkbox-group"
                  options={sortBy(mainArr.map(o => ({ value: o.id, label: o.label })), 'label')}
                  onChange={s => this.props.onChangeSelected(s)}
                />
              }

              {!!secondaryArr.length &&
                <CheckboxGroup
                  name="secondaryArr"
                  selected={selected[tab]}
                  className="secondaryArr-checkbox-group"
                  options={sortBy(secondaryArr.map(o => ({ value: o.id, label: o.label })), 'label')}
                  onChange={s => this.props.onChangeSelected(s)}
                />
              }

        }

        {/* Dropdown search */}
        {open && value &&

Search by text:

                    <button
                      type="button"
                      className={classnames({
                        '-active': index === 0
                      })}
                      onClick={() => this.props.onChangeSearch(value)}
                      onMouseOver={() => this.onListItemMouseOver(0)}
                    >
                      {value}
                    </button>

              {Object.keys(groupedFilteredList).map(g => (

                  {!!g && g.toLowerCase &&

Filter by {g.toLowerCase()}:

                  }

                    {groupedFilteredList[g].map((l) => {
                      const currentIndex = ++groupedFilteredListIndex;

                      return (

                          <button
                            type="button"
                            className={classnames({
                              '-active': index === currentIndex
                            })}
                            onClick={() => {
                              this.props.onToggleSelected({
                                tag: l,
                                tab: (tabs.find(t => t.type === l.labels[1]) || {}).value || 'custom'
                              });

                              this.onToggleOpen(false);
                            }}
                            onMouseOver={() => this.onListItemMouseOver(currentIndex)}
                          >
                            {l.label}
                          </button>

                      );
                    })}

              ))}

        }

        {/* Selected */}
        {!open && (!!selectedAllArr.length || !!search) &&

              {!!search &&
                <Tag
                  key="clear-search"
                  name={`Text: ${search}`}
                  className="-tertiary"
                  isRemovable
                  onClick={() => this.props.onChangeSearch('')}
                />
              }

              {selectedAllArr.map(s => (
                <Tag
                  key={s.id}
                  name={s.label}
                  className="-secondary"
                  isRemovable
                  onClick={() => this.props.onToggleSelected({ tag: s, tab: s.tab })}
                />
              ))}

              <Tag
                key="clear-filters"
                name="Clear filters"
                className="-primary"
                onClick={() => this.props.onResetSelected()}
              />

        }

    );
  }
}

export default SearchComponent;
<commit_msg>Switch order ot appearance of results on the Explore Search. Filters go first now.<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import flatten from 'lodash/flatten';
import sortBy from 'lodash/sortBy';
import groupBy from 'lodash/groupBy';
import omit from 'lodash/omit';
import Fuse from 'fuse.js';

// Components
import Tabs from 'components/ui/Tabs';
import Tag from 'components/ui/Tag';
import Icon from 'components/ui/Icon';

import CheckboxGroup from 'components/form/CheckboxGroup';

class SearchComponent extends React.Component {
  static propTypes = {
    open: PropTypes.bool,
    list: PropTypes.array,
    options: PropTypes.object,
    selected: PropTypes.object,
    tab: PropTypes.string,
    search: PropTypes.string,

    // CALLBACKS
    onChangeOpen: PropTypes.func,
    onChangeTab: PropTypes.func,
    onChangeSearch: PropTypes.func,
    onToggleSelected: PropTypes.func,
    onChangeSelected: PropTypes.func,
    onResetSelected: PropTypes.func
  };

  constructor(props) {
    super(props);

    const { list } = props;

    this.fuse = new Fuse(list, {
      keys: [{
        name: 'label',
        weight: 0.6
      }, {
        name: 'synonyms',
        weight: 0.3
      }, {
        name: 'id',
        weight: 0.1
      }],
      threshold: 0.2,
      minMatchCharLength: 2
    });
  }

  state = {
    index: 0,
    value: '',
    filteredList: [],
    groupedFilteredList: {}
  }

  // UI EVENTS:
  // - onScreenClick
  // - onScreenKeyup
  // - onToggleOpen
  // - onKeyArrow
  // - onChangeTab
  // - onChangeSearch
  onScreenClick = (e) => {
    const el = document.querySelector('.c-dataset-search');
    const clickOutside = el && el.contains && !el.contains(e.target);

    if (clickOutside) {
      this.onToggleOpen(false);
    }
  }

  onScreenKeyup = (e) => {
    switch (e.keyCode) {
      case 27:
        this.onToggleOpen(false);
        break;

      // ENTER
      case 13:
        this.onKeyEnter();
        break;

      // ARROWS
      case 38:
        this.onKeyArrow('up');
        break;

      case 40:
        this.onKeyArrow('down');
        break;

      default:
        return true;
    }
  }

  onToggleOpen = (to) => {
    requestAnimationFrame(() => {
      if (to) {
        window.addEventListener('click', this.onScreenClick);
        window.addEventListener('keyup', this.onScreenKeyup);
      } else {
        window.removeEventListener('click', this.onScreenClick);
        window.removeEventListener('keyup', this.onScreenKeyup);
        this.setState({
          index: 0,
          value: '',
          filteredList: [],
          groupedFilteredList: {}
        });
        if (this.input) this.input.blur();
      }
    });

    this.props.onChangeOpen(to);
  }

  onKeyArrow = (direction) => {
    const { index, filteredList } = this.state;
    if (direction === 'up') {
      this.setState({
        index: (index !== 0) ? index - 1 : filteredList.length
      });
    }

    if (direction === 'down') {
      this.setState({
        index: (index !== filteredList.length) ? index + 1 : 0
      });
    }
  }

  onKeyEnter = () => {
    const tabs = this.getTabs();
    const { value, index, groupedFilteredList } = this.state;

    if (index === 0) {
      this.props.onChangeSearch(value);
    }

    if (index !== 0) {
      const filteredList = flatten(Object.keys(groupedFilteredList).map(g =>
        groupedFilteredList[g]));

      const tag = filteredList[index - 1];
      const tab = (tabs.find((t) => {
        const labels = (tag && tag.labels) || [];
        return t.type === labels[1];
      }) || {}).value || 'custom';

      this.props.onToggleSelected({
        tag,
        tab
      });
    }

    this.onToggleOpen(false);
  }

  onListItemMouseOver = (index) => {
    this.setState({ index });
  }

  onChangeTab = (t) => {
    const { tab } = this.props;
    if (t === tab) {
      this.onToggleOpen(false);
    } else {
      this.props.onChangeTab(t);
    }
  }

  onChangeSearch = (e) => {
    const { value } = e.currentTarget;

    const filteredList = (value.length > 2) ? sortBy(this.fuse.search(value), 'label') : [];
    const newGroupFilteredList = omit(groupBy(filteredList, (l) => {
      const group = l.labels && l.labels[1];
      return group || 'undefined';
    }), ['undefined', 'GEOGRAPHY']);
    this.setState({
      index: Object.keys(newGroupFilteredList).length > 0 ? 1 : 0,
      value,
      filteredList,
      groupedFilteredList: newGroupFilteredList
    });
  }

  // HELPERS
  getTabs = () => {
    const {
      options, selected
    } = this.props;

    return Object
      .keys(options)
      .filter((o) => {
        if (o === 'custom') {
          return selected.custom.length;
        }
        return o !== 'custom';
      })
      .map(o => ({
        label: options[o].label,
        value: options[o].value,
        type: options[o].type,
        ...selected[o].length && { number: selected[o].length }
      }));
  }

  render() {
    const { open, search, options, selected, tab, list } = this.props;
    const { index, value, groupedFilteredList } = this.state;
    let groupedFilteredListIndex = 0;

    const tabs = this.getTabs();

    const mainArr = options[tab].list;
    const secondaryArr = selected[tab]
      .filter(s => !options[tab].list.find(l => l.id === s))
      .map(s => list.find(l => l.id === s));

    const selectedAllArr = flatten(Object.keys(selected).map(s =>
      selected[s].map((c) => {
        const result = list.find(o => o.id === c) ||
          mainArr.find(a => a.id === c);
        return { ...result, tab: s };
      })));

    return (

        {/* Search */}

          <button
            className={classnames({
              'search-icon': true,
              '-search': true
            })}
          >
            <Icon name="icon-search" className="-small" />
          </button>

          <input
            ref={(c) => { this.input = c; }}
            className={classnames({
              'search-input': true,
              '-open': open
            })}
            type="search"
            placeholder="Search and filter datasets"
            value={value}
            onClick={() => this.onToggleOpen(true)}
            onChange={this.onChangeSearch}
          />

          <button
            className={classnames({
              'search-icon': true,
              '-arrow': true,
              '-open': open
            })}
            onClick={() => this.onToggleOpen(!open)}
          >
            <Icon name="icon-arrow-down-2" className="-small" />
          </button>

        {/* Dropdown */}
        {open && !value &&

            <Tabs
              className="-dark -no-margin"
              options={tabs}
              defaultSelected={tab}
              selected={tab}
              onChange={this.onChangeTab}
            />

              {!!mainArr.length &&
                <CheckboxGroup
                  name="mainArr"
                  selected={selected[tab]}
                  className="mainArr-checkbox-group"
                  options={sortBy(mainArr.map(o => ({ value: o.id, label: o.label })), 'label')}
                  onChange={s => this.props.onChangeSelected(s)}
                />
              }

              {!!secondaryArr.length &&
                <CheckboxGroup
                  name="secondaryArr"
                  selected={selected[tab]}
                  className="secondaryArr-checkbox-group"
                  options={sortBy(secondaryArr.map(o => ({ value: o.id, label: o.label })), 'label')}
                  onChange={s => this.props.onChangeSelected(s)}
                />
              }

        }

        {/* Dropdown search */}
        {open && value &&

              {Object.keys(groupedFilteredList).map(g => (

                  {!!g && g.toLowerCase &&

Filter by {g.toLowerCase()}:

                  }

                    {groupedFilteredList[g].map((l) => {
                      const currentIndex = ++groupedFilteredListIndex;

                      return (

                          <button
                            type="button"
                            className={classnames({
                              '-active': index === 1 && currentIndex === 1
                            })}
                            onClick={() => {
                              this.props.onToggleSelected({
                                tag: l,
                                tab: (tabs.find(t => t.type === l.labels[1]) || {}).value || 'custom'
                              });

                              this.onToggleOpen(false);
                            }}
                            onMouseOver={() => this.onListItemMouseOver(currentIndex)}
                          >
                            {l.label}
                          </button>

                      );
                    })}

              ))}

Search by text:

                    <button
                      type="button"
                      className={classnames({
                        '-active': index === 0
                      })}
                      onClick={() => this.props.onChangeSearch(value)}
                      onMouseOver={() => this.onListItemMouseOver(0)}
                    >
                      {value}
                    </button>

        }

        {/* Selected */}
        {!open && (!!selectedAllArr.length || !!search) &&

              {!!search &&
                <Tag
                  key="clear-search"
                  name={`Text: ${search}`}
                  className="-tertiary"
                  isRemovable
                  onClick={() => this.props.onChangeSearch('')}
                />
              }

              {selectedAllArr.map(s => (
                <Tag
                  key={s.id}
                  name={s.label}
                  className="-secondary"
                  isRemovable
                  onClick={() => this.props.onToggleSelected({ tag: s, tab: s.tab })}
                />
              ))}

              <Tag
                key="clear-filters"
                name="Clear filters"
                className="-primary"
                onClick={() => this.props.onResetSelected()}
              />

        }

    );
  }
}

export default SearchComponent;
<|endoftext|>


<commit_before><commit_msg>Fix flyout/workspace ordering<commit_after><|endoftext|>


<commit_before>export { ConvBiasActivation };

import * as FloatValue from "../../Unpacker/FloatValue.js";
import * as ValueDesc from "../../Unpacker/ValueDesc.js";
import { InputsOutputs } from "./BoundsArraySet_InputsOutputs.js";

/**
 * Element value bounds (per channel) for every operation's result of a convolution-bias-activation. The main purpose is to find out the
 * activationEscaping_ScaleArraySet so that it can be used to let channel escape from activation function's non-linear effect.
 *
 *   - Only input0 is used. The input1 always is undefined.
 *   - Only outputChannelCount0 is used. The outputChannelCount1 always is undefined.
 *
 * @member {FloatValue.BoundsArray} afterUndoPreviousActivationEscaping
 *   The element value bounds (per channel) after applying the previousConvBiasActivation.BoundsArraySet.ActivationEscaping.undo
 * to this.input0. (i.e. beforeFilter)
 *
 * @member {FloatValue.BoundsArray} afterFilter
 *   The element value bounds (per channel) after applying the convolution filters to this.afterUndoPreviousActivationEscaping.
 * (i.e. beforeBias)
 *
 * @member {FloatValue.BoundsArray} afterBias
 *   The element value bounds (per channel) after applying the convolution biases to this.afterFilter. (i.e. beforeActivationEscaping)
 *
 * @member {FloatValue.BoundsArray} afterActivationEscaping
 *   The element value bounds (per channel) after applying this.activationEscaping_ScaleArraySet.do to this.afterBias. (i.e. beforeActivation)
 *
 * @member {FloatValue.BoundsArray} afterActivation
 *   The element value bounds (per channel) after applying activation function to this.afterActivationEscaping. It is just
 * the this.output0.boundsArray (without this.output0.scaleArraySet).
 *
 * @member {boolean[]} bPassThrough
 *   If true for a output channel, the output channel should be arranged to pass-through from input to output.
 *
 * @see InputsOutputs
 */
class ConvBiasActivation extends InputsOutputs {

  /**
   *   - The .input0 will be set as input0.
   *   - The .afterUndoPreviousActivationEscaping will be set according to  input0 and input0.scaleArraySet.undo.scales.
   *
   * Difference from (parent class) InputsOutputs:
   *   - Only input0 (always no input1), because convolution (no matter pointwise or depthwise) could handle one input tensor.
   *   - Only output0 (always no output1), because convolution (no matter pointwise or depthwise) always generate one output tensor.
   *
   */
  constructor( input0, outputChannelCount0 ) {
    super( input0, undefined, outputChannelCount0, undefined ); // .input0 and .output0

    this.afterUndoPreviousActivationEscaping = new FloatValue.BoundsArray( input0.length ); // channel count same as input0.

    this.afterFilter = new FloatValue.BoundsArray( outputChannelCount0 );
    this.afterBias = new FloatValue.BoundsArray( outputChannelCount0 );
    this.afterActivationEscaping = new FloatValue.BoundsArray( outputChannelCount0 );

    this.bPassThrough = new Array( outputChannelCount0 );

    this.set_afterUndoPreviousActivationEscaping_by_input0_undoScales();
  }

  /**
   * Set .afterUndoPreviousActivationEscaping as .input0 multiplying .input0.scaleArraySet.undo.scales.
   *
   * @return {ConvBiasActivation}
   *   Return this (modified) object.
   */
  set_afterUndoPreviousActivationEscaping_by_input0_undoScales() {
    this.afterUndoPreviousActivationEscaping
      .set_all_byBoundsArray( this.input0.boundsArray )
      .multiply_all_byNs( this.input0.scaleArraySet.undo.scales );
    return this;
  }

  /**
   * @return {ConvBiasActivation}
   *   Return a newly created ConvBiasActivation which is a copy of this ConvBiasActivation. The this.inputs will just past
   * to new ConvBiasActivation (i.e. NOT copied). But the other data members will be copied.
   */
  clone() {
    let result = new ConvBiasActivation( this.input0, this.outputChannelCount0 );
    result.set_all_byBoundsArraySet( this );
    return result;
  }

  /**
   * Set:
   *   - this.bPassThrough[] to false (i.e. all are not pass-through).
   *
   * @return {ConvBiasActivation}
   *   Return this (modified) object.
   */
  set_bPassThrough_all_none() {
    this.bPassThrough.fill( false );
    return this;
  }

  /**
   * Set:
   *   - this.activationEscaping_ScaleArraySet to scale 1 (i.e. all are no scale).
   *   - this.bPassThrough[] to false (i.e. all are not pass-through).
   *
   * @return {ConvBiasActivation}
   *   Return this (modified) object.
   */
  set_activationEscaping_bPassThrough_all_none() {
    super.set_activationEscaping_all_none();
    this.set_bPassThrough_all_none();
    return this;
  }

  /**
   * @param {FloatValue.Bounds} aBounds
   *   Set all outputs related BoundsArray (.afterFilter, .afterBias, .afterActivationEscaping, .output0.boundsArray
   * (i.e. .afterActivation), .bPassThrough) to the same as the specified aBounds. Set the this.output0.scaleArraySet
   * to default ( 1 ). The .input0 are not modified.
   *
   * @return {ConvBiasActivation}
   *   Return this (modified) object.
   */
  set_outputs_all_byBounds( aBounds ) {
    this.afterFilter.set_all_byBounds( aBounds );
    this.afterBias.set_all_byBounds( aBounds );
    this.afterActivationEscaping.set_all_byBounds( aBounds );
    super.set_outputs_all_byBounds( aBounds ); // i.e. .output0.boundsArray (i.e. .afterActivation), .output0.scaleArraySet
    this.set_bPassThrough_all_none();
    return this;
  }

  /**
   * @param {BoundsArraySet.ConvBiasActivation} aBoundsArraySet
   *   The BoundsArraySet to be copied. The .inputs will just be referenced (NOT copied). But the other data members will be copied.
   *
   * @return {ConvBiasActivation}
   *   Return this (modified) object which is copied from aBoundsArraySet.
   */
  set_all_byBoundsArraySet( aBoundsArraySet ) {

    // inputs. Non-copy. Just reference to the same inputs.
    {
      this.input0 = aBoundsArraySet.input0;

      if ( aBoundsArraySet.input1 )
        this.input1 = aBoundsArraySet.input1;
      else
        delete this.input1;
    }

    this.afterUndoPreviousActivationEscaping.set_all_byBoundsArray( aBoundsArraySet.afterUndoPreviousActivationEscaping );
    this.afterFilter                        .set_all_byBoundsArray( aBoundsArraySet.afterFilter );
    this.afterBias                          .set_all_byBoundsArray( aBoundsArraySet.afterBias );
    this.afterActivationEscaping            .set_all_byBoundsArray( aBoundsArraySet.afterActivationEscaping );

    // .output0.boundsArray (i.e. .afterActivation), .output0.scaleArraySet, .output1.boundsArray, .output1.scaleArraySet
    super.set_outputs_all_byBoundsArraySet( aBoundsArraySet );

    for ( let i = 0; i < this.bPassThrough.length; ++i ) {
      this.bPassThrough[ i ] = aBoundsArraySet.bPassThrough[ i ];
    }

    return this;
  }

  /**
   * Determine .afterActivationEscaping, .output0.boundsArray (i.e. .afterActivation) and .output0.scaleArraySet,
   * by .afterBias and .bPassThrough and nActivationId.
   *
   * The following properties will be used:
   *   - this.afterBias
   *   - this.bPassThrough
   *
   * The following properties will be modified:
   *   - this.afterActivationEscaping
   *   - this.output0.boundsArray (i.e. this.afterActivation)
   *   - this.output0.scaleArraySet
   *
   * @param {number} nActivationId
   *   The activation function id (ValueDesc.ActivationFunction.Singleton.Ids.Xxx) of this depthwise convolution.
   *
   * @return {ConvBiasActivation}
   *   Return this (modified) object.
   */
  set_afterActivationEscaping_output0_by_afterBias_bPassThrough_nActivationId( nActivationId ) {
    let theActivationFunctionInfo = ValueDesc.ActivationFunction.Singleton.getInfoById( nActivationId );

    for ( let outChannel = 0; outChannel < this.afterBias.length; ++outChannel ) {

      // 1. Determine (activationEscaping) .scaleArraySet (of .output0)
      {
        // 1.1 Determine .do

        if ( nActivationId == ValueDesc.ActivationFunction.Singleton.Ids.NONE ) {

          // Since no activation function, no need to escape. (i.e. scale = 1 for no scale)
          this.output0.scaleArraySet.do.set_one_byN( outChannel, 1 );

        } else {

          if ( this.bPassThrough[ outChannel ] ) { // For pass-through half channels.

            // Calculate the scale for escaping bias result from activation function's non-linear domain into linear domain.
            //
            // Note: This does not work for avg/max pooling.
            this.output0.scaleArraySet.do.set_one_by_fromLowerUpper_toLowerUpper( outChannel,
              this.afterBias.lowers[ outChannel ], this.afterBias.uppers[ outChannel ],
              theActivationFunctionInfo.inputDomainLinear.lower, theActivationFunctionInfo.inputDomainLinear.upper
            );

            let doEscapingScale = this.output0.scaleArraySet.do.scales[ outChannel ];
            tf.util.assert( ( Number.isNaN( doEscapingScale ) == false ),
              `ConvBiasActivation.BoundsArraySet.`
                + `set_afterActivationEscaping_afterActivation_by_afterBias_bPassThrough_nActivationId(): `
                + `this.output0.scaleArraySet.do.scales[ ${outChannel} ] ( ${doEscapingScale} ) `
                + `should not be NaN. `
                + `Please use activation function (e.g. tanh()) which has both negative and positive parts near origin point.`
            );

          } else { // Non pass-through half channels.
            // Since non-pass-through, no need to escape. (i.e. scale = 1 for no scale)
            this.output0.scaleArraySet.do.set_one_byN( outChannel, 1 );
          }
        }

        // 1.2 Determine .undo (Prepared for the next convolution-bias-activation. Not for this.)
        this.output0.scaleArraySet.undo.set_one_byUndo_ScaleArray(
          outChannel, this.output0.scaleArraySet.do, outChannel );
      }

      // 2. Determine .afterActivationEscaping
      this.afterActivationEscaping
        .set_one_byBoundsArray( outChannel, this.afterBias, outChannel )
        .multiply_one_byNs( outChannel, this.output0.scaleArraySet.do.scales, outChannel );

      // 3. Determine .afterActivation (i.e. .output0.boundsArray)
      {
        // If no activation function, the output range is determined by .afterActivationEscaping.
        if ( nActivationId == ValueDesc.ActivationFunction.Singleton.Ids.NONE ) {
          this.output0.boundsArray.set_one_byBoundsArray( outChannel, this.afterActivationEscaping, outChannel )

        // Otherwise, the activation function dominates the output range.
        //
        // Note: Consider the implementation of ScaleArray.set_one_by_fromLowerUpper_toLowerUpper(), they are all not so good no
        //       matter using set_one_byXxx() or clamp_one_byXxx() of this.afterActivation. However, when using clamp_one_byXxx(),
        //       even if the activation function output range has Infinity (e.g. RELU is [ 0, +Infinity ]), the result bounds
        //       is more feasible (at least, will not become another bounds with Infinity).
        } else {
          if ( this.bPassThrough[ outChannel ] ) { // For pass-through half channels, it is clamped by the output range for linearDomainLinear.
            //this.output0.boundsArray.set_one_byBounds( outChannel, theActivationFunctionInfo.outputRangeLinear );
            this.output0.boundsArray.clamp_one_byBounds( outChannel, theActivationFunctionInfo.outputRangeLinear );

          } else { // Non pass-through half channels, it is clamped by the output range for the whole input domain.
            //this.output0.boundsArray.set_one_byBounds( outChannel, theActivationFunctionInfo.outputRange );
            this.output0.boundsArray.clamp_one_byBounds( outChannel, theActivationFunctionInfo.outputRange );
          }
        }
      }
    }

    return this;
  }

  /**
   * Rearrange output related channel information (.afterFilter, .afterBias, .afterActivationEscaping, .afterActivation
   * (i.e. .output0.boundsArray), output0.scaleArraySet (i.e. activationEscaping), .bPassThrough) by interleaving as
   * ( groupCount == 2 ). The channel count must be even (i.e. divisible by 2).
   *
   * @param {Array} arrayTemp
   *   A temporary array for placing the original elements temporarily. Provide this array could reduce memory re-allocation
   * and improve performance.
   *
   * @return {ConvBiasActivation}
   *   Return this (modified) object.
   */
  set_outputs_all_byInterleave_asGrouptTwo( arrayTemp ) {
    this.afterFilter.set_all_byInterleave_asGrouptTwo( arrayTemp );
    this.afterBias.set_all_byInterleave_asGrouptTwo( arrayTemp );
    this.afterActivationEscaping.set_all_byInterleave_asGrouptTwo( arrayTemp );
    super.set_outputs_all_byInterleave_asGrouptTwo( arrayTemp ); // i.e. this.afterActivation
    FloatValue.ArrayInterleaver.interleave_asGrouptTwo( this.bPassThrough, 0, this.bPassThrough.length, arrayTemp );
    return this;
  }

  get afterActivation() {
    return this.output0.boundsArray;
  }

}

<commit_msg>Update BoundsArraySet_ConvBiasActivation.js<commit_after>export { ConvBiasActivation };

import * as FloatValue from "../../Unpacker/FloatValue.js";
import * as ValueDesc from "../../Unpacker/ValueDesc.js";
import { InputsOutputs } from "./BoundsArraySet_InputsOutputs.js";

/**
 * Element value bounds (per channel) for every operation's result of a convolution-bias-activation. The main purpose is to find out the
 * activationEscaping_ScaleArraySet so that it can be used to let channel escape from activation function's non-linear effect.
 *
 *   - Only input0 is used. The input1 always is undefined.
 *   - Only outputChannelCount0 is used. The outputChannelCount1 always is undefined.
 *
 * @member {FloatValue.BoundsArray} afterUndoPreviousActivationEscaping
 *   The element value bounds (per channel) after applying the previousConvBiasActivation.BoundsArraySet.ActivationEscaping.undo
 * to this.input0. (i.e. beforeFilter)
 *
 * @member {FloatValue.BoundsArray} afterFilter
 *   The element value bounds (per channel) after applying the convolution filters to this.afterUndoPreviousActivationEscaping.
 * (i.e. beforeBias)
 *
 * @member {FloatValue.BoundsArray} afterBias
 *   The element value bounds (per channel) after applying the convolution biases to this.afterFilter. (i.e. beforeActivationEscaping)
 *
 * @member {FloatValue.BoundsArray} afterActivationEscaping
 *   The element value bounds (per channel) after applying this.activationEscaping_ScaleArraySet.do to this.afterBias. (i.e. beforeActivation)
 *
 * @member {FloatValue.BoundsArray} afterActivation
 *   The element value bounds (per channel) after applying activation function to this.afterActivationEscaping. It is just
 * the this.output0.boundsArray (without this.output0.scaleArraySet).
 *
 * @member {boolean[]} bPassThrough
 *   If true for a output channel, the output channel should be arranged to pass-through from input to output.
 *
 * @see InputsOutputs
 */
class ConvBiasActivation extends InputsOutputs {

  /**
   *   - The .input0 will be set as input0.
   *   - The .afterUndoPreviousActivationEscaping will be set according to  input0 and input0.scaleArraySet.undo.scales.
   *
   * Difference from (parent class) InputsOutputs:
   *   - Only input0 (always no input1), because convolution (no matter pointwise or depthwise) could handle one input tensor.
   *   - Only output0 (always no output1), because convolution (no matter pointwise or depthwise) always generate one output tensor.
   *
   */
  constructor( input0, outputChannelCount0 ) {
    super( input0, undefined, outputChannelCount0, undefined ); // .input0 and .output0

    this.afterUndoPreviousActivationEscaping = new FloatValue.BoundsArray( input0.length ); // channel count same as input0.

    this.afterFilter = new FloatValue.BoundsArray( outputChannelCount0 );
    this.afterBias = new FloatValue.BoundsArray( outputChannelCount0 );
    this.afterActivationEscaping = new FloatValue.BoundsArray( outputChannelCount0 );

    this.bPassThrough = new Array( outputChannelCount0 );

    this.set_afterUndoPreviousActivationEscaping_by_input0_undoScales();
  }

  /**
   * Set .afterUndoPreviousActivationEscaping as .input0 multiplying .input0.scaleArraySet.undo.scales.
   *
   * @return {ConvBiasActivation}
   *   Return this (modified) object.
   */
  set_afterUndoPreviousActivationEscaping_by_input0_undoScales() {
    this.afterUndoPreviousActivationEscaping
      .set_all_byBoundsArray( this.input0.boundsArray )
      .multiply_all_byNs( this.input0.scaleArraySet.undo.scales );
    return this;
  }

  /**
   * @return {ConvBiasActivation}
   *   Return a newly created ConvBiasActivation which is a copy of this ConvBiasActivation. The this.inputs will just past
   * to new ConvBiasActivation (i.e. NOT copied). But the other data members will be copied.
   */
  clone() {
    let result = new ConvBiasActivation( this.input0, this.outputChannelCount0 );
    result.set_all_byBoundsArraySet( this );
    return result;
  }

  /**
   * Set:
   *   - this.bPassThrough[] to false (i.e. all are not pass-through).
   *
   * @return {ConvBiasActivation}
   *   Return this (modified) object.
   */
  set_bPassThrough_all_none() {
    this.bPassThrough.fill( false );
    return this;
  }

  /**
   * Set:
   *   - this.activationEscaping_ScaleArraySet to scale 1 (i.e. all are no scale).
   *   - this.bPassThrough[] to false (i.e. all are not pass-through).
   *
   * @return {ConvBiasActivation}
   *   Return this (modified) object.
   */
  set_activationEscaping_bPassThrough_all_none() {
    super.set_activationEscaping_all_none();
    this.set_bPassThrough_all_none();
    return this;
  }

  /**
   * @param {FloatValue.Bounds} aBounds
   *   Set all outputs related BoundsArray (.afterFilter, .afterBias, .afterActivationEscaping, .output0.boundsArray
   * (i.e. .afterActivation), .bPassThrough) to the same as the specified aBounds. Set the this.output0.scaleArraySet
   * to default ( 1 ). The .input0 are not modified.
   *
   * @return {ConvBiasActivation}
   *   Return this (modified) object.
   */
  set_outputs_all_byBounds( aBounds ) {
    this.afterFilter.set_all_byBounds( aBounds );
    this.afterBias.set_all_byBounds( aBounds );
    this.afterActivationEscaping.set_all_byBounds( aBounds );
    super.set_outputs_all_byBounds( aBounds ); // i.e. .output0.boundsArray (i.e. .afterActivation), .output0.scaleArraySet
    this.set_bPassThrough_all_none();
    return this;
  }

  /**
   * @param {BoundsArraySet.ConvBiasActivation} aBoundsArraySet
   *   The BoundsArraySet to be copied. The .inputs will just be referenced (NOT copied). But the other data members will be copied.
   *
   * @return {ConvBiasActivation}
   *   Return this (modified) object which is copied from aBoundsArraySet.
   */
  set_all_byBoundsArraySet( aBoundsArraySet ) {

    // inputs. Non-copy. Just reference to the same inputs.
    {
      this.input0 = aBoundsArraySet.input0;

      if ( aBoundsArraySet.input1 )
        this.input1 = aBoundsArraySet.input1;
      else
        delete this.input1;
    }

    this.afterUndoPreviousActivationEscaping.set_all_byBoundsArray( aBoundsArraySet.afterUndoPreviousActivationEscaping );
    this.afterFilter                        .set_all_byBoundsArray( aBoundsArraySet.afterFilter );
    this.afterBias                          .set_all_byBoundsArray( aBoundsArraySet.afterBias );
    this.afterActivationEscaping            .set_all_byBoundsArray( aBoundsArraySet.afterActivationEscaping );

    // .output0.boundsArray (i.e. .afterActivation), .output0.scaleArraySet, .output1.boundsArray, .output1.scaleArraySet
    super.set_outputs_all_byBoundsArraySet( aBoundsArraySet );

    for ( let i = 0; i < this.bPassThrough.length; ++i ) {
      this.bPassThrough[ i ] = aBoundsArraySet.bPassThrough[ i ];
    }

    return this;
  }

  /**
   * Determine .afterActivationEscaping, .output0.boundsArray (i.e. .afterActivation) and .output0.scaleArraySet,
   * by .afterBias and .bPassThrough and nActivationId.
   *
   * The following properties will be used:
   *   - this.afterBias
   *   - this.bPassThrough
   *
   * The following properties will be modified:
   *   - this.afterActivationEscaping
   *   - this.output0.boundsArray (i.e. this.afterActivation)
   *   - this.output0.scaleArraySet
   *
   * @param {number} nActivationId
   *   The activation function id (ValueDesc.ActivationFunction.Singleton.Ids.Xxx) of this depthwise convolution.
   *
   * @return {ConvBiasActivation}
   *   Return this (modified) object.
   */
  set_afterActivationEscaping_output0_by_afterBias_bPassThrough_nActivationId( nActivationId ) {
    let theActivationFunctionInfo = ValueDesc.ActivationFunction.Singleton.getInfoById( nActivationId );

    for ( let outChannel = 0; outChannel < this.afterBias.length; ++outChannel ) {

      // 1. Determine (activationEscaping) .scaleArraySet (of .output0)
      {
        // 1.1 Determine .do

        if ( nActivationId == ValueDesc.ActivationFunction.Singleton.Ids.NONE ) {

          // Since no activation function, no need to escape. (i.e. scale = 1 for no scale)
          this.output0.scaleArraySet.do.set_one_byN( outChannel, 1 );

        } else {

          if ( this.bPassThrough[ outChannel ] ) { // For pass-through half channels.

            // Calculate the scale for escaping bias result from activation function's non-linear domain into linear domain.
            //
            // Note: This does not work for avg/max pooling.
            this.output0.scaleArraySet.do.set_one_by_fromLowerUpper_toLowerUpper( outChannel,
              this.afterBias.lowers[ outChannel ], this.afterBias.uppers[ outChannel ],
              theActivationFunctionInfo.inputDomainLinear.lower, theActivationFunctionInfo.inputDomainLinear.upper
            );

            let doEscapingScale = this.output0.scaleArraySet.do.scales[ outChannel ];
            tf.util.assert( ( Number.isNaN( doEscapingScale ) == false ),
              `ConvBiasActivation.BoundsArraySet.`
                + `set_afterActivationEscaping_afterActivation_by_afterBias_bPassThrough_nActivationId(): `
                + `this.output0.scaleArraySet.do.scales[ ${outChannel} ] ( ${doEscapingScale} ) `
                + `should not be NaN. `
                + `Please use activation function (e.g. tanh()) which has both negative and positive parts near origin point.`
            );

          } else { // Non pass-through half channels.
            // Since non-pass-through, no need to escape. (i.e. scale = 1 for no scale)
            this.output0.scaleArraySet.do.set_one_byN( outChannel, 1 );
          }
        }

        // 1.2 Determine .undo (Prepared for the next convolution-bias-activation. Not for this.)
        this.output0.scaleArraySet.undo.set_one_byUndo_ScaleArray(
          outChannel, this.output0.scaleArraySet.do, outChannel );
      }

      // 2. Determine .afterActivationEscaping
      this.afterActivationEscaping
        .set_one_byBoundsArray( outChannel, this.afterBias, outChannel )
        .multiply_one_byNs( outChannel, this.output0.scaleArraySet.do.scales, outChannel );

      // 3. Determine .afterActivation (i.e. .output0.boundsArray)
      {
        this.output0.boundsArray.set_one_byBoundsArray( outChannel, this.afterActivationEscaping, outChannel );

        // If there is activation function, the activation function dominates the output range.
        //
        // Note: Consider the implementation of ScaleArray.set_one_by_fromLowerUpper_toLowerUpper(), they are all not so good no
        //       matter using set_one_byXxx() or clamp_one_byXxx() of this.afterActivation. However, when using clamp_one_byXxx(),
        //       even if the activation function output range has Infinity (e.g. RELU is [ 0, +Infinity ]), the result's bounds
        //       is more feasible (at least, will not become another bounds with Infinity).
        if ( nActivationId != ValueDesc.ActivationFunction.Singleton.Ids.NONE ) {

          if ( this.bPassThrough[ outChannel ] ) { // For pass-through half channels, it is clamped by the output range for linearDomainLinear.
            //this.output0.boundsArray.set_one_byBounds( outChannel, theActivationFunctionInfo.outputRangeLinear );
            this.output0.boundsArray.clamp_one_byBounds( outChannel, theActivationFunctionInfo.outputRangeLinear );

          } else { // Non pass-through half channels, it is clamped by the output range for the whole input domain.
            //this.output0.boundsArray.set_one_byBounds( outChannel, theActivationFunctionInfo.outputRange );
            this.output0.boundsArray.clamp_one_byBounds( outChannel, theActivationFunctionInfo.outputRange );
          }

        // Otherwise, no activation function, the output range is determined by .afterActivationEscaping.
        }
      }

//!!! (2022/04/25 Remarked) should this.output0.boundsArray.set_one_Xxx() first.
//       {
//         // If no activation function, the output range is determined by .afterActivationEscaping.
//         if ( nActivationId == ValueDesc.ActivationFunction.Singleton.Ids.NONE ) {
//           this.output0.boundsArray.set_one_byBoundsArray( outChannel, this.afterActivationEscaping, outChannel );
//
//         // Otherwise, the activation function dominates the output range.
//         //
//         // Note: Consider the implementation of ScaleArray.set_one_by_fromLowerUpper_toLowerUpper(), they are all not so good no
//         //       matter using set_one_byXxx() or clamp_one_byXxx() of this.afterActivation. However, when using clamp_one_byXxx(),
//         //       even if the activation function output range has Infinity (e.g. RELU is [ 0, +Infinity ]), the result bounds
//         //       is more feasible (at least, will not become another bounds with Infinity).
//         } else {
//
// //!!! ...unfinished... (2022/04/25) should this.output0.boundsArray.set_one_Xxx() first.
//
//           if ( this.bPassThrough[ outChannel ] ) { // For pass-through half channels, it is clamped by the output range for linearDomainLinear.
//             //this.output0.boundsArray.set_one_byBounds( outChannel, theActivationFunctionInfo.outputRangeLinear );
//             this.output0.boundsArray.set_one_byBoundsArray( outChannel, this.afterActivationEscaping, outChannel );
//             this.output0.boundsArray.clamp_one_byBounds( outChannel, theActivationFunctionInfo.outputRangeLinear );
//
//           } else { // Non pass-through half channels, it is clamped by the output range for the whole input domain.
//             //this.output0.boundsArray.set_one_byBounds( outChannel, theActivationFunctionInfo.outputRange );
//             this.output0.boundsArray.set_one_byBoundsArray( outChannel, this.afterActivationEscaping, outChannel );
//             this.output0.boundsArray.clamp_one_byBounds( outChannel, theActivationFunctionInfo.outputRange );
//           }
//         }
//       }

    }

    return this;
  }

  /**
   * Rearrange output related channel information (.afterFilter, .afterBias, .afterActivationEscaping, .afterActivation
   * (i.e. .output0.boundsArray), output0.scaleArraySet (i.e. activationEscaping), .bPassThrough) by interleaving as
   * ( groupCount == 2 ). The channel count must be even (i.e. divisible by 2).
   *
   * @param {Array} arrayTemp
   *   A temporary array for placing the original elements temporarily. Provide this array could reduce memory re-allocation
   * and improve performance.
   *
   * @return {ConvBiasActivation}
   *   Return this (modified) object.
   */
  set_outputs_all_byInterleave_asGrouptTwo( arrayTemp ) {
    this.afterFilter.set_all_byInterleave_asGrouptTwo( arrayTemp );
    this.afterBias.set_all_byInterleave_asGrouptTwo( arrayTemp );
    this.afterActivationEscaping.set_all_byInterleave_asGrouptTwo( arrayTemp );
    super.set_outputs_all_byInterleave_asGrouptTwo( arrayTemp ); // i.e. this.afterActivation
    FloatValue.ArrayInterleaver.interleave_asGrouptTwo( this.bPassThrough, 0, this.bPassThrough.length, arrayTemp );
    return this;
  }

  get afterActivation() {
    return this.output0.boundsArray;
  }

}

<|endoftext|>


<commit_before>define(["Tone/core/Tone", "Tone/core/Transport"], function(Tone){

	"use strict";

	/**
	 *  @class  Base class for sources.
	 *          Sources have start/stop/pause and
	 *          the ability to be synced to the
	 *          start/stop/pause of Tone.Transport.
	 *
	 *  @constructor
	 *  @extends {Tone}
	 */
	Tone.Source = function(){
		//unlike most ToneNodes, Sources only have an output and no input
		Tone.call(this, 0, 1);

		/**
		 *  @type {Tone.Source.State}
		 */
		this.state = Tone.Source.State.STOPPED;
	};

	Tone.extend(Tone.Source);

	/**
	 *  @abstract
	 *  @param  {Tone.Time} time
	 */
	Tone.Source.prototype.start = function(){};

	/**
 	 *  @abstract
	 *  @param  {Tone.Time} time
	 */
	Tone.Source.prototype.stop = function(){};

	/**
 	 *  @abstract
	 *  @param  {Tone.Time} time
	 */
	Tone.Source.prototype.pause = function(time){
		//if there is no pause, just stop it
		this.stop(time);
	};

	/**
	 *  sync the source to the Transport
	 *
	 *  @param {Tone.Time} [delay=0] delay time before starting the source
	 */
	Tone.Source.prototype.sync = function(delay){
		Tone.Transport.syncSource(this, delay);
	};

	/**
	 *  unsync the source to the Transport
	 */
	Tone.Source.prototype.unsync = function(){
		Tone.Transport.unsyncSource(this);
	};

	/**
	 *  set the volume in decibels
	 *  @param {number} db in decibels
	 *  @param {Tone.Time=} fadeTime (optional) time it takes to reach the value
	 */
	Tone.Source.prototype.setVolume = function(db, fadeTime){
		var now = this.now();
		var gain = this.dbToGain(db);
		if (fadeTime){
			var currentVolume = this.output.gain.value;
			this.output.gain.cancelScheduledValues(now);
			this.output.gain.setValueAtTime(currentVolume, now);
			this.output.gain.linearRampToValueAtTime(gain, now + this.toSeconds(fadeTime));
		} else {
			this.output.gain.setValueAtTime(gain, now);
		}
	};

	/**
	 *  set the parameters at once
	 *  @param {Object} params
	 */
	Tone.Source.prototype.set = function(params){
		if (!this.isUndef(params.volume)) this.setVolume(params.volume);
	};

	/**
	 *	clean up
	 */
	Tone.Source.prototype.dispose = function(){
		Tone.prototype.dispose.call(this);
		this.state = null;
	};

	/**
	 *  @enum {string}
	 */
	Tone.Source.State = {
		STARTED : "started",
		PAUSED : "paused",
		STOPPED : "stopped",
		SYNCED : "synced"
 	};

	return Tone.Source;
});<commit_msg>volume gets set right away<commit_after>define(["Tone/core/Tone", "Tone/core/Transport"], function(Tone){

	"use strict";

	/**
	 *  @class  Base class for sources.
	 *          Sources have start/stop/pause and
	 *          the ability to be synced to the
	 *          start/stop/pause of Tone.Transport.
	 *
	 *  @constructor
	 *  @extends {Tone}
	 */
	Tone.Source = function(){
		//unlike most ToneNodes, Sources only have an output and no input
		Tone.call(this, 0, 1);

		/**
		 *  @type {Tone.Source.State}
		 */
		this.state = Tone.Source.State.STOPPED;
	};

	Tone.extend(Tone.Source);

	/**
	 *  @abstract
	 *  @param  {Tone.Time} time
	 */
	Tone.Source.prototype.start = function(){};

	/**
 	 *  @abstract
	 *  @param  {Tone.Time} time
	 */
	Tone.Source.prototype.stop = function(){};

	/**
 	 *  @abstract
	 *  @param  {Tone.Time} time
	 */
	Tone.Source.prototype.pause = function(time){
		//if there is no pause, just stop it
		this.stop(time);
	};

	/**
	 *  sync the source to the Transport
	 *
	 *  @param {Tone.Time} [delay=0] delay time before starting the source
	 */
	Tone.Source.prototype.sync = function(delay){
		Tone.Transport.syncSource(this, delay);
	};

	/**
	 *  unsync the source to the Transport
	 */
	Tone.Source.prototype.unsync = function(){
		Tone.Transport.unsyncSource(this);
	};

	/**
	 *  set the volume in decibels
	 *  @param {number} db in decibels
	 *  @param {Tone.Time=} fadeTime (optional) time it takes to reach the value
	 */
	Tone.Source.prototype.setVolume = function(db, fadeTime){
		var now = this.now();
		var gain = this.dbToGain(db);
		if (fadeTime){
			var currentVolume = this.output.gain.value;
			this.output.gain.cancelScheduledValues(now);
			this.output.gain.setValueAtTime(currentVolume, now);
			this.output.gain.linearRampToValueAtTime(gain, now + this.toSeconds(fadeTime));
		} else {
			this.output.gain.value = gain;
		}
	};

	/**
	 *  set the parameters at once
	 *  @param {Object} params
	 */
	Tone.Source.prototype.set = function(params){
		if (!this.isUndef(params.volume)) this.setVolume(params.volume);
	};

	/**
	 *	clean up
	 */
	Tone.Source.prototype.dispose = function(){
		Tone.prototype.dispose.call(this);
		this.state = null;
	};

	/**
	 *  @enum {string}
	 */
	Tone.Source.State = {
		STARTED : "started",
		PAUSED : "paused",
		STOPPED : "stopped",
		SYNCED : "synced"
 	};

	return Tone.Source;
});<|endoftext|>


<commit_before>/*

var SB = require('./bots/_SocketBot.js');
var a = new SB({"tags": ["t1","t2"]});
var b = new SB({"tags": ["t2","t3"]});
var c = new SB({"tags": ["t3","t4"]});
a.start();
b.start();
c.start();
c.broadcast('yo', 't1', 100);

 */

var Bot = require('./_Bot.js')
,	util = require('util');

var SocketBot = function(config) {
	if(!config) config = {};
	this.init(config);
};

util.inherits(SocketBot, Bot);

SocketBot.prototype.init = function(config) {
	config = config || {};
	SocketBot.super_.prototype.init.call(this, config);
	this.server = config.server || 'ws://127.0.0.1:2266';
	this.tags = config.tags || [];
};

SocketBot.prototype.start = function() {
	if(this.active) { return; }
	var self = this;
	SocketBot.super_.prototype.start.apply(this);
	this.socket = require('socket.io-client')(this.server, {'force new connection': true});

	this.tag(this.tags);

	this.socket.on('message', function(msg) {
		if(msg._response) {
			self.getResponse(msg);
		}
		else {
			self.get(msg);
		}
	});

	this.socket.on('wait', function(msg) {
		self.addJob(msg._id, msg.jobs);
		self.done(msg._id);
	});
};

SocketBot.prototype.stop = function() {
	Coordinator.super_.prototype.stop.apply(this);
	this.socket.disconnect();
};

SocketBot.prototype.tag = function(tag) {
	if(Array.isArray(tag)) {
		for(var k in tag) {
			this.tag(tag[k]);
		}

		return true;
	}

	if(this.tags.indexOf(tag) == -1) { this.tags.push(tag); }
	if(this.socket) { this.socket.emit('tag', tag); }
	return true;
};

SocketBot.prototype.untag = function() {
	this.tags = [];
	this.socket.emit('untag');
};

SocketBot.prototype.send = function(msg, option) {
	if(typeof msg != 'object') {
		msg = {"data": msg};
	}

	msg._id = this.randomID();
	msg._option = option;

	this.socket.emit('message', msg);

	if(option.waiting) {
		this.initEvent(msg._id);
		this.addJob(msg._id);
		return this.wait(msg._id);
	}
};

SocketBot.prototype.broadcast = function(msg, tags, response) {
	var option = {
		"method": "broadcast",
		"tag": tags
	};

	if(response) {
		option.waiting = true;
	}

	return this.send(msg, option);
};

SocketBot.prototype.peer = function(msg, clients, response) {
	var option = {
		"method": "peer",
		"peer": clients
	}

	if(response) {
		option.waiting = true;
	}

	return this.send(msg, option);
};

SocketBot.prototype.random = function(msg, num, tags, response) {
	var option = {
		"method": "random",
		"num": num,
		"tag": tags
	};

	if(response) {
		option.waiting = true;
	}

	return this.send(msg, option);
};

SocketBot.prototype.get = function(message) {
	if(message._command) {
		this.command(message);
	}
	else {
		console.log('I got message: %s', JSON.stringify(message));
		this.response("OK!", message);
	}
};
SocketBot.prototype.getResponse = function(message) {
	this.done(message._response, message);
	// console.log('I got response: %s', JSON.stringify(message))
};

SocketBot.prototype.response = function(msg, oldMsg) {
	if(!oldMsg._from) { return false; }
	if(typeof msg != 'object') { msg = {"data": msg}; }
	msg._id = oldMsg._id;
	msg._response = oldMsg._id;
	this.peer(msg, oldMsg._from);
};

module.exports = SocketBot;<commit_msg>Debug<commit_after>/*

var SB = require('./bots/_SocketBot.js');
var a = new SB({"tags": ["t1","t2"]});
var b = new SB({"tags": ["t2","t3"]});
var c = new SB({"tags": ["t3","t4"]});
a.start();
b.start();
c.start();
c.broadcast('yo', 't1', 100);

 */

var Bot = require('./_Bot.js')
,	util = require('util');

var SocketBot = function(config) {
	if(!config) config = {};
	this.init(config);
};

util.inherits(SocketBot, Bot);

SocketBot.prototype.init = function(config) {
	config = config || {};
	SocketBot.super_.prototype.init.call(this, config);
	this.server = config.server || 'ws://127.0.0.1:2266';
	this.tags = config.tags || [];
};

SocketBot.prototype.start = function() {
	if(this.active) { return; }
	var self = this;
	SocketBot.super_.prototype.start.apply(this);
	this.socket = require('socket.io-client')(this.server, {'force new connection': true});

	this.tag(this.tags);

	this.socket.on('message', function(msg) {
		if(msg._response) {
			self.getResponse(msg);
		}
		else {
			self.get(msg);
		}
	});

	this.socket.on('wait', function(msg) {
		self.addJob(msg._id, msg.jobs);
		self.done(msg._id);
	});
};

SocketBot.prototype.stop = function() {
	Coordinator.super_.prototype.stop.apply(this);
	this.socket.disconnect();
};

SocketBot.prototype.tag = function(tag) {
	if(Array.isArray(tag)) {
		for(var k in tag) {
			this.tag(tag[k]);
		}

		return true;
	}

	if(this.tags.indexOf(tag) == -1) { this.tags.push(tag); }
	if(this.socket) { this.socket.emit('tag', tag); }
	return true;
};

SocketBot.prototype.untag = function() {
	this.tags = [];
	this.socket.emit('untag');
};

SocketBot.prototype.send = function(msg, option) {
	if(typeof msg != 'object') {
		msg = {"data": msg};
	}

	msg._id = this.randomID();
	msg._option = option;

	this.socket.emit('message', msg);

	if(option.waiting) {
		this.initEvent(msg._id);
		this.addJob(msg._id);
		return this.wait(msg._id);
	}
};

SocketBot.prototype.broadcast = function(msg, tags, response) {
	var option = {
		"method": "broadcast",
		"tag": tags
	};

	if(response) {
		option.waiting = true;
	}

	return this.send(msg, option);
};

SocketBot.prototype.peer = function(msg, clients, response) {
	var option = {
		"method": "peer",
		"peer": clients
	}

	if(response) {
		option.waiting = true;
	}

	return this.send(msg, option);
};

SocketBot.prototype.random = function(msg, num, tags, response) {
	var option = {
		"method": "random",
		"num": num,
		"tag": tags
	};

	if(response) {
		option.waiting = true;
	}

	return this.send(msg, option);
};

SocketBot.prototype.get = function(message) {
	if(message._command) {
		this.exec(message);
	}
	else {
		console.log('I got message: %s', JSON.stringify(message));
		this.response("OK!", message);
	}
};
SocketBot.prototype.getResponse = function(message) {
	this.done(message._response, message);
	// console.log('I got response: %s', JSON.stringify(message))
};

SocketBot.prototype.response = function(msg, oldMsg) {
	if(!oldMsg._from) { return false; }
	if(typeof msg != 'object') { msg = {"data": msg}; }
	msg._id = oldMsg._id;
	msg._response = oldMsg._id;
	this.peer(msg, oldMsg._from);
};

SocketBot.prototype.record = function(table, data) {
	var message = {
		"table": table,
		"data": data
	};

	this.random(message, 1, 'recorder');
};

module.exports = SocketBot;<|endoftext|>


<commit_before>/*
 * Copyright 2015-2016 OpenCB
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {html, LitElement} from "/web_modules/lit-element.js";
import UtilsNew from "../../../utilsNew.js";
import "../../tool-header.js";
import "./variant-interpreter-landing.js";
import "./variant-interpreter-qc.js";
import "./variant-interpreter-report.js";
import "./variant-interpreter-rd-browser.js";
import "./variant-interpreter-cancer-browser.js";
import "./variant-interpreter-review.js";
import "./variant-interpreter-interpretation.js";
import "./opencga-variant-interpreter-genome-browser.js";
import "../../opencga/opencga-genome-browser.js";
import "../../clinical/opencga-clinical-analysis-view.js";
import "../../clinical/clinical-interpretation-view.js";
import "../../commons/opencga-active-filters.js";
import "../../commons/filters/select-field-filter-autocomplete-simple.js";

class VariantInterpreter extends LitElement {

    constructor() {
        super();

        // Set status and init private properties
        this._init();
    }

    createRenderRoot() {
        return this;
    }

    static get properties() {
        return {
            opencgaSession: {
                type: Object
            },
            clinicalAnalysisId: {
                type: String
            },
            clinicalAnalysis: {
                type: Object
            },
            cellbaseClient: {
                type: Object
            },
            config: {
                type: Object
            }
        };
    }

    _init() {
        this._prefix = "vgi-" + UtilsNew.randomString(6);
        this.activeTab = {};
    }

    connectedCallback() {
        super.connectedCallback();

        this._config = {...this.getDefaultConfig(), ...this.config};
    }

    updated(changedProperties) {
        if (changedProperties.has("opencgaSession")) {
            this.opencgaSessionObserver();
        }

        if (changedProperties.has("clinicalAnalysisId")) {
            this.clinicalAnalysisIdObserver();
        }
    }

    opencgaSessionObserver() {
        // With each property change we must updated config and create the columns again. No extra checks are needed.
        this._config = {...this.getDefaultConfig(), ...this.config};
        this.clinicalAnalysis = null;
        this._changeView(this._config?.tools[0].id)
        this.requestUpdate();
    }

    clinicalAnalysisIdObserver() {
        if (this.opencgaSession && this.clinicalAnalysisId) {
            this.opencgaSession.opencgaClient.clinical().info(this.clinicalAnalysisId, {study: this.opencgaSession.study.fqn})
                .then(response => {
                    this.clinicalAnalysis = response.responses[0].results[0];
                    this.requestUpdate();
                })
                .catch(response => {
                    console.error("An error occurred fetching clinicalAnalysis: ", response);
                });
        }
    }

    onClickSection(e) {
        // e.preventDefault();
        this._changeView(e.currentTarget.dataset.view);
    }

    _changeView(tabId) {
        console.log("changing to ", tabId)
        $(`.clinical-portal-step`, this).removeClass("active");
        $(`.clinical-portal-content`, this).hide(); // hides all content divs
        for (const tab in this.activeTab) this.activeTab[tab] = false;

        $(`.clinical-portal-step[data-view=${tabId}]`, this).addClass("active");
        $("#" + this._prefix + tabId, this).show();
        this.activeTab[tabId] = true;
        this.requestUpdate();
    }

    /*_changeView(e) {
        e.preventDefault(); // prevents the hash change to "#" and allows to manipulate the hash fragment as needed

        if (e.currentTarget?.dataset?.view && !e.currentTarget.className.includes("disabled")) {
            $(".clinical-portal-content", this).hide(); // hides all content divs
            // $("#" + this._prefix + e.target.dataset.view).show(); // get the href and use it find which div to show
            this.querySelector("#" + this._prefix + e.currentTarget.dataset.view).style.display = "block";
            // Show the active button
            // $(".clinical-portal-button").removeClass("active");
            $(".clinical-portal-step").removeClass("active");
            // $(e.target).addClass("active");
            $(e.currentTarget).addClass("active");
        }
    }*/

    onClinicalAnalysisUpdate (e) {
        this.clinicalAnalysis = {...e.detail.clinicalAnalysis};
        this.requestUpdate();
    }

    onClinicalAnalysis(e) {
        this.clinicalAnalysis = e.detail.clinicalAnalysis;
        // debugger
        // this.clinicalAnalysis.type = "CANCER";
        this.requestUpdate();
    }

    getDefaultConfig() {
        return {
            title: "Case Interpreter",
            icon: "fas fa-user-md",
            active: false,
            tools: [
                {
                    id: "select",
                    title: "Case Info",
                    acronym: "VB",
                    description: "",
                    icon: "fa fa-folder-open"
                },
                {
                    id: "qc",
                    title: "Quality Control",
                    acronym: "VB",
                    description: "",
                    icon: "fa fa-chart-bar"
                },
                {
                    id: "interpretation",
                    title: "Interpretation Methods",
                    acronym: "VB",
                    description: "",
                    icon: "fa fa-sync"
                },
                {
                    id: "variant-browser",
                    title: "Variant Browser",
                    acronym: "VB",
                    description: "",
                    icon: "fa fa-search"
                },
                {
                    id: "review",
                    title: "Interpretation Review",
                    acronym: "VB",
                    description: "",
                    icon: "fa fa-edit"
                },
                {
                    id: "report",
                    title: "Report",
                    acronym: "VB",
                    description: "",
                    disabled: true,
                    icon: "fa fa-file-alt"
                }
            ]
        };
    }

    render() {
        // Check Project exists
        if (!this.opencgaSession || !this.opencgaSession.project) {
            return html`

No project available to browse. Please login to continue

            `;
        }

        return html`

                ${this.clinicalAnalysis && this.clinicalAnalysis.id ? html`
                    <tool-header title="${`${this._config.title}<span class="inverse"> Case ${this.clinicalAnalysis?.id} </span>` }" icon="${this._config.icon}"></tool-header>
                ` : html`
                    <tool-header title="${this._config.title}" icon="${this._config.icon}"></tool-header>
                `}

                                ${this._config.tools && this._config.tools.map( item => html`

${item.title}

                                `)}

                        ${this._config.tools ? html`

                                <variant-interpreter-landing .opencgaSession="${this.opencgaSession}"
                                                             .clinicalAnalysis="${this.clinicalAnalysis}"
                                                             .config="${this._config}"
                                                             @selectClinicalAnalysis="${this.onClinicalAnalysis}">
                                </variant-interpreter-landing>

                                <variant-interpreter-qc .opencgaSession="${this.opencgaSession}"
                                                        .cellbaseClient="${this.cellbaseClient}"
                                                        .clinicalAnalysis="${this.clinicalAnalysis}"
                                                        .config="${this._config}">
                                </variant-interpreter-qc>

                                <variant-interpreter-interpretation .opencgaSession="${this.opencgaSession}"
                                                        .clinicalAnalysis="${this.clinicalAnalysis}"
                                                        .config="${this._config}">
                                </variant-interpreter-interpretation>

                                <opencga-variant-interpreter-genome-browser .opencgaSession="${this.opencgaSession}"
                                                                            .cellbaseClient="${this.cellbaseClient}"
                                                                            .clinicalAnalysis="${this.clinicalAnalysis}"
                                                                            .config="${this._config}">
                                </opencga-variant-interpreter-genome-browser>

                                ${this.clinicalAnalysis ?
                                    this.clinicalAnalysis.type.toUpperCase() === "SINGLE" || this.clinicalAnalysis.type.toUpperCase() === "FAMILY"
                                        ? html`
                                            <variant-interpreter-rd-browser .opencgaSession="${this.opencgaSession}"
                                                                            .clinicalAnalysis="${this.clinicalAnalysis}"
                                                                            .query="${this.interpretationSearchQuery}"
                                                                            .cellbaseClient="${this.cellbaseClient}"
                                                                            .populationFrequencies="${this._config.populationFrequencies}"
                                                                            .proteinSubstitutionScores="${this._config.proteinSubstitutionScores}"
                                                                            .consequenceTypes="${this._config.consequenceTypes}"
                                                                            @clinicalAnalysisUpdate="${this.onClinicalAnalysisUpdate}"
                                                                            @gene="${this.geneSelected}"
                                                                            @samplechange="${this.onSampleChange}">
                                            </variant-interpreter-rd-browser>`
                                        : html `
                                            <variant-interpreter-cancer-browser .opencgaSession="${this.opencgaSession}"
                                                                                .clinicalAnalysis="${this.clinicalAnalysis}"
                                                                                .query="${this.interpretationSearchQuery}"
                                                                                .cellbaseClient="${this.cellbaseClient}"
                                                                                .populationFrequencies="${this._config.populationFrequencies}"
                                                                                .proteinSubstitutionScores="${this._config.proteinSubstitutionScores}"
                                                                                .consequenceTypes="${this._config.consequenceTypes}"
                                                                                @clinicalAnalysisUpdate="${this.onClinicalAnalysisUpdate}"
                                                                                @gene="${this.geneSelected}">
                                            </variant-interpreter-cancer-browser>`
                                    : null
                                }

                                <variant-interpreter-review .opencgaSession="${this.opencgaSession}"
                                                            .clinicalAnalysis="${this.clinicalAnalysis}"
                                                            .cellbaseClient="${this.cellbaseClient}"
                                                            .populationFrequencies="${this._config.populationFrequencies}"
                                                            .proteinSubstitutionScores="${this._config.proteinSubstitutionScores}"
                                                            .consequenceTypes="${this._config.consequenceTypes}"
                                                            .config="${this._config}"
                                                            @gene="${this.geneSelected}"
                                                            @samplechange="${this.onSampleChange}">
                                 </variant-interpreter-review>

                                <variant-interpreter-report .opencgaSession="${this.opencgaSession}">
                                </variant-interpreter-report>

                        ` : null}

        `;
    }

}

customElements.define("variant-interpreter", VariantInterpreter);
<commit_msg>tool-header `title` attr fixed in variant-interpreter<commit_after>/*
 * Copyright 2015-2016 OpenCB
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {html, LitElement} from "/web_modules/lit-element.js";
import UtilsNew from "../../../utilsNew.js";
import "../../tool-header.js";
import "./variant-interpreter-landing.js";
import "./variant-interpreter-qc.js";
import "./variant-interpreter-report.js";
import "./variant-interpreter-rd-browser.js";
import "./variant-interpreter-cancer-browser.js";
import "./variant-interpreter-review.js";
import "./variant-interpreter-interpretation.js";
import "./opencga-variant-interpreter-genome-browser.js";
import "../../opencga/opencga-genome-browser.js";
import "../../clinical/opencga-clinical-analysis-view.js";
import "../../clinical/clinical-interpretation-view.js";
import "../../commons/opencga-active-filters.js";
import "../../commons/filters/select-field-filter-autocomplete-simple.js";

class VariantInterpreter extends LitElement {

    constructor() {
        super();

        // Set status and init private properties
        this._init();
    }

    createRenderRoot() {
        return this;
    }

    static get properties() {
        return {
            opencgaSession: {
                type: Object
            },
            clinicalAnalysisId: {
                type: String
            },
            clinicalAnalysis: {
                type: Object
            },
            cellbaseClient: {
                type: Object
            },
            config: {
                type: Object
            }
        };
    }

    _init() {
        this._prefix = "vgi-" + UtilsNew.randomString(6);
        this.activeTab = {};
    }

    connectedCallback() {
        super.connectedCallback();

        this._config = {...this.getDefaultConfig(), ...this.config};
    }

    updated(changedProperties) {
        if (changedProperties.has("opencgaSession")) {
            this.opencgaSessionObserver();
        }

        if (changedProperties.has("clinicalAnalysisId")) {
            this.clinicalAnalysisIdObserver();
        }
    }

    opencgaSessionObserver() {
        // With each property change we must updated config and create the columns again. No extra checks are needed.
        this._config = {...this.getDefaultConfig(), ...this.config};
        this.clinicalAnalysis = null;
        this._changeView(this._config?.tools[0].id)
        this.requestUpdate();
    }

    clinicalAnalysisIdObserver() {
        if (this.opencgaSession && this.clinicalAnalysisId) {
            this.opencgaSession.opencgaClient.clinical().info(this.clinicalAnalysisId, {study: this.opencgaSession.study.fqn})
                .then(response => {
                    this.clinicalAnalysis = response.responses[0].results[0];
                    this.requestUpdate();
                })
                .catch(response => {
                    console.error("An error occurred fetching clinicalAnalysis: ", response);
                });
        }
    }

    onClickSection(e) {
        // e.preventDefault();
        this._changeView(e.currentTarget.dataset.view);
    }

    _changeView(tabId) {
        console.log("changing to ", tabId)
        $(`.clinical-portal-step`, this).removeClass("active");
        $(`.clinical-portal-content`, this).hide(); // hides all content divs
        for (const tab in this.activeTab) this.activeTab[tab] = false;

        $(`.clinical-portal-step[data-view=${tabId}]`, this).addClass("active");
        $("#" + this._prefix + tabId, this).show();
        this.activeTab[tabId] = true;
        this.requestUpdate();
    }

    /*_changeView(e) {
        e.preventDefault(); // prevents the hash change to "#" and allows to manipulate the hash fragment as needed

        if (e.currentTarget?.dataset?.view && !e.currentTarget.className.includes("disabled")) {
            $(".clinical-portal-content", this).hide(); // hides all content divs
            // $("#" + this._prefix + e.target.dataset.view).show(); // get the href and use it find which div to show
            this.querySelector("#" + this._prefix + e.currentTarget.dataset.view).style.display = "block";
            // Show the active button
            // $(".clinical-portal-button").removeClass("active");
            $(".clinical-portal-step").removeClass("active");
            // $(e.target).addClass("active");
            $(e.currentTarget).addClass("active");
        }
    }*/

    onClinicalAnalysisUpdate (e) {
        this.clinicalAnalysis = {...e.detail.clinicalAnalysis};
        this.requestUpdate();
    }

    onClinicalAnalysis(e) {
        this.clinicalAnalysis = e.detail.clinicalAnalysis;
        // debugger
        // this.clinicalAnalysis.type = "CANCER";
        this.requestUpdate();
    }

    getDefaultConfig() {
        return {
            title: "Case Interpreter",
            icon: "fas fa-user-md",
            active: false,
            tools: [
                {
                    id: "select",
                    title: "Case Info",
                    acronym: "VB",
                    description: "",
                    icon: "fa fa-folder-open"
                },
                {
                    id: "qc",
                    title: "Quality Control",
                    acronym: "VB",
                    description: "",
                    icon: "fa fa-chart-bar"
                },
                {
                    id: "interpretation",
                    title: "Interpretation Methods",
                    acronym: "VB",
                    description: "",
                    icon: "fa fa-sync"
                },
                {
                    id: "variant-browser",
                    title: "Variant Browser",
                    acronym: "VB",
                    description: "",
                    icon: "fa fa-search"
                },
                {
                    id: "review",
                    title: "Interpretation Review",
                    acronym: "VB",
                    description: "",
                    icon: "fa fa-edit"
                },
                {
                    id: "report",
                    title: "Report",
                    acronym: "VB",
                    description: "",
                    disabled: true,
                    icon: "fa fa-file-alt"
                }
            ]
        };
    }

    render() {
        // Check Project exists
        if (!this.opencgaSession || !this.opencgaSession.project) {
            return html`

No project available to browse. Please login to continue

            `;
        }

        return html`

                ${this.clinicalAnalysis && this.clinicalAnalysis.id ? html`
                    <tool-header .title="${`${this._config.title}<span class="inverse"> Case ${this.clinicalAnalysis?.id} </span>` }" icon="${this._config.icon}"></tool-header>
                ` : html`
                    <tool-header .title="${this._config.title}" icon="${this._config.icon}"></tool-header>
                `}

                                ${this._config.tools && this._config.tools.map( item => html`

${item.title}

                                `)}

                        ${this._config.tools ? html`

                                <variant-interpreter-landing .opencgaSession="${this.opencgaSession}"
                                                             .clinicalAnalysis="${this.clinicalAnalysis}"
                                                             .config="${this._config}"
                                                             @selectClinicalAnalysis="${this.onClinicalAnalysis}">
                                </variant-interpreter-landing>

                                <variant-interpreter-qc .opencgaSession="${this.opencgaSession}"
                                                        .cellbaseClient="${this.cellbaseClient}"
                                                        .clinicalAnalysis="${this.clinicalAnalysis}"
                                                        .config="${this._config}">
                                </variant-interpreter-qc>

                                <variant-interpreter-interpretation .opencgaSession="${this.opencgaSession}"
                                                        .clinicalAnalysis="${this.clinicalAnalysis}"
                                                        .config="${this._config}">
                                </variant-interpreter-interpretation>

                                <opencga-variant-interpreter-genome-browser .opencgaSession="${this.opencgaSession}"
                                                                            .cellbaseClient="${this.cellbaseClient}"
                                                                            .clinicalAnalysis="${this.clinicalAnalysis}"
                                                                            .config="${this._config}">
                                </opencga-variant-interpreter-genome-browser>

                                ${this.clinicalAnalysis ?
                                    this.clinicalAnalysis.type.toUpperCase() === "SINGLE" || this.clinicalAnalysis.type.toUpperCase() === "FAMILY"
                                        ? html`
                                            <variant-interpreter-rd-browser .opencgaSession="${this.opencgaSession}"
                                                                            .clinicalAnalysis="${this.clinicalAnalysis}"
                                                                            .query="${this.interpretationSearchQuery}"
                                                                            .cellbaseClient="${this.cellbaseClient}"
                                                                            .populationFrequencies="${this._config.populationFrequencies}"
                                                                            .proteinSubstitutionScores="${this._config.proteinSubstitutionScores}"
                                                                            .consequenceTypes="${this._config.consequenceTypes}"
                                                                            @clinicalAnalysisUpdate="${this.onClinicalAnalysisUpdate}"
                                                                            @gene="${this.geneSelected}"
                                                                            @samplechange="${this.onSampleChange}">
                                            </variant-interpreter-rd-browser>`
                                        : html `
                                            <variant-interpreter-cancer-browser .opencgaSession="${this.opencgaSession}"
                                                                                .clinicalAnalysis="${this.clinicalAnalysis}"
                                                                                .query="${this.interpretationSearchQuery}"
                                                                                .cellbaseClient="${this.cellbaseClient}"
                                                                                .populationFrequencies="${this._config.populationFrequencies}"
                                                                                .proteinSubstitutionScores="${this._config.proteinSubstitutionScores}"
                                                                                .consequenceTypes="${this._config.consequenceTypes}"
                                                                                @clinicalAnalysisUpdate="${this.onClinicalAnalysisUpdate}"
                                                                                @gene="${this.geneSelected}">
                                            </variant-interpreter-cancer-browser>`
                                    : null
                                }

                                <variant-interpreter-review .opencgaSession="${this.opencgaSession}"
                                                            .clinicalAnalysis="${this.clinicalAnalysis}"
                                                            .cellbaseClient="${this.cellbaseClient}"
                                                            .populationFrequencies="${this._config.populationFrequencies}"
                                                            .proteinSubstitutionScores="${this._config.proteinSubstitutionScores}"
                                                            .consequenceTypes="${this._config.consequenceTypes}"
                                                            .config="${this._config}"
                                                            @gene="${this.geneSelected}"
                                                            @samplechange="${this.onSampleChange}">
                                 </variant-interpreter-review>

                                <variant-interpreter-report .opencgaSession="${this.opencgaSession}">
                                </variant-interpreter-report>

                        ` : null}

        `;
    }

}

customElements.define("variant-interpreter", VariantInterpreter);
<|endoftext|>


<commit_before>import angular from 'angular';

/**
 * Sets attribute with optional value.
 * Does not owerwrite.
 * @param {Array} nodes nodes
 * @param {String} attr  attribute name
 * @param {String} val   atrtibute value
 */
function addIfNotPresent(nodes, attr, val) {
  angular.forEach(nodes, (node) => {
    if (!node.getAttribute(attr)) {
      node.setAttribute(attr, val);
    }
  });
}

/**
 * Gets all ngModels from node
 */
function getNgModelNodes(node) {
  const query = '[ng-model], [data-ng-model]';

  return node.querySelectorAll(query);
}

/**
 * Adds attribute with optional value to all elements using ngModel directive.
 * Handles extras.skipNgModelAttrsManipulator
 * And does not overwrite attriutes
 *
 * @param  {String} template  Template provided by formly template manipulator
 * @param  {Object} options   Options provided by formly template manipulator
 * @param  {String} attrName  Attribute's name
 * @param  {String|undefined} Attribute's value (optional)
 * @return {String} result
 */
export function ngModelAttrsManipulator(template, options, attrName, attrValue) {
  const node = document.createElement('div');
  const skip = options.extras && options.extras.skipNgModelAttrsManipulator;

  if (skip === true) {
    return template;
  }
  node.innerHTML = template;
  const modelNodes = getNgModelNodes(node);

  if (!modelNodes || !modelNodes.length) {
    return template;
  }

  addIfNotPresent(modelNodes, attrName, attrValue);

  return node.innerHTML;
}
<commit_msg>feat(helpers): ngModelAttrsTransformer<commit_after>import angular from 'angular';

/**
 * Sets attribute with optional value.
 * Does not owerwrite.
 * @param {Array} nodes nodes
 * @param {String} attr  attribute name
 * @param {String} val   atrtibute value
 */
function addIfNotPresent(nodes, attr, val) {
  angular.forEach(nodes, (node) => {
    if (!node.getAttribute(attr)) {
      node.setAttribute(attr, val);
    }
  });
}

/**
 * Gets all ngModels from node
 */
function getNgModelNodes(node) {
  const query = '[ng-model], [data-ng-model]';

  return node.querySelectorAll(query);
}

/**
 * Adds attribute with optional value to all elements using ngModel directive.
 * Handles extras.skipNgModelAttrsManipulator
 * And does not overwrite attriutes
 *
 * @param  {String} template  Template provided by formly template manipulator
 * @param  {Object} options   Options provided by formly template manipulator
 * @param  {String} attrName  Attribute's name
 * @param  {String|undefined} Attribute's value (optional)
 * @return {String} result
 */
export function ngModelAttrsManipulator(template, options, attrName, attrValue) {
  const node = document.createElement('div');
  const skip = options.extras && options.extras.skipNgModelAttrsManipulator;

  if (skip === true) {
    return template;
  }
  node.innerHTML = template;
  const modelNodes = getNgModelNodes(node);

  if (!modelNodes || !modelNodes.length) {
    return template;
  }

  addIfNotPresent(modelNodes, attrName, attrValue);

  return node.innerHTML;
}

/**
 * Adds ngModelAttr to the field when specified condition is true.
 * @param  {Array} fields    fields provided by formly's fieldTranform
 * @param  {Funcion} condition with field as only parameter
 * @param  {String} name      ngModelAttr's name
 * @param  {Object} settings  ngModelAttr's settings
 * @return {Array}           returns fields
 */
export function ngModelAttrsTransformer(fields, condition, name, settings) {
  (fields || []).forEach((field) => {
    if (condition(field) === true) {
      if (!field.ngModelAttrs) {
        field.ngModelAttrs = {};
      }

      if (typeof field.templateOptions[name] !== 'undefined') {
        field.ngModelAttrs[name] = settings;
      }
    }
  });

  return fields;
}
<|endoftext|>