<commit_before>﻿/// Definitions of plug-in types and interfaces.
module PluginTypes
open Amyris.ErrorHandling
open commonTypes
open commandConfig
open Amyris.Bio
open constants
open LegacyParseTypes
open pragmaTypes
open AstTypes
open RefGenome
open Amyris.Bio.IO.CodonUsage
open utils
open Amyris.Dna

/// Interface specification for plugins that want to inject command line arguments and
/// be configured from the command line.
type IConfigurable<'T> =
    /// Return the list of the names of command line arguments this behavior accepts.
    abstract member ProvidedArgs : unit -> CmdLineArgSpec list
    /// Configure this behavior and return a configured version, allowing for immutable behaviors.
    abstract member Configure : ParsedCmdLineArg -> 'T
    /// Configure this behavior using the built-in compiler options.
    /// This enables sharing of items like the lib directory, verbose flag, etc.
    abstract member ConfigureFromOptions : ParsedOptions -> 'T

// =======================
// plugin behavior defintion for codon cache and optimization
// =======================

type CodonOptTask =
   {verbose:bool;
    seedOverride:int option;
    refGenome:GenomeDef;
    aminoAcidSequence:string}

type ICodonProvider =
    /// Allow codon opt providers to add command line args and be configurable.
    inherit IConfigurable<ICodonProvider>

    /// Codon optimizers use the pragma environment to configure themselves locally.
    abstract member Setup : PragmaCollection -> ICodonProvider

    ///<summary>Perform codon optimization using a particular reference genome on a string
    /// representing a protein sequence, returning a
    /// codon-optimized version.  Optionally override the RNG seed for this particular run, as well
    /// as set verbosity.
    ///</summary>
    // FIXME: this should both accept and return a domain type from Amyris.Bio.  May need to
    // define a domain type for AA sequences to match Amyris.Dna
    abstract member DoCodonOpt : CodonOptTask -> Dna

    ///Provide a codon usage lookup table for the given ref genome.
    abstract member GetCodonLookupTable : GenomeDef -> CodonLookup


/// Helpful wrapper type for handing around GSLC's static assets and caches.
type GlobalAssets =
    {seqLibrary: SequenceLibrary;
     codonProvider: ICodonProvider;
     rgs: Map<string, GenomeDef>;}
// =========================
// plugin behavior defintion for allele swaps
// =========================

type EndPref = NTERM | CTERM | NONETERM

/// Amount of extra dna adjacent to the ORF to include
let orfPlusMargin = 100

type AlleleSwapJobAccept = Capabilities->float<PluginScore> option
type AlleleSwapDesignParams = {
    verbose:bool
    longStyle:bool
    endPref:EndPref
    codonLookup:CodonLookup
    gene:string
    name:string
    rg:GenomeDef
    f:sgd.Feature
    m:Mutation
    len:int<ZeroOffset>
    mutOff:int<ZeroOffset>
    orf: Dna
    orfPlus: Dna
    pragmas: PragmaCollection
}

type AlleleSwapProvider = { jobScorer:AlleleSwapJobAccept ; provider:AlleleSwapDesignParams -> GslSourceCode }

// =======================
// plugin behavior definition for l2 expansion
// =======================

type L2JobAccept = Capabilities->float<PluginScore> option

type L2DesignParams = {
        rgs:GenomeDefs
        megastitch : bool
        refGenome: string
        line : BuiltL2Expression
        pragmas: PragmaCollection
}
type L2Provider = {
        jobScorer:L2JobAccept
        explicitLocusProvider:L2Id->L2DesignParams-> GslSourceCode
        implicitLocusProvider:L2DesignParams-> GslSourceCode
}

// ======================
// plugin behavior definition for output assembly transformations
// ======================
   
type ATContext = {ga: GlobalAssets; opts: ParsedOptions}

type AssemblyTransformationMessageKind = | ATError | ATWarning
    with
    override x.ToString() = match x with | ATError -> "Error" | ATWarning -> "Warning"

