{ core, document, ... } @ libs: let inherit(core) debug indentation lambda list number path set string type; inherit(document) ClearPage Heading' LaTeX PhantomHeading; getDetails = minimum: peak: string.concatWith ", " ( list.filter (x: x != null) [ ( let strength = ( 100.0 - peak.y ) / ( 100.0 - minimum ) * 1.2; in if strength >= 0.7 then "s" else if strength <= 0.3 then "w" else "m" ) ( let assignment = "\\ch{${peak.assignment}}"; type = { stretching = "\\nu"; bending = "\\delta"; scissoring = "\\delta"; rocking = "\\gamma"; twisting = "\\tau"; wagging = "\\kappa"; }.${peak.type} or "???"; symmetric = if peak.sym == null then "" else if peak.sym then "\\textsubscript{s}" else "\\textsubscript{as}"; in if peak.assignment == null then null else if peak.type == null then "${assignment}" else "${symmetric}${type}(${assignment})" ) ] ); getXpos = peak: if set.isInstanceOf peak.x then "${string (number.round peak.x.from)}–${string (number.round peak.x.till)}" else (string (number.round peak.x)); reportSpectrum = { acronyms, ... }: spectrum: let signals = list.filter ( { y, ... }: let strength = ( 100.0 - y ) / ( 100.0 - spectrum.min ) * 1.2; in strength >= 0.3 ) spectrum.signals; signals' = list.sort ( first: second: let first' = if list.isInstanceOf first.x then list.head first.x else if set.isInstanceOf first.x then first.x.from else first.x; second' = if list.isInstanceOf second.x then list.head second.x else if set.isInstanceOf second.x then second.x.from else second.x; in debug.info "compare ir-signals" { data = { first = first.x; second = second.x; }; } first' > second' ) signals; spectrum' = list.map ( peak: "${getXpos peak} (${getDetails spectrum.min peak})" ) signals'; note = if spectrum.note or null != null then "${spectrum.note}, " else ""; in if spectrum' != [ ] then LaTeX ( [ "\\mbox{}\\textbf{${acronyms.infrared.short}} (${note}${acronyms.waveNumber.short}/${acronyms.cm-1.short}):" indentation.more ] ++ ( list.generate (x: "${list.get spectrum' x},") (( list.length spectrum' ) - 1) ) ++ [ "${list.foot spectrum'}." indentation.less ] ) else null; genPeaks = list.map ( peak: let x' = if set.isInstanceOf peak.x then ( peak.x.from + peak.x.till ) / 2 else peak.x; x = string (number.round x'); y = string peak.y; z = string (number.round ( x' + peak.z or 0 )); colour = "0x00aaaaaa"; in '' set arrow from first ${x}, graph 0.2 to first ${x}, first ${y} nohead lc rgb "${colour}" set arrow from first ${x}, graph 0.2 to first ${z}, graph 0.13 nohead lc rgb "${colour}" set label "\\tiny ${x}" right rotate by 90 at first ${z}, graph 0.12 '' ); genAppendix = { acronyms, ... }: { journal ? "", substance, ... } @ product: { label ? null, plot, min, max, note ? null, range, signals ? [], ... } @ spectrum: if plot != null then let fileName = let plot' = path.getBaseName plot; matching = string.match "(.+)[.]plot$" plot'; in if matching != null then list.head matching else plot'; body = '' ${string.concat ( genPeaks signals )} set xlabel "{\\small ''${\${acronyms.waveNumber.short} / \${acronyms.cm-1.short}}$}" set ylabel "{\\small ''${\\text{Transmission} / \${acronyms.percent.short}}$}" set xrange [${string range.max}:${string range.min}] set yrange [${string min}:${string max}] plot "${plot}" notitle with lines lt rgb "0x00777777" set output ''; hash = string.hash "sha1" body; dst = "generated/appendix/ir/${hash}-plot"; epsFile = "${dst}.eps"; texFile = "${dst}.tex"; gnuplotSourceFile = path.toFile "${hash}.gnuplot" '' set terminal epslatex set output "${epsFile}" ${body} ''; gnuplotDestinationFile = "${dst}.gnuplot"; src = output: string.concatWith " && " [ "(mkdir -p \"generated/appendix/ir/${substance.name}/\"" "gnuplot \"${gnuplotSourceFile}\"" "mv \"${texFile}\" \"${output}.tex\"" "epstopdf \"${epsFile}\" \"${output}.pdf\")" ]; note' = if note != null then " (${note})" else ""; in Heading' "${acronyms.infrared.short}-Spektrum~${substance.NameID}${note'}" [ ( LaTeX ( ( if label != null then [ "\\labelAppendix{ir:${label}}%" ] else [ ] ) ++ ( if true then [ "\\vspace{-1\\normalbaselineskip}" "\\begin{figure}[H]%" indentation.more "\\centering%" "\\begin{adjustbox}%" indentation.more "{max width=\\textwidth,max height=.4\\textheight,keepaspectratio}%" "{\\input{\\source/${texFile}}}%" indentation.less "\\end{adjustbox}%" indentation.less "\\end{figure}%" null ] else [ "\\begin{figure}[H]%" indentation.more "\\centering%" "\\begin{adjustbox}%" indentation.more "{angle=90,min width=\\textwidth,min totalheight=\\textheightleft,max width=\\textwidth,max totalheight=\\textheightleft-2em}%" "{\\input{\\source/${texFile}}}%" indentation.less "\\end{adjustbox}%" indentation.less "\\end{figure}%" null ] ) ) ) ] { clearPage = false; # rotate = false; before = "\\refstepcounter{ctrAppendix}%"; dependencies = [ { src = gnuplotSourceFile; dst = gnuplotDestinationFile; } { inherit dst src; } ]; } else [ ]; genAppendix' = resources: { failure ? false, ... } @ product: let ir = product.ir or product.substance.ir or null; genAppendix' = genAppendix resources product; in if ir != null && !failure then if list.isInstanceOf ir then list.map genAppendix' ir else [ ( genAppendix' ir ) ] else [ ]; generateAppendix = syntheses: { configuration, resources, ... } @ document: let syntheses' = if path.isInstanceOf syntheses then import syntheses (libs // { chemistry = libs.chemistry // { ir = null; }; }) document else syntheses; in LaTeX [ ( ClearPage ) ( PhantomHeading ( PhantomHeading ( list.concatMap ( synthesis: if synthesis ? product then let product = if lambda.isInstanceOf synthesis.product then synthesis.product { } else synthesis.product; in if list.isInstanceOf product then list.map (genAppendix' resources) product else [ ( genAppendix' resources product ) ] else [ ] ) ( if list.isInstanceOf syntheses' then syntheses' else syntheses'.list ) ) ) ) ]; report = { ... } @ resources: spectra: let reportSpectrum' = reportSpectrum resources; in if list.isInstanceOf spectra then list.filter (x: x != null) (list.map reportSpectrum' spectra) else [ ( reportSpectrum' spectra ) ]; Spectrum = plot: config: signals: { inherit plot signals; min = config.min or (-10); max = config.max or 101; range = { min = ( config.range or {} ).min or 500; max = ( config.range or {} ).max or 4000; }; note = config.note or null; }; Signal = x: y: z: type: sym: assignment: { x = type.matchPrimitiveOrDefault x { set = { from = x.from; till = x.till; }; list = { from = list.get x 0; till = list.get x 1; }; } x; inherit y z type sym assignment; }; in { inherit generateAppendix report; inherit Spectrum Signal; Signal' = x: y: z: Signal x y z null null null; }