import {
  dofetch3
} from "./chunk-7EMWHCVW.js";
import {
  DNA_METHYLATION,
  GENE_EXPRESSION,
  PROTEOME_DAP,
  SINGLECELL_CELLTYPE
} from "./chunk-NOEAT6CX.js";
import {
  rgb
} from "./chunk-OMR2DT66.js";

// plots/volcano/colors.ts
function getGroupColors(config) {
  const groups = config?.samplelst?.groups;
  const termValues = config?.tw?.term?.values;
  const rawDown = termValues?.[groups?.[0]?.name]?.color || "red";
  const rawUp = termValues?.[groups?.[1]?.name]?.color || "blue";
  return {
    controlColor: toHex(rawDown, "red"),
    caseColor: toHex(rawUp, "blue")
  };
}
function toHex(color, fallback) {
  const c = rgb(color || fallback);
  return c.displayable() ? c.formatHex() : rgb(fallback).formatHex();
}

// plots/volcano/model/VolcanoModel.ts
var VolcanoModel = class {
  constructor(app, termType) {
    this.app = app;
    this.termType = termType;
  }
  /** May use mapper instead as more termTypes are added */
  async getData(config, settings) {
    this.config = config;
    this.settings = settings;
    if (this.termType === GENE_EXPRESSION) {
      const body = await this.getGERequestBody();
      const response = await dofetch3("termdb/DE", { body });
      if (response && !response.error) response.daRequest = body;
      return response;
    }
    if (this.termType === DNA_METHYLATION) {
      const body = await this.getDMRequestBody();
      const response = await dofetch3("termdb/diffMeth", { body });
      if (response && !response.error) response.daRequest = body;
      return response;
    }
    if (this.termType === SINGLECELL_CELLTYPE) {
      const body = await this.getSCCTRequestBody();
      return await dofetch3("termdb/singlecellDEgenes", { body });
    }
    if (this.termType === PROTEOME_DAP) {
      const body = this.getDapRequestBody();
      return await dofetch3("termdb/dapVolcano", { body });
    }
    throw new Error(`Volcano plot does not support route for termType='${this.termType}'`);
  }
  //Gene expression
  async getGERequestBody() {
    await this.getOtherSamples(this.config.samplelst);
    const state = this.app.getState();
    const body = {
      kind: "DE",
      genome: this.app.vocabApi.vocab.genome,
      dslabel: this.app.vocabApi.vocab.dslabel,
      method: this.settings.method,
      min_count: this.settings.minCount,
      min_total_count: this.settings.minTotalCount,
      samplelst: this.config.samplelst,
      filter: state.termfilter.filter,
      filter0: state.termfilter.filter0,
      cpm_cutoff: this.settings.cpmCutoff,
      volcanoRender: this.getVolcanoRender()
    };
    this.addConfounderTw(body);
    return body;
  }
  //DNA methylation
  async getDMRequestBody() {
    await this.getOtherSamples(this.config.samplelst);
    const state = this.app.getState();
    const body = {
      kind: "DM",
      genome: this.app.vocabApi.vocab.genome,
      dslabel: this.app.vocabApi.vocab.dslabel,
      samplelst: this.config.samplelst,
      filter: state.termfilter.filter,
      filter0: state.termfilter.filter0,
      min_samples_per_group: this.settings.minSamplesPerGroup,
      volcanoRender: this.getVolcanoRender()
    };
    this.addConfounderTw(body);
    return body;
  }
  /** Parameters telling the server to run the `volcano` Rust renderer and return a
   * volcano PNG + top-significant rows instead of the full dot list. */
  getVolcanoRender() {
    const dotRadius = Math.max(this.settings.width, this.settings.height) / 80;
    const { caseColor, controlColor } = getGroupColors(this.config);
    return {
      significanceThresholds: {
        pValueCutoff: this.settings.pValue,
        pValueType: this.settings.pValueType,
        foldChangeCutoff: this.settings.foldChangeCutoff
      },
      pixelWidth: this.settings.width,
      pixelHeight: this.settings.height,
      colorSignificant: toHex(this.settings.defaultSignColor, "red"),
      colorSignificantUp: caseColor,
      colorSignificantDown: controlColor,
      colorNonsignificant: toHex(this.settings.defaultNonSignColor, "black"),
      dotRadius,
      maxInteractiveDots: this.settings.maxInteractiveDots,
      // Render the PNG at device-pixel resolution so it stays sharp on
      // retina screens. The server reports the plot extent in CSS-space,
      // so SVG overlay coords are unaffected.
      //
      // Oversample by 2× so the PNG also stays sharp when the user
      // *zooms in after* the initial render (the captured DPR is frozen
      // at fetch time — bigger headroom = more tolerable post-render
      // zoom before pixelation appears). The server clamp keeps the
      // bitmap memory bounded.
      devicePixelRatio: (typeof window !== "undefined" ? window.devicePixelRatio : 1) * 2
    };
  }
  //This is a workaround until the server can accept an arr of confounder tws
  addConfounderTw(body) {
    const confounders = this.config?.confounderTws;
    if (confounders?.length) {
      body.tw = this.config.confounderTws[0];
      if (confounders.length > 1) body.tw2 = this.config.confounderTws[1];
    }
  }
  //Single cell cell type
  getSCCTRequestBody() {
    const body = {
      genome: this.app.vocabApi.vocab.genome,
      dslabel: this.app.vocabApi.vocab.dslabel,
      sample: this.config.sample,
      termId: this.config.termId,
      categoryName: this.config.categoryName,
      volcanoRender: this.getVolcanoRender()
    };
    return body;
  }
  getDapRequestBody() {
    const { organism, assay, cohort } = this.config.proteomeDetails;
    return {
      genome: this.app.vocabApi.vocab.genome,
      dslabel: this.app.vocabApi.vocab.dslabel,
      organism,
      assay,
      cohort,
      volcanoRender: this.getVolcanoRender()
    };
  }
  /** retrieve the sampleId/sampleName for samples in
   * the "others" group instead of using {in: false} */
  async getOtherSamples(samplelst) {
    const othersSamplesGroup = samplelst.groups.find((g) => !g.in);
    if (!othersSamplesGroup) return;
    const state = this.app.getState();
    const samplesGroup = samplelst.groups.find((g) => g.in);
    othersSamplesGroup.values = [];
    for (const s of await this.app.vocabApi.getFilteredSampleList(state.termfilter.filter)) {
      if (samplesGroup.values.indexOf((i) => i.sampleId == s.id) == -1) {
        othersSamplesGroup.values.push({ sampleId: s.id, sample: s.name });
      }
    }
    othersSamplesGroup.in = true;
  }
};

export {
  getGroupColors,
  VolcanoModel
};
//# sourceMappingURL=chunk-UOVALHAJ.js.map