/// Domain type for errors encountered during transformation.
/// The type of assembly is left generic to permit re-use of this type during both
/// DNA materialization and transformation of DnaAssemblies.
type AssemblyTransformationMessage<'A when 'A :> ISourcePosition> =
    {msg: string;
     kind: AssemblyTransformationMessageKind;
     assembly: 'A;
     stackTrace: System.Diagnostics.StackTrace option;
     fromException: System.Exception option}
    with
    member x.Format(phase, ?sourceCode, ?verbose) =
        let verbose = defaultArg verbose false
        seq {
            match (x.assembly :> ISourcePosition).OptionalSourcePosition with
            | Some(p) ->
                yield sprintf "%O during %s %s: %s" x.kind phase (p.Format()) x.msg
                match sourceCode with
                | Some(source) -> yield! p.SourceContext(source)
                | None -> ()
            | None ->
                yield sprintf "%O during %s: %s" x.kind phase x.msg

        
            if verbose then
                yield sprintf "\n%+A" x.assembly
                match x.stackTrace with
                | Some(s) -> yield s.ToString()
                | None -> ()
        } |> String.concat "\n"

/// Convert an exception during assembly transformation into a message.
let exceptionToAssemblyMessage assembly (exc: System.Exception) =
    {msg = exc.Message;
     kind = ATError;
     assembly = assembly;
     stackTrace = Some(System.Diagnostics.StackTrace(exc));
     fromException = Some exc}

/// Interface specification for output assembly transformations.
type IAssemblyTransform =
    inherit IConfigurable<IAssemblyTransform>
    /// Perform a transformation of an assembly.
    abstract member TransformAssembly :
        ATContext -> DnaAssembly -> Result<DnaAssembly, AssemblyTransformationMessage<DnaAssembly>>

// =======================
// plugin behavior defintion for output file generation
// =======================

