import {
  VolcanoModel
} from "./chunk-UOVALHAJ.js";
import {
  PlotBase,
  axisstyle,
  controlsInit,
  getCombinedTermFilter,
  getDefaultVolcanoSettings,
  renderTable,
  sayerror,
  table2col
} from "./chunk-SA7APTJR.js";
import {
  Menu
} from "./chunk-HYOEWQ5P.js";
import {
  dofetch3
} from "./chunk-7EMWHCVW.js";
import {
  copyMerge,
  getCompInit
} from "./chunk-M3J4MINX.js";
import {
  PROTEOME_DAP,
  SINGLECELL_CELLTYPE
} from "./chunk-NOEAT6CX.js";
import {
  axisBottom,
  axisLeft
} from "./chunk-LOZEKOES.js";
import {
  linear
} from "./chunk-OAWQ6LOO.js";
import {
  roundValueAuto
} from "./chunk-TLT4YIG3.js";

// plots/gsea.js
var tip = new Menu();
var gsea = class _gsea extends PlotBase {
  static type = "gsea";
  constructor(opts) {
    super(opts);
    this.type = _gsea.type;
    this.opts = opts;
    this.components = {
      controls: {}
    };
    const controlsDiv = typeof opts.controls == "object" ? opts.controls : opts.holder.append("div").style("display", "inline-block");
    const main = opts.holder.append("div").style("display", "inline-block");
    const actionsDiv = main.append("div").attr("data-testid", "sjpp-gsea-actions").style("margin", "10px").style("text-align", "left");
    const loadingDiv = main.append("div").attr("data-testid", "sjpp-gsea-loading").style("text-align", "center").style("display", "none").style("margin", "10px").style("text-align", "left").text("Loading...");
    const holder = main.append("div").style("margin-left", "50px").style("display", "inline-block").attr("data-testid", "sjpp-gsea-holder");
    const detailsDiv = main.append("div").attr("data-testid", "sjpp-gsea-details").style("display", "inline-block").style("vertical-align", "top").style("margin-top", "50px");
    const tableDiv = main.append("div").style("margin", "10px").attr("data-testid", "sjpp-gsea-results-table");
    this.dom = {
      holder,
      header: opts.header,
      actionsDiv,
      loadingDiv,
      controlsDiv,
      detailsDiv,
      tableDiv
    };
  }
  async setControls() {
    this.dom.controlsDiv.selectAll("*").remove();
    const inputs = [
      {
        label: "Minimum Gene Set Size Filter Cutoff",
        type: "number",
        chartType: "gsea",
        settingsKey: "min_gene_set_size_cutoff",
        title: "Minimum Gene set size cutoff. Helps in filtering out small gene sets",
        min: 0
      },
      {
        label: "Maximum Gene Set Size Filter Cutoff",
        type: "number",
        chartType: "gsea",
        settingsKey: "max_gene_set_size_cutoff",
        title: "Maximum Gene set size cutoff. Helps in filtering out large gene sets",
        max: 25e3
      },
      {
        label: "Filter Non-coding Genes",
        type: "checkbox",
        chartType: "gsea",
        settingsKey: "filter_non_coding_genes",
        title: "Filter non-coding genes",
        boxLabel: ""
      },
      {
        label: "FDR or Top Gene Sets",
        type: "radio",
        chartType: "gsea",
        settingsKey: "fdr_or_top",
        title: "Toggle between FDR cutoff and top gene sets in ascending order of FDR",
        options: [
          { label: "FDR", value: "fdr" },
          { label: "Top Gene Sets", value: "top" }
        ]
      }
    ];
    if (JSON.parse(sessionStorage.getItem("optionalFeatures")).gsea_test) {
      inputs.push({
        label: "GSEA method",
        type: "radio",
        chartType: "gsea",
        settingsKey: "gsea_method",
        title: "Toggle between blitzgsea and CERNO method",
        options: [
          { label: "blitzgsea", value: "blitzgsea" },
          { label: "CERNO", value: "cerno" }
        ]
      });
    }
    if (this.settings.gsea_method == "blitzgsea") {
      inputs.push({
        label: "Number of Permutations",
        type: "number",
        chartType: "gsea",
        settingsKey: "num_permutations",
        title: "Number of permutations to be used for GSEA. Higher number increases accuracy but also compute time.",
        min: 0,
        max: 4e4
        // Setting it to pretty lenient limit for testing
      });
    }
    if (this.settings.fdr_or_top == "fdr") {
      inputs.push({
        label: "FDR Filter Cutoff (Linear Scale)",
        type: "number",
        chartType: "gsea",
        settingsKey: "fdr_cutoff",
        title: "P-value significance",
        min: 0,
        max: 1
      });
    } else if (this.settings.fdr_or_top == "top") {
      inputs.push({
        label: "Number of top Gene Sets by FDR",
        type: "number",
        chartType: "gsea",
        settingsKey: "top_genesets",
        title: "Number of top gene sets to be displayed in ascending order of FDR",
        min: 0,
        max: 5e3
      });
    } else {
      throw "unknown FDR/top option";
    }
    this.components.controls = await controlsInit({
      app: this.app,
      id: this.id,
      holder: this.dom.controlsDiv,
      inputs
    });
    this.components.controls.on("downloadClick.gsea", () => {
      if (!this.imageUrl) return alert("No image to download");
      const dataUrl = this.imageUrl;
      const downloadImgName = `${this.state.config.gsea_params.geneset_name || ""}_GSEA_IMG`;
      const a = document.createElement("a");
      document.body.appendChild(a);
      a.addEventListener(
        "click",
        () => {
          a.download = downloadImgName + ".png";
          a.href = dataUrl;
          document.body.removeChild(a);
        },
        false
      );
      a.click();
    });
  }
  getState(appState) {
    const config = appState.plots.find((p) => p.id === this.id);
    if (!config) throw `No plot with id='${this.id}' found`;
    const parentConfig = appState.plots.find((p) => p.id === this.parentId);
    const termfilter = getCombinedTermFilter(appState, config.filter || parentConfig?.filter);
    return {
      config,
      termfilter
    };
  }
  /** This allows the gsea to run independently. If the DE data
   * was already requested (e.g. in the DA from the volcano plot),
   * the cached response returns rather than running the DE
   * route again.
   *
   * Also allows loading the gsea from a mass session file without
   * error. */
  async init(appState) {
    const config = appState.plots.find((p) => p.id === this.id);
    if (!config.gsea_params) {
      try {
        if (config.termType === PROTEOME_DAP) {
          await this.app.save({
            type: "plot_edit",
            id: this.id,
            config: {
              gsea_params: {
                dapParams: config.proteomeDetails,
                genome: this.app.vocabApi.opts.state.vocab.genome,
                dslabel: this.app.vocabApi.vocab.dslabel
              }
            }
          });
        } else if (config.termType === SINGLECELL_CELLTYPE) {
          const body = {
            genome: this.app.vocabApi.vocab.genome,
            dslabel: this.app.vocabApi.vocab.dslabel,
            sample: config.sample,
            termId: config.termId,
            categoryName: config.categoryName
          };
          const response = await dofetch3("termdb/singlecellDEgenes", { body });
          if (response.error) throw response.error;
          if (!Array.isArray(response.data) || response.data.length === 0) throw "No DE genes returned for this cluster";
          const genes = [];
          const fold_change = [];
          for (const g of response.data) {
            genes.push(g.gene_name);
            fold_change.push(g.fold_change);
          }
          await this.app.save({
            type: "plot_edit",
            id: this.id,
            config: {
              gsea_params: {
                genes,
                fold_change,
                genes_length: genes.length,
                genome: this.app.vocabApi.opts.state.vocab.genome
              }
            }
          });
        } else {
          const volcanoSettings = config.settings?.volcano || getDefaultVolcanoSettings({}, { termType: "geneExpression" });
          const model = new VolcanoModel(this.app, config.termType);
          const response = await model.getData(config, volcanoSettings);
          if (!response?.data?.cacheId || response.error) {
            throw response.error || "No DE cacheId returned from volcano model";
          }
          await this.app.save({
            type: "plot_edit",
            id: this.id,
            config: {
              gsea_params: {
                cacheId: response.data.cacheId,
                // Snapshot of the DE request so the server can regenerate
                // the cache if this GSEA request lands on a peer node or
                // arrives after the cache TTL has expired.
                daRequest: response.daRequest,
                genes_length: response.data.totalRows,
                genome: this.app.vocabApi.opts.state.vocab.genome,
                // Sending dslabel at the top level makes the global
                // auth middleware populate clientAuthResult on this
                // request the same way it did for the volcano
                // request, so the server can re-apply the same
                // auth-filter injection to daRequest before hashing.
                dslabel: this.app.vocabApi.vocab.dslabel
              }
            }
          });
        }
      } catch (e) {
        if (e instanceof Error) console.error(e.message || e);
        else if (e.stack) console.log(e.stack);
        throw e;
      }
    }
  }
  reactsTo(action) {
    if (action.type.startsWith("plot_")) {
      return (action.id === this.id || action.id == this.parentId) && (!action.config?.childType || action.config?.childType == this.type);
    }
  }
  async main() {
    const config = this.app.getState().plots.find((p) => p.id === this.id);
    this.config = structuredClone(config);
    if (this.config.chartType != this.type && this.config.childType != this.type) return;
    this.settings = this.config.settings.gsea;
    this.imageUrl = null;
    await this.setControls();
    if (this.dom.header) {
      const geneCount = this.config.gsea_params.genes_length ?? this.config.gsea_params.genes?.length ?? 0;
      this.dom.header.html(
        geneCount + ' genes <span style="font-size:.8em;opacity:.7">GENE SET ENRICHMENT ANALYSIS</span>'
      );
    }
    render_gsea(this);
  }
};
async function renderPathwayDropdown(self) {
  const settings = structuredClone(self.settings);
  const pathwayOpts = structuredClone(self.app.opts.genome.termdbs.msigdb.analysisGenesetGroups);
  if (JSON.parse(sessionStorage.getItem("optionalFeatures")).gsea_test && self.settings.gsea_method == "blitzgsea") {
    pathwayOpts.push(
      { label: "REACTOME (blitzgsea)", value: "REACTOME--blitzgsea" },
      { label: "KEGG (blitzgsea)", value: "KEGG--blitzgsea" },
      { label: "WikiPathways (blitzgsea)", value: "WikiPathways--blitzgsea" }
    );
  }
  if (settings.pathway) {
    pathwayOpts.shift();
    pathwayOpts.find((opt) => opt.value == settings.pathway).selected = true;
  }
  self.dom.actionsDiv.append("span").attr("data-testid", "sjpp-gsea-pathway").style("margin-right", "10px").text("Select a gene set group:");
  const dropdown = self.dom.actionsDiv.append("select").on("change", (event) => {
    if (!settings.pathway) {
      const placeholder = dropdown.select('option[value="-"]');
      placeholder.remove();
      pathwayOpts.shift();
    }
    const idx = event.target.selectedIndex;
    settings.pathway = pathwayOpts[idx].value;
    self.app.dispatch({
      type: "plot_edit",
      id: self.id,
      config: {
        //Need to clear the gsea_params completely
        gsea_params: {
          geneset_name: null,
          pathway: pathwayOpts[idx].value
        },
        highlightGenes: [],
        settings: {
          gsea: settings
        }
      }
    });
  });
  for (const opt of pathwayOpts) {
    dropdown.append("option").text(opt.label).attr("value", opt.value).attr("selected", opt.selected ? true : null);
  }
}
async function render_gsea(self) {
  self.dom.actionsDiv.selectAll("*").remove();
  renderPathwayDropdown(self);
  if (self.settings.pathway == "-" || self.settings.pathway == void 0) return;
  self.dom.detailsDiv.selectAll("*").remove();
  self.dom.holder.selectAll("*").remove();
  self.dom.tableDiv.selectAll("*").remove();
  self.config.gsea_params.geneSetGroup = self.settings.pathway;
  self.config.gsea_params.filter_non_coding_genes = self.settings.filter_non_coding_genes;
  self.config.gsea_params.num_permutations = self.settings.num_permutations;
  let output;
  try {
    const p = self.config.gsea_params;
    const body = {
      genome: p.genome,
      geneSetGroup: self.settings.pathway,
      filter_non_coding_genes: self.settings.filter_non_coding_genes,
      method: self.settings.gsea_method
    };
    if (p.cacheId) {
      body.cacheId = p.cacheId;
      if (p.daRequest) body.daRequest = p.daRequest;
      if (p.dslabel) body.dslabel = p.dslabel;
    } else if (p.dapParams) {
      body.dapParams = p.dapParams;
      body.dslabel = p.dslabel;
    } else {
      body.genes = p.genes;
      body.fold_change = p.fold_change;
    }
    if (self.settings.gsea_method == "blitzgsea") {
      body.num_permutations = self.settings.num_permutations;
    }
    output = await rungsea(body, self.dom);
    if (output.error) {
      throw Object.assign(new Error(output.error), { code: output.code });
    }
  } catch (e) {
    self.dom.holder.selectAll("*").remove();
    const msg = String(e?.message || e);
    if (e?.code === "CACHE_BUSY") {
      if (window.confirm(msg)) render_gsea(self);
      return;
    }
    const userMsg = /daCacheMissing|ENOENT|no such file/i.test(msg) ? "The differential-analysis cache for this GSEA is no longer available. Reopen the volcano plot to regenerate it." : msg;
    sayerror(self.dom.holder, userMsg);
    return;
  }
  if (self.config.gsea_params.geneset_name != null) {
    try {
      if (self.settings.gsea_method == "blitzgsea") {
        self.config.gsea_params.method = self.settings.gsea_method;
        const image = await rungsea(self.config.gsea_params, self.dom);
        if (image.error) throw image.error;
        self.imageUrl = URL.createObjectURL(image);
        const png_width = 600;
        const png_height = 400;
        self.dom.holder.append("img").attr("width", png_width).attr("height", png_height).attr("src", self.imageUrl);
      } else if (self.settings.gsea_method == "cerno") {
        if (!self.rankedDE && (self.config.gsea_params.cacheId || self.config.gsea_params.dapParams)) {
          const fetchBody = {
            genome: self.config.gsea_params.genome,
            dslabel: self.config.gsea_params.dslabel,
            fetchDE: true,
            geneSetGroup: "-",
            filter_non_coding_genes: false,
            method: "cerno"
          };
          if (self.config.gsea_params.cacheId) {
            fetchBody.cacheId = self.config.gsea_params.cacheId;
            fetchBody.daRequest = self.config.gsea_params.daRequest;
          } else if (self.config.gsea_params.dapParams) {
            fetchBody.dapParams = self.config.gsea_params.dapParams;
          }
          const deResp = await dofetch3("genesetEnrichment", {
            body: fetchBody
          });
          if (deResp.error) throw Object.assign(new Error(deResp.error), { code: deResp.code });
          self.rankedDE = deResp.data;
        }
        render_cerno_plot(self, output);
      } else {
        throw "Unknown method:" + self.settings.gsea_method;
      }
    } catch (e) {
      self.dom.holder.selectAll("*").remove();
      const msg = String(e?.message || e);
      if (e?.code === "CACHE_BUSY") {
        if (window.confirm(msg)) render_gsea(self);
        return;
      }
      const userMsg = /daCacheMissing|ENOENT|no such file/i.test(msg) ? "The differential-analysis cache for this GSEA is no longer available. Reopen the volcano plot to regenerate it." : msg;
      sayerror(self.dom.holder, userMsg);
      return;
    }
  }
  const table_stats = table2col({ holder: self.dom.detailsDiv.attr("data-testid", "sjpp-gsea-stats") });
  const [t1, t2] = table_stats.addRow();
  t2.style("text-align", "center").style("font-size", "0.8em").style("opacity", "0.8").text("COUNT");
  let addStats;
  if (self.settings.gsea_method == "blitzgsea") {
    addStats = [
      {
        label: "Gene sets analyzed",
        values: Object.keys(output.data).length
      }
    ];
  } else if (self.settings.gsea_method == "cerno") {
    addStats = [
      {
        label: "Gene sets analyzed",
        values: Object.keys(output).length
      }
    ];
  } else {
    throw "Unknown method:" + self.settings.gsea_method;
  }
  for (const dataRow of addStats) {
    const [td1, td2] = table_stats.addRow();
    td1.text(dataRow.label);
    td2.style("text-align", "end").text(dataRow.values);
  }
  self.gsea_table_rows = [];
  let output_keys;
  if (self.settings.gsea_method == "blitzgsea") {
    output_keys = Object.entries(output.data).map(([key, value]) => {
      return { key, value };
    });
  } else if (self.settings.gsea_method == "cerno") {
    output_keys = Object.entries(output).map(([key, value]) => {
      return { key, value };
    });
  } else {
    throw "Unknown method:" + self.settings.gsea_method;
  }
  if (self.settings.fdr_or_top == "top") {
    output_keys.sort((i, j) => Number(i.value.fdr) - Number(j.value.fdr));
    const top_genesets = Math.min(self.settings.top_genesets, output_keys.length);
    for (let iter = 0; iter < top_genesets; iter++) {
      if (self.settings.max_gene_set_size_cutoff >= output_keys[iter].value.geneset_size && self.settings.min_gene_set_size_cutoff <= output_keys[iter].value.geneset_size) {
        setResultsRows(output_keys, iter, self);
      }
    }
  } else if (self.settings.fdr_or_top == "fdr") {
    for (let iter = 0; iter < output_keys.length; iter++) {
      if (self.settings.fdr_cutoff >= output_keys[iter].value.fdr && self.settings.max_gene_set_size_cutoff >= output_keys[iter].value.geneset_size && self.settings.min_gene_set_size_cutoff <= output_keys[iter].value.geneset_size) {
        setResultsRows(output_keys, iter, self);
      }
    }
  }
  self.dom.tableDiv.selectAll("*").remove();
  const d_gsea = self.dom.tableDiv.append("div");
  self.gsea_table_cols = [];
  if (self.settings.gsea_method == "blitzgsea") {
    self.gsea_table_cols = [
      { label: "Gene Set", sortable: true },
      //{ label: 'Enrichment Score' },
      { label: "Normalized Enrichment Score", barplot: { axisWidth: 200 }, sortable: true },
      { label: "Gene Set Size", sortable: true },
      { label: "P value", sortable: true },
      //{ label: 'Sidak' },
      { label: "FDR", sortable: true },
      { label: "Leading Edge" }
    ];
  } else if (self.settings.gsea_method == "cerno") {
    self.gsea_table_cols = [
      { label: "Gene Set", sortable: true },
      { label: "Area Under Curve", barplot: { axisWidth: 200 }, sortable: true },
      { label: "Enrichment Score", barplot: { axisWidth: 200 }, sortable: true },
      { label: "Total Gene Set Size", sortable: true },
      { label: "P value", sortable: true },
      { label: "FDR", sortable: true },
      { label: "Gene Set Hits" }
    ];
  } else {
    throw "Unknown method:" + self.settings.gsea_method;
  }
  let download = {};
  if (self.config.chartType == "differentialAnalysis") {
    self.dom.detailsDiv.append("button").style("margin-left", "10px").style(
      "display",
      self.config.chartType == "differentialAnalysis" && self.config.gsea_params.geneset_name == null ? "none" : "block"
    ).attr("aria-label", "Highlight genes in the volcano plot").text("Highlight genes").on("click", () => {
      self.app.dispatch({
        type: "plot_edit",
        id: self.id,
        config: {
          childType: "volcano",
          highlightedData: self.config.highlightGenes
        }
      });
    });
  }
  if (self.state.config.downloadFilename) download.fileName = self.state.config.downloadFilename;
  const geneSetIdx = self.gsea_table_rows.findIndex((row) => row[0].value == self.config.gsea_params.geneset_name);
  const selectedRows = geneSetIdx > -1 ? [geneSetIdx] : [];
  renderTable({
    download,
    columns: self.gsea_table_cols,
    rows: self.gsea_table_rows,
    div: d_gsea,
    showLines: true,
    maxHeight: "30vh",
    singleMode: true,
    resize: true,
    header: { allowSort: true },
    selectedRows,
    noButtonCallback: async (index) => {
      const config = {
        gsea_params: {
          geneset_name: self.gsea_table_rows[index][0].value
        }
      };
      if (self.config.chartType == "differentialAnalysis") {
        let genes;
        if (self.settings.gsea_method == "blitzgsea") {
          genes = [...self.gsea_table_rows[index][5].value.split(",")];
        } else if (self.settings.gsea_method == "cerno") {
          genes = [...self.gsea_table_rows[index][6].value.split(",")];
        } else {
          throw "Unknown method:" + self.settings.gsea_method;
        }
        if (genes) config.highlightGenes = genes;
      }
      await self.app.dispatch({
        type: "plot_edit",
        id: self.id,
        config
      });
    }
  });
}
function setResultsRows(output_keys, iter, self) {
  const pathway_name = output_keys[iter].key;
  const pval = output_keys[iter].value.pval ? roundValueAuto(output_keys[iter].value.pval) : output_keys[iter].value.pval;
  const fdr = output_keys[iter].value.fdr ? roundValueAuto(output_keys[iter].value.fdr) : output_keys[iter].value.fdr;
  if (self.settings.gsea_method == "blitzgsea") {
    const nes = output_keys[iter].value.nes ? roundValueAuto(output_keys[iter].value.nes) : output_keys[iter].value.nes;
    self.gsea_table_rows.push([
      { value: pathway_name },
      { value: nes },
      { value: output_keys[iter].value.geneset_size },
      { value: pval },
      //{ value: sidak },
      { value: fdr },
      { value: output_keys[iter].value.leading_edge }
    ]);
  } else if (self.settings.gsea_method == "cerno") {
    const auc = output_keys[iter].value.auc ? roundValueAuto(output_keys[iter].value.auc) : output_keys[iter].value.auc;
    const es = output_keys[iter].value.es ? roundValueAuto(output_keys[iter].value.es) : output_keys[iter].value.es;
    self.gsea_table_rows.push([
      { value: pathway_name },
      { value: auc },
      { value: es },
      { value: output_keys[iter].value.geneset_size },
      { value: pval },
      { value: fdr },
      { value: output_keys[iter].value.leading_edge }
    ]);
  } else {
    throw "Unknown method:" + self.settings.gsea_method;
  }
}
function render_cerno_plot(self, cerno_output) {
  const holder = self.dom.holder;
  holder.selectAll("*").remove();
  const svg_width = 400;
  const svg_height = 400;
  const svg = holder.append("svg").attr("width", svg_width).attr("height", svg_height);
  const toppad = 20;
  const rightpad = 5;
  const yaxisw = 50;
  const xaxish = 50;
  const yaxisg = svg.append("g");
  const xaxisg = svg.append("g");
  const xpad = 50;
  const ypad = 100;
  const rankedDE = self.rankedDE || self.config.gsea_params;
  const DE_output = [];
  for (let i = 0; i < rankedDE.genes.length; i++) {
    const item = { gene: rankedDE.genes[i], fold_change: rankedDE.fold_change[i] };
    DE_output.push(item);
  }
  DE_output.sort((i, j) => j.fold_change - i.fold_change);
  const xscale = linear().domain([0, DE_output.length]).range([xpad, svg_width - rightpad]);
  const yscale = linear().domain([100, 0]).range([toppad, svg_height - ypad]);
  yaxisg.attr("transform", "translate(" + xpad + ",0)");
  xaxisg.attr("transform", "translate(0," + (svg_height - ypad) + ")");
  const xlab = svg.append("text").text("Gene list").attr("fill", "black").attr("text-anchor", "start").attr("transform", "translate(" + xscale(DE_output.length / 3) + "," + (svg_height - ypad + 2 * toppad) + ")");
  const ylab = svg.append("text").text("Percentage of gene set").attr("fill", "black").attr("text-anchor", "middle").attr("y", xpad / 2).attr("x", -svg_width / 2.5).attr("transform", "rotate(-90)");
  let fontSize = 30;
  const title = svg.append("text").text(self.config.gsea_params.geneset_name).attr("fill", "black").attr("text-anchor", "start").attr("font-size", fontSize + "px").attr("transform", "translate(" + xpad + "," + toppad / 2 + ")");
  let title_bbox = title.node().getBBox();
  while (title_bbox.width > svg_width - xpad || title_bbox.height > toppad * 3.5 / 5) {
    fontSize -= 1;
    title.node().setAttribute("font-size", fontSize + "px");
    title_bbox = title.node().getBBox();
  }
  const auc = cerno_output[self.config.gsea_params.geneset_name].auc;
  if (typeof auc === "number") {
    let auc_pos;
    if (auc >= 0.5) {
      auc_pos = xscale(DE_output.length * 3 / 3.5) + "," + (svg_height - ypad * 1.5);
    } else {
      auc_pos = xscale(DE_output.length * 0.8 / 4.5) + "," + (svg_height - ypad * 3);
    }
    const auc_text = svg.append("text").text("AUC=" + roundValueAuto(auc)).attr("fill", "black").attr("text-anchor", "middle").attr("transform", "translate(" + auc_pos + ")");
  } else {
    throw "AUC not a number:" + auc;
  }
  axisstyle({
    axis: yaxisg.call(axisLeft().scale(yscale)),
    color: "black",
    showline: true,
    fontsize: "10"
  });
  axisstyle({
    axis: xaxisg.call(axisBottom().scale(xscale)),
    color: "black",
    showline: true,
    fontsize: "10"
  });
  if (Object.keys(cerno_output).includes(self.config.gsea_params.geneset_name)) {
    const hit_genes = cerno_output[self.config.gsea_params.geneset_name].leading_edge.split(",");
    const y_increment = 100 / hit_genes.length;
    const lines = svg.append("g");
    let y_iter = 100;
    for (let i = 0; i < DE_output.length; i++) {
      const y_old = y_iter;
      if (hit_genes.includes(DE_output[i].gene)) {
        y_iter = y_iter - y_increment;
        lines.append("line").style("stroke", "red").attr("x1", xscale(i)).attr("y1", svg_height).attr("x2", xscale(i)).attr("y2", svg_height - ypad + 2.5 * toppad);
      }
      lines.append("line").style("stroke", "red").attr("x1", xscale(i)).attr("y1", yscale(100 - y_old)).attr("x2", xscale(i + 1)).attr("y2", yscale(100 - y_iter));
    }
  } else {
    throw "${self.config.gsea_params.geneset_name} not found";
  }
}
function getDefaultGseaSettings(overrides = {}) {
  const defaults = {
    fdr_cutoff: 0.05,
    num_permutations: 1e3,
    top_genesets: 40,
    pathway: void 0,
    geneset_name: null,
    min_gene_set_size_cutoff: 0,
    max_gene_set_size_cutoff: 2e4,
    filter_non_coding_genes: true,
    fdr_or_top: "top",
    gsea_method: "blitzgsea"
  };
  if (JSON.parse(sessionStorage.getItem("optionalFeatures")).gsea_test) {
    defaults.gsea_method = "cerno";
  }
  return Object.assign(defaults, overrides);
}
async function getPlotConfig(opts, app) {
  try {
    const config = {
      //idea for fixing nav button
      //samplelst: { groups: app.opts.state.groups}
      settings: {
        gsea: getDefaultGseaSettings(opts.overrides)
      }
    };
    return copyMerge(config, opts);
  } catch (e) {
    throw `${e} [gsea getPlotConfig()]`;
  }
}
var gseaInit = getCompInit(gsea);
var componentInit = gseaInit;
function makeChartBtnMenu(holder, chartsInstance) {
  chartsInstance.prepPlot({
    config: {
      chartType: "gsea"
    }
  });
}
async function rungsea(body, dom) {
  dom.actionsDiv.style("display", "none");
  dom.loadingDiv.style("display", "block");
  const data = await dofetch3("genesetEnrichment", { body });
  dom.loadingDiv.style("display", "none");
  dom.actionsDiv.style("display", "block");
  return data;
}

export {
  getDefaultGseaSettings,
  getPlotConfig,
  gseaInit,
  componentInit,
  makeChartBtnMenu
};
//# sourceMappingURL=chunk-VHOEJBFP.js.map