type OutputGenerationData =
    {ga: GlobalAssets;<commit_msg>ENH: improve formatting of error positions<commit_after>﻿/// Definitions of plug-in types and interfaces.
module PluginTypes
open Amyris.ErrorHandling
open commonTypes
open commandConfig
open Amyris.Bio
open constants
open LegacyParseTypes
open pragmaTypes
open AstTypes
open RefGenome
open Amyris.Bio.IO.CodonUsage
open utils
open Amyris.Dna

/// Interface specification for plugins that want to inject command line arguments and
/// be configured from the command line.
type IConfigurable<'T> =
    /// Return the list of the names of command line arguments this behavior accepts.
    abstract member ProvidedArgs : unit -> CmdLineArgSpec list
    /// Configure this behavior and return a configured version, allowing for immutable behaviors.
    abstract member Configure : ParsedCmdLineArg -> 'T
    /// Configure this behavior using the built-in compiler options.
    /// This enables sharing of items like the lib directory, verbose flag, etc.
    abstract member ConfigureFromOptions : ParsedOptions -> 'T

// =======================
// plugin behavior defintion for codon cache and optimization
// =======================

type CodonOptTask =
   {verbose:bool;
    seedOverride:int option;
    refGenome:GenomeDef;
    aminoAcidSequence:string}

type ICodonProvider =
    /// Allow codon opt providers to add command line args and be configurable.
    inherit IConfigurable<ICodonProvider>

    /// Codon optimizers use the pragma environment to configure themselves locally.
    abstract member Setup : PragmaCollection -> ICodonProvider

    ///<summary>Perform codon optimization using a particular reference genome on a string
    /// representing a protein sequence, returning a
    /// codon-optimized version.  Optionally override the RNG seed for this particular run, as well
    /// as set verbosity.
    ///</summary>
    // FIXME: this should both accept and return a domain type from Amyris.Bio.  May need to
    // define a domain type for AA sequences to match Amyris.Dna
    abstract member DoCodonOpt : CodonOptTask -> Dna

    ///Provide a codon usage lookup table for the given ref genome.
    abstract member GetCodonLookupTable : GenomeDef -> CodonLookup


/// Helpful wrapper type for handing around GSLC's static assets and caches.
type GlobalAssets =
    {seqLibrary: SequenceLibrary;
     codonProvider: ICodonProvider;
     rgs: Map<string, GenomeDef>;}
// =========================
// plugin behavior defintion for allele swaps
// =========================

type EndPref = NTERM | CTERM | NONETERM

/// Amount of extra dna adjacent to the ORF to include
let orfPlusMargin = 100

type AlleleSwapJobAccept = Capabilities->float<PluginScore> option
type AlleleSwapDesignParams = {
    verbose:bool
    longStyle:bool
    endPref:EndPref
    codonLookup:CodonLookup
    gene:string
    name:string
    rg:GenomeDef
    f:sgd.Feature
    m:Mutation
    len:int<ZeroOffset>
    mutOff:int<ZeroOffset>
    orf: Dna
    orfPlus: Dna
    pragmas: PragmaCollection
}

type AlleleSwapProvider = { jobScorer:AlleleSwapJobAccept ; provider:AlleleSwapDesignParams -> GslSourceCode }

// =======================
// plugin behavior definition for l2 expansion
// =======================

type L2JobAccept = Capabilities->float<PluginScore> option

type L2DesignParams = {
        rgs:GenomeDefs
        megastitch : bool
        refGenome: string
        line : BuiltL2Expression
        pragmas: PragmaCollection
}
type L2Provider = {
        jobScorer:L2JobAccept
        explicitLocusProvider:L2Id->L2DesignParams-> GslSourceCode
        implicitLocusProvider:L2DesignParams-> GslSourceCode
}

// ======================
// plugin behavior definition for output assembly transformations
// ======================
   
type ATContext = {ga: GlobalAssets; opts: ParsedOptions}

type AssemblyTransformationMessageKind = | ATError | ATWarning
    with
    override x.ToString() = match x with | ATError -> "Error" | ATWarning -> "Warning"

/// Domain type for errors encountered during transformation.
/// The type of assembly is left generic to permit re-use of this type during both
/// DNA materialization and transformation of DnaAssemblies.
type AssemblyTransformationMessage<'A when 'A :> ISourcePosition> =
    {msg: string;
     kind: AssemblyTransformationMessageKind;
     assembly: 'A;
     stackTrace: System.Diagnostics.StackTrace option;
     fromException: System.Exception option}
    with
    member x.Format(phase, ?sourceCode, ?verbose) =
        let verbose = defaultArg verbose false
        seq {
            match (x.assembly :> ISourcePosition).OptionalSourcePosition with
            | Some(p) ->
                yield sprintf "%O during %s %s:" x.kind phase (p.Format())
                yield x.msg
                yield "================================================================="
                match sourceCode with
                | Some(source) -> yield! p.SourceContext(source)
                | None -> ()
            | None ->
                yield sprintf "%O during %s:" x.kind phase
                yield x.msg

            if verbose then
                yield sprintf "\n%+A" x.assembly
                match x.stackTrace with
                | Some(s) -> yield s.ToString()
                | None -> ()
        } |> String.concat "\n"

/// Convert an exception during assembly transformation into a message.
let exceptionToAssemblyMessage assembly (exc: System.Exception) =
    {msg = exc.Message;
     kind = ATError;
     assembly = assembly;
     stackTrace = Some(System.Diagnostics.StackTrace(exc));
     fromException = Some exc}

/// Interface specification for output assembly transformations.
type IAssemblyTransform =
    inherit IConfigurable<IAssemblyTransform>
    /// Perform a transformation of an assembly.
    abstract member TransformAssembly :
        ATContext -> DnaAssembly -> Result<DnaAssembly, AssemblyTransformationMessage<DnaAssembly>>

// =======================
// plugin behavior defintion for output file generation
// =======================

type OutputGenerationData =
    {ga: GlobalAssets;
{'fraction_non_alphanumeric': 0.11622879946790822, 'fraction_numerical': 0.0019953441968739607, 'mean_word_length': 3.1898293277603624, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4120932', 'n_tokens_mistral': 3217, 'n_tokens_neox': 3062, 'n_words': 1067}