#
# This package of procedures implements the product operator
# formalism approach for calculation and vizualization of the
# effect of an NMR pulse sequence. The implementation is written
# for weakly-coupled systems with nuclear spin of 1/2.
# Copyright (1994) Rene P.F. Kanters, KANTERS@urvax.urich.edu
#

macro(monopoly=`pof/monopoly`):
macro(t_evo=`pof/t_evo`):
macro(pof_norm=`pof/pof_norm`):
macro(SQjump=`pof/SQjump`):
macro(preQF=`pof/preQF`):
macro(doQF=`pof/doQF`):
macro(CFT=`pof/CFT`):
macro(MonCFT=`pof/MonCFT`):
macro(Cos_FT=`pof/Cos_FT`):
macro(MonCosFT=`pof/MonCosFT`):
macro(combi=`pof/combi`):
macro(MonoPreFT=`pof/MonoPreFT`):
macro(do_ph_cor=`pof/do_ph_cor`):
macro(getW=`pof/getW`):
macro(plotsub=`pof/plotsub`):
macro(monosuper=`pof/monosuper`):

monopoly:=proc() local i; 
if type(args[2],`+`) then map(args[1],seq(args[i],i=2..nargs));
else args[1](seq(args[i],i=2..nargs)); fi;
end:

nmrsubs:=proc() local i; cleanup(subs(seq(args[i],i=1..nargs))) end:

spinsystem:=proc(s) local i,j,k,l,m,n;
global J,T,W;
if not type(s,list) then ERROR(`argument should be a list`); fi;
J:=table(symmetric); W:='W';
T:=map(proc(s) if type(s,list) then op(s);else s;fi;end,s);
for i in s do
  if type(i,list) then
    for j to nops(i) do for k to j-1 do J[i[k],i[j]]:=0; od; od;
    m:=i[1]; l:=subsop(1=NULL,i); member(m,T,'n');
    for j in l do W[j]:=W[m]; od;
    for j in l do
      for k to n-1 do J[T[k],j]:=J[T[k],m]; od;
      for k from n+nops(l)+1 to nops(T) do J[j,T[k]]:=J[m,T[k]]; od;
    od;
  fi;
od;
convert(map(proc(s) Iz[s];end,T),`+`);
end:
 
xpulse:=proc(s,k,b) local i;
seq(Iy[k[i]]=Iy[k[i]]*cos(b)+Iz[k[i]]*sin(b),i=1..nops(k));
seq(Iz[k[i]]=Iz[k[i]]*cos(b)-Iy[k[i]]*sin(b),i=1..nops(k));
subs({",""},s);
end:
 
ypulse:=proc(s,k,b) local i;
seq(Ix[k[i]]=Ix[k[i]]*cos(b)-Iz[k[i]]*sin(b),i=1..nops(k));
seq(Iz[k[i]]=Iz[k[i]]*cos(b)+Ix[k[i]]*sin(b),i=1..nops(k));
subs({",""},s);
end:
 
zpulse:=proc(s,k,b) local i;
seq(Ix[k[i]]=Ix[k[i]]*cos(b)+Iy[k[i]]*sin(b),i=1..nops(k));
seq(Iy[k[i]]=Iy[k[i]]*cos(b)-Ix[k[i]]*sin(b),i=1..nops(k));
subs({",""},s);
end:
 
pulse:=proc(s,p,a,b) local k;
if nops(p)=0 then k:=T; else k:=p; fi;
if type(a,list) then
  if nops(a)<>2 then ERROR(`tilted rf pulse needs [theta,phi]`); fi;
  zpulse(s,k,-a[2]);
  ypulse(",k,Pi/2-a[1]);
  xpulse(",k,b);
  ypulse(",k,a[1]-Pi/2);
  zpulse(",k,a[2]);
else
  zpulse(s,k,-a);
  xpulse(",k,b);
  zpulse(",k,a);
fi;
cleanup(");
end:
  
shift:=proc(s,p,t) local i,n,C,S,a;
if nops(p)=0 then n:=s;
  for i in T do a:=2*Pi*W[i]*t; S:=Sin(a); C:=Cos(a);
    n:=subs({Ix[i]=Ix[i]*C+Iy[i]*S,Iy[i]=Iy[i]*C-Ix[i]*S},n);
  od;
else n:=0;
  for i in p do a:=2*Pi*W[i]*t; S:=Sin(a); C:=Cos(a);
    n:=n+coeff(s,Ix[i])*(Ix[i]*C+Iy[i]*S)+coeff(s,Iy[i])*(Iy[i]*C-Ix[i]*S);
  od;
fi;
cleanup(n);
end:
 
couple:=proc(s,t) local i,j,n,a,C,S,k,l;
n:=s;
for i to nops(T) do l:=T[i];
  for j to i-1 do k:=T[j];
    if J[k,l]<>0 then a:=Pi*J[k,l]*t; S:=Sin(a); C:=Cos(a);
      Ix[k]=Ix[k]*C+2*Iy[k]*Iz[l]*S, Iy[k]=Iy[k]*C-2*Ix[k]*Iz[l]*S;
      Ix[l]=Ix[l]*C+2*Iy[l]*Iz[k]*S, Iy[l]=Iy[l]*C-2*Ix[l]*Iz[k]*S;
      n:=subs({",""},n);
    fi;
  od;
od;
cleanup(n);
end:
 
evolve:=proc(s,p,t) couple(shift(s,p,t),t); end:
 
t_evo:=proc(s) local i,t;
t:=false;
if not type(s,`*`) then RETURN(t_evo(2*s)/2); fi;
for i in s do
  if type(i,`^`) then i:=op(1,i);
    if type(i,indexed) and (op(0,i)=`Ix` or op(0,i)=`Iy`) then RETURN(0); fi; 
  elif type(i,indexed) then
    if op(0,i)<>`Iz` then
      if t and (op(0,i)=`Ix` or op(0,i)=`Iy`) then RETURN(0); else t:=true; fi;
    fi;
  fi;
od;
if t then s; else 0; fi;
end:

#observe by quadrature detection
observe:=proc(s,k,t,p) local i,s1,s2,s3;
s1:=seq(Ix[T[i]]=cos(p)-I*sin(p),i=1..nops(T));
s2:=seq(Iy[T[i]]=sin(p)+I*cos(p),i=1..nops(T));
s3:=seq(Iz[T[i]]=0,i=1..nops(T));
subs(s1,s2,s3,evolve(monopoly(t_evo,s),k,t))/2;
end:

cleanup:=proc(s) monopoly(pof_norm,expand(s)); end:

pof_norm:=proc(s) local n,i,j,r,c,p,f,a,b;
  c:=false; r:=1;
  if type(s,`*`) then n:=convert(s,list); else n:=[s]; fi;
  for i to nops(n) do
    if type(n[i],function) then
      a:=op(n[i]);
      if op(0,n[i])=`Sin` then
        if type(a,constant) then r:=r*sin(a);
        else f:=false; j:=i+1;
          while not f and j<=nops(n) do
            if type(n[j],function) and indets(a)=indets(op(n[j])) then
	      b:=op(n[j]);
              if op(0,n[j])=`Sin` then f:=true; n:=subsop(j=1,n);
                if sign(evalf(a-b))=1 then r:=r*(Cos(a-b)-Cos(a+b))/2;
                else r:=r*(Cos(b-a)-Cos(a+b))/2; fi;
              elif op(0,n[j])=`Cos` then f:=true; n:=subsop(j=1,n);
                if sign(evalf(a-b))=1 then r:=r*(Sin(a+b)+Sin(a-b))/2;
                else r:=r*(Sin(a+b)-Sin(b-a))/2; fi;
              fi;
            fi; j:=j+1;
          od;
          if f then c:=true; else r:=r*n[i]; fi;
        fi;
      elif op(0,n[i])=`Cos` then
        if type(a,constant) then r:=r*cos(a);
        else f:=false; j:=i+1;
          while not f and j<=nops(n) do
            if type(n[j],function) and indets(a)=indets(op(n[j])) then
	      b:=op(n[j]);
              if op(0,n[j])=`Cos` then f:=true; n:=subsop(j=1,n);
                if sign(evalf(a-b))=1 then r:=r*(Cos(a+b)+Cos(a-b))/2;
                else r:=r*(Cos(a+b)+Cos(b-a))/2; fi;
              elif op(0,n[j])=`Sin` then f:=true; n:=subsop(j=1,n);
                if sign(evalf(a-b))=1 then r:=r*(Sin(a+b)-Sin(a-b))/2;
                else r:=r*(Sin(b+a)+Sin(b-a))/2; fi;
              fi;
            fi; j:=j+1;
          od;
          if f then c:=true; else r:=r*n[i]; fi;
        fi;
      else r:=r*n[i]; fi;	# added else because of exp(...)  
    elif type(n[i],`^`) then
      a:=op(1,n[i]); p:=op(2,n[i]);
      if type(a,function) then
        if op(0,a)=`Sin` then
          r:=r*((1-Cos(2*op(a)))/2)^iquo(p,2)*a^irem(p,2); c:=true;
        elif op(0,a)=`Cos` then
          r:=r*((1+Cos(2*op(a)))/2)^iquo(p,2)*a^irem(p,2); c:=true;
        else r:=r*n[i]; fi;
      elif type(a,indexed) and op(0,a)=`Iz` then
	r:=r*(1/4)^iquo(p,2)*a^irem(p,2);
      else r:=r*n[i]; fi;
    else r:=r*n[i]; fi;
  od;
  if c then RETURN(monopoly(pof_norm,expand(r))); else RETURN(r); fi;
end:

pm_xy:=proc(s) local i;
seq(Ip[T[i]]=Ix[T[i]]+I*Iy[T[i]],i=1..nops(T));
seq(Im[T[i]]=Ix[T[i]]-I*Iy[T[i]],i=1..nops(T));
expand(subs(","",s));
end:
 
xy_pm:=proc(s) local i;
seq(Ix[T[i]]=(Ip[T[i]]+Im[T[i]])/2,i=1..nops(T));
seq(Iy[T[i]]=I*(Im[T[i]]-Ip[T[i]])/2,i=1..nops(T));
expand(subs(","",s));
end:
 
QC:=proc(s) local qc,i,p;
if(s=0) then RETURN(0); fi;qc:=0;
if not type(s,`*`) then RETURN(QC(2*s)); fi;
for i in s do
  if type(i,`^`) then p:=op(2,i); i:=op(1,i); else p:=1; fi;
  if type(i,indexed) then
    if op(0,i)=`Ip` then qc:=qc+p;
    elif op(0,i)=`Im` then qc:=qc-p;
    fi;
  fi;
od;
RETURN(qc);
end:
 
QCset:=proc(s) map(QC,convert(xy_pm(s),set)); end:
 
SQjump:=proc(s,k,a,b,p,n) local new,i,qc,ns;
qc:=QC(s); new:=0;
ns:=xy_pm(pulse(pm_xy(s),k,a,b));
for i in ns do if modp(QC(i)-qc,n)=p then new:=new+i; fi; od;
expand(evalc(pm_xy(new)));
end:
 
QFpulse:=proc(s,k,a,b,p,n) monopoly(SQjump,xy_pm(s),k,a,b,p,n); end:
 
preQF:=proc(s,q) local i,t,p;
t:=0;
if not type(s,`*`) then RETURN(preQF(2*s,q)/2); fi;
for i in s do
  if type(i,`^`) then p:=op(2,i); i:=op(1,i); else p:=1; fi;
  if type(i,indexed) and (op(0,i)=`Ix` or op(0,i)=`Iy`) then t:=t+p; fi;
od;
p:=abs(q);
if t>=p and irem(p,2)=irem(t,2) then s; else 0; fi;
end:

doQF:=proc(s,q) local r;
if iquo(QC(s),q,`r`)<>0 and r=0 then s; else 0; fi;
end:
 
QF:=proc(s,q)
xy_pm(monopoly(preQF,s,q));
monopoly(doQF,",q);
expand(evalc(pm_xy(")));
end:

CFT:=proc(s,t) local c;
if type(s,function) and has(op(1,s),t) then c:=expand(coeff(op(s),t)/(2*Pi));
  if op(0,s)=`Cos` then 
    if has(c,`W`) then (Ab(c,t)+I*Di(c,t))/2; 
    else (Ab(c,t)+Ab(-c,t)+I*Di(c,t)+I*Di(-c,t))/2; fi;
  elif op(0,s)=`Sin` then
    if has(c,`W`) then (Di(c,t)-I*Ab(c,t))/2;
    else (Di(c,t)-Di(-c,t)-I*Ab(c,t)+I*Ab(-c,t))/2; fi;
  fi;
else s; fi;
end:
 
MonCFT:=proc(s,t) local i,n;
if not has(s,t) then RETURN(s*Ab(0,t)); fi;
if type(s,`*`) then map(CFT,s,t); else CFT(s,t); fi;
end:

# real or cosine transform, only positive chemical shifts, for TPPI
Cos_FT:=proc(s,t) local c;
if type(s,function) and has(op(1,s),t) then c:=expand(coeff(op(s),t)/(2*Pi));
  if op(0,s)=`Cos` then 
    if has(c,`W`) then Ab(c,t)/2; 
    else (Ab(c,t)+Ab(-c,t))/2; fi;
  elif op(0,s)=`Sin` then
    if has(c,`W`) then Di(c,t)/2;
    else (Di(c,t)-Di(-c,t))/2; fi;
  fi;
else s; fi;
end:
 
MonCosFT:=proc(s,t) local i,n;
if not has(s,t) then RETURN(s*Ab(0,t)); fi;
if type(s,`*`) then map(Cos_FT,s,t); else Cos_FT(s,t); fi;
end:

combi:=proc(a,b,t) local c,v,i,s,d;
if type(a,`*`) then c:=1; v:=1;
  for i in a do if not has(i,t) then c:=c*i; else v:=v*i; fi; od;
  RETURN(c*combi(v,b,t));
fi;
if has(b,`W`) then RETURN(combi(b,a,t)); fi;
if not type(a,function) or not type(b,function) then RETURN(a*b); fi;
s:=op(a)+op(b); d:=op(a)-op(b);
if op(0,a)=`Sin` then
  if op(0,b)=`Sin` then Cos(d)/2-Cos(s)/2;
  elif op(0,b)=`Cos` then Sin(s)/2+Sin(d)/2; fi;
elif op(0,a)=`Cos` then
  if op(0,b)=`Sin` then Sin(s)/2-Sin(d)/2;
  elif op(0,b)=`Cos` then Cos(s)/2+Cos(d)/2; fi;
else a*b; fi;
end:
 
MonoPreFT:=proc(s,t) local i,combining,c,k;
if not type(s,`*`) then RETURN(s); fi;
k:=1;c:=1; combining:=false;
for i in s do
  if has(i,t) then
    if combining then c:=monopoly(combi,c,i,t);
    else c:=i; combining:=true; fi;
  else k:=k*i; fi;
od; expand(k*c);
end:
 
do_ph_cor:=proc(s,p,t) local n,i,k;
if type(s,`*`) then n:=convert(s,list); else n:=[s]; fi;
for i to nops(n) do k:=n[i];
  if type(k,function) and has(op(1,k),t) then
    if op(0,k)=`Sin` then n:=subsop(i=cos(p)*k+sin(p)*Cos(op(k)),n);
    elif op(0,k)=`Cos` then n:=subsop(i=cos(p)*k-sin(p)*Sin(op(k)),n); fi;
  fi;
od; convert(n,`*`);
end:
 
FT:=proc(s,p,t,v) 
monopoly(MonoPreFT,s,t);
expand(monopoly(do_ph_cor,",p,t));
expand(monopoly(MonCFT,",t));
subs(t=v,");
end:

CosFT:=proc(s,p,t,v) 
monopoly(MonoPreFT,s,t);
expand(monopoly(do_ph_cor,",p,t));
expand(monopoly(MonCosFT,",t));
subs(t=v,");
end:

getW:=proc(s) local i;
if type(s,indexed) and op(0,s)=`W` then RETURN(op(s)); fi;
for i in op(s) do if type(i,indexed) and op(0,i)=`W` then RETURN(op(i)); fi;
od;
RETURN(0);
end:
 
pA:=proc(v0,v,T2) 2*T2/(1+(2*Pi*T2*(v0-v))^2); end:
 
pD:=proc(v0,v,T2) 4*Pi*T2^2*(v0-v)/(1+(2*Pi*T2*(v0-v))^2); end:
 
plotsub:=proc(s) local n,i;
n:=evalc(Re(s));
if type(s,`*`) then n:=convert(n,list); else n:=[n]; fi;
for i in n do
  if type(i,function) and (op(0,i)=`Ab` or op(0,i)=`Di`) then
    n:=subs(i=op(0,i)(op(1,i),op(2,i),T2[getW(op(1,i))]),n);
  fi;
od;
convert(subs(Ab=pA,Di=pD,W=Wv,J=Jv,Cos=cos,Sin=sin,n),`*`);
end:
 
nmrplot:=proc() local n,i;
n:=args[1];
if type(n,`set`) then n:={seq(monopoly(plotsub,op(i,n)),i=1..nops(n))};
else n:=monopoly(plotsub,n); fi; 
plot(eval(n),seq(args[i],i=2..nargs));
end:
 
nmrplot2d:=proc() local n,i;
n:=args[1];
if type(n,`set`) then n:={seq(monopoly(plotsub,op(i,n)),i=1..nops(n))};
else n:=monopoly(plotsub,n); fi; 
# Must eval n here
plot3d(eval(n),args[2..nargs]);
end:

with(plots,display3d):
crit_A:=1:
crit_D:=10:

super2d:=proc() local i;
if type(args[1],`+`) then convert(args[1],set); else {args[1]}; fi;
display3d(map(monosuper,",seq(args[i],i=2..nargs)));
end:

monosuper:=proc() local i,s,r1,r2,w,t,v,d;
if type(args[1],`*`) then s:=convert(args[1],list); else s:=[args[1]]; fi;
for i in s do
  if type(i,function) and (op(0,i)=`Ab` or op(0,i)=`Di`) then
    w:=T2[getW(op(1,i))]; v:=op(1,i): t:=op(2,i);
	if op(0,i)=`Ab` then d:=crit_A/w; else d:=crit_D/w; fi;
    if t=args[2] then r1:=t=v-d..v+d;
    elif t=args[3] then r2:=t=v-d..v+d; fi;
    s:=subs(i=op(0,i)(v,t,w),s);
  fi;
od;
r1:=eval(subs(W=Wv,J=Jv,r1)); r2:=eval(subs(W=Wv,J=Jv,r2));
convert(subs(Ab=pA,Di=pD,W=Wv,J=Jv,Cos=cos,Sin=sin,s),`*`);
plot3d(",r1,r2,seq(args[i],i=4..nargs));
end:

# pofhelp.map to be included here:
`help/text/pof`:=TEXT(` `,
`PROCEDURES: Product-Operator Formalism`,
` `,
`The Product Operator Formalism procedures as reported in`,
` `,
`Rene' P. F. Kanters, Bruce W. Char, and Anthony W. Addison, "A Computer-`,
`Algebra Application for the Description of NMR Experiments Using the`,
`Product-Operator Formalism," Journal of Magnetic Resonance, Series A,`,
`Vol. 101, 1993, 23-29.`,
` `,
`To work with this set of procedures, you should be familiar with the`,
`following expression, globals, and functions.`,
` `,
`       FOR                     SEE ALSO`,
` `,
` expression types      : spinstate, FID, spectrum`,
` terms in expression   : spinoperator, modulation, peak`,
` spinoperator globals  : Ix, Iy, Iz, Im, Ip`,
` modulation            : Cos, Sin`,
` peak                  : Ab, Di`,
` `,
` spinsystem globals    : J, W, T`,
` visualization globals : Jv, Wv, T2, crit_A, crit_D`,
` `,
` initialization        : spinsystem`,
` pulses                : xpulse, ypulse, zpulse, pulse `,
` evolution             : shift, couple, evolve, observe`,
` manipulation          : nmrsubs, cleanup`,
` Fourier transform     : FT, CosFT`,
` visualization         : pA, pD, nmrplot, nmrplot2d, super2d`,
` quantum coherence     : QFpulse, QF, xy_pm, pm_xy, QC, QCset`):


`help/text/spinstate`:=TEXT(` `,
`EXPRESSION: spinstate`,
` `,
`SYNOPSIS:`,
`The spinstate is an algebraic polynomial, describing the state of all`,
`spins as a product-operator expression. In general the terms in this`,
`polynomial consist of an amplitude, one or more cartesian (Ix, Iy, and`,
`Iz), or step (Ip, Im) spin operators and time modulations (Sin or Cos).`,
` `,
`Spinstate expressions are returned from the procedures spinsystem,`,
`xpulse, ypulse, zpulse, pulse, QFpulse, shift, couple, evolve, QF,`,
`xy_pm, pm_xy, nmrsubs, and cleanup.`,
` `,
`In order to normalize spinstate expressions use the procedure cleanup.`,
`Note: all POF procedures return normalized spinstate expressions.`,
` `,
`EXAMPLES:`,
`> Iz[A] + Iz[B]:`,
`> Ix[A]*Cos(Pi*J[A,B]*t1)*Cos(2*Pi*W[A]*t1)`,
`    +Iy[A]*Cos(Pi*J[A,B]*t1)*Sin(2*Pi*W[A]*t1):`,
`> 1/2*I*Sin(Pi*J[A,B]t1)*Sin(2*Pi*W[A]*t1)*Im[A]`,
`    -1/2*I*Sin(Pi*J[A,B]*t1)*Sin(2*Pi*W[A]*t1)*Ip[A]:`,
` `,
`SEE ALSO: spinoperator, modulation, cleanup`):


`help/text/FID`:=TEXT(` `,
`EXPRESSION: FID`,
` `,
`SYNOPSIS:`,
`The observed Free Induction Decay, FID, is an algabraic polynomial of`,
`terms consisting of an amplitude and time modulations Sin or Cos.`,
` `,
`FID expressions are returned from the observe procedure.`,
` `,
`Since the Product-Operator Formalism does not include relaxation`,
`processes the FID does not contain the decay in the variable time`,
`domains that real spectra will have.`,
` `,
`In order to normalize FID expressions use the procedure cleanup.`,
`Note: all POF procedures return normalized FID expressions`,
` `,
`EXAMPLE:`,
`> -1/2*Cos(2*Pi*W[A]*t)*I*Cos(Pi*J[A,X]*t)`,
`    +1/2*Sin(2*Pi*W[A]*t)*Cos(Pi*J[A,X]*t):`,
` `,
`SEE ALSO: modulation, observe`):


`help/text/spectrum`:=TEXT(` `,
`EXPRESSION: spectrum and mixed FID/spectrum`,
` `,
`SYNOPSIS:`,
`The NMR spectrum expression is a polynomial whose terms consist of an`,
`amplitude and peak functions Ab or Di.`,
` `,
`A mixed FID/spectrum expression is a polynomial consisting of terms`,
`that are products FID and spectrum terms.`,
` `,
`This kind of expressions are returned from the symbolic Fourier`,
`transform procedures FT and CosFT.`,
` `,
`EXAMPLE:`,
`> 1/64*Ab(W[A]+J[A,B]/2,v1)*Ab(W[B]+J[A,B]/2,v2):`,
`> 1/8*Ab(W[A]+J[A,B]/2,v1)*Sin(2*Pi*W[B]*t2)*Cos(Pi*J[A,B]*t2):`,
` `,
`SEE ALSO: peak, FID, FT, CosFT`):

`help/text/modulation`:=TEXT(` `,
`FUNCTIONS: Cos, Sin - cosine and sine modulation`,
` `,
`CALLING SEQUENCE: Cos(m); Sin(m);`,
` `,
`PARAMETERS : m - modulation in radian`,
` `,
`SYNOPSIS:`,
`The functions Cos and Sin are undefined and evaluate to themselves.`,
`This allows the description of cosine (Cos) and sine (Sin) modulations`,
`in spinstate and FID expressions.`,
` `,
`EXAMPLES:`,
`> s:=Ix[A]*Cos(Pi*J[A,B]*t1)*Sin(2*Pi*W[A]*t1);`,
`> Sin(0);                     # yields  Sin(0)`,
`> cleanup(Sin(0));            # yields  0`,
` `,
`SEE ALSO: FID, spinstate`):
`help/text/Sin`:=`help/text/modulation`:
`help/text/Cos`:=`help/text/modulation`:


`help/text/peak`:=TEXT(` `,
`FUNCTIONS: Ab, Di - absorption and dispersion peak`,
` `,
`CALLING SEQUENCE: Ab(p,v); Di(p,v);`,
` `,
`PARAMETERS: p - position`,
`            v - frequency domain`,
` `,
`SYNOPSIS:`,
`The peak functions, Ab and Di, are undefined and evaluate to themselves.`,
`This allows the description of absorption (Ab) peaks and dispersion (Di)`,
`peaks in mixed FID/spectrum and spectrum expressions.`,
` `,
`The peak functions are introduced in expressions by Fourier transforming`,
`the observed spectrum using the FT or CosFT procedures.`,
` `,
`EXAMPLES:`,
`> spec:=Di(W[A]+1/2*J[A,B],v1)*Di(W[B]+1/2*J[A,B],v2):`,
`> spec:=Ab(W[A]+1/2*J[A,B],v1)*Ab(W[B]+1/2*J[A,B],v2):`,
`> Di:=proc() 0 end:;   # to suppress dispersion peaks`,
`> Di:='Di':            # to enable getting dispersion peaks`,
` `,
`SEE ALSO: spectrum, FT, CosFT`):
`help/text/Di`:=`help/text/peak`:
`help/text/Ab`:=`help/text/peak`:


`help/text/spinoperator`:=TEXT(` `,
`GLOBALS: Ix, Iy, Iz, Im, Ip - spinoperators`,
` `,
`ACCESSING SEQUENCE: Ix[A]; Iy[A]; Iz[A]; Im[A]; Ip[A];`,
` `,
`PARAMETER: A - spin`,
` `,
`SYNOPSIS:`,
`Cartesian spin operators Ix (Ix), Iy (Iy), and Iz (Iz) and Step`,
`operators I+ (Ip) and I- (Im).`,
` `,
`The variables are undefined tables whose index refers to the spin that`,
`the operator works on.`,
` `,
`EXAMPLES:`,
`> s:=Ix[A]+Iy[B];`,
`> QC(Ip[A]);  # yields the coherence order of I+[A], i.e. 1`,
` `,
`SEE ALSO: spinstate`):
`help/text/Ix`:=`help/text/spinoperator`:
`help/text/Iy`:=`help/text/spinoperator`:
`help/text/Iz`:=`help/text/spinoperator`:
`help/text/Ip`:=`help/text/spinoperator`:
`help/text/Im`:=`help/text/spinoperator`:

`help/text/J`:=TEXT(` `,
`GLOBAL: J - coupling table`,
` `,
`ACCESSING SEQUENCE:  J[A,B];`,
` `,
`PARAMETERS: A, B - spin`,
` `,
`SYNOPSIS:`,
`J is a symmetric table for the symbolic representation of the size of`,
`the J coupling between two spins.`,
` `,
`This global variable is set by the spinsystem procedure to represent`,
`the particular spinsystem present. Entries in the J table are only`,
`defined when the spin system gives rise to equal or absent couplings,`,
`e.g. in the case of an AnX spinsystem all JA,X couplings are the same`,
`and the couplings between the 3 A spins are absent (zero).`,
` `,
`EXAMPLES:`,
`> spinsystem([[A,A2],B]): op(J);`,
`            table(symmetric,[`,
`                (A, A2) = 0`,
`                (A2, B) = J[A, B]`,
`            ])`,
`> J[A,B]:=0;                  # clear coupling between spins A and B`,
`> J[A,B]:='J[A,B]';           # reset coupling between spins A and B`,
`> s:=Ix[A]*Sin(Pi*J[A,B]*t1);`,
` `,
`SEE ALSO: spinsystem`):

`help/text/W`:=TEXT(` `,
`GLOBAL: W - chemical shift table`,
` `,
`ACCESSING SEQUENCE: W[A];`,
` `,
`PARAMETER: A - spin`,
` `,
`SYNOPSIS:`,
`W is an implicitely defined table of symbolic chemical shifts.`,
` `,
`This global variable is set in the spinsystem procedure to represent`,
`the particular spinsystem present. The W table is only defined when`,
`certain shifts are equal to other ones, e.g. in the case of an AnX`,
`spinsystem all the shifts of the spins in A are set to be equal.`,
` `,
`EXAMPLES:`,
`> s:=Ix[A]*Sin(2*Pi*W[A]*t1);`,
`> spinsystem([[A,A2],B]): op(W);`,
`              table([`,
`                  A2 = W[A]`,
`              ])`,
` `,
`SEE ALSO: spinsystem`):

`help/text/T`:=TEXT(` `,
`GLOBAL: T - list of all spins`,
` `,
`ACCESSING SEQUENCE: T;`,
` `,
`SYNOPSIS:`,
`T is the list of all present spins.`,
` `,
`This global variable is set in the initializing procedure spinsystem.`,
` `,
`It is used in the procedure couple to generate all possible couplings`,
`present. It is also used in the procedures that have sets or lists of`,
`spins as arguments that can be empty, in which case the empty set or`,
`list is substituted with list T.`,
` `,
`EXAMPLES:`,
`> xpulse(spinsystem([[A,A2],B]),T,Pi/2);`,
`                - Iy[A] - Iy[A2] - Iy[B]`,
`> op(T);`,
`                           A, A2, B`,
` `,
`SEE ALSO:`):

`help/text/pof/crit`:=TEXT(` `,
`GLOBAL: crit_A, crit_D`,
` `,
`ACCESSING SEQUENCE: crit_A; crit_D;`,
` `,
`crit_A and crit_D are arameters to define the automatic range of the`,
`grid to be calculated around an absorption and dispersion peak,`,
`respectively, in the super2d procedure.`,
` `,
`                   Absorption peak             Dispersion peak`,
`variable name          crit_A                      crit_D`,
`freq. range        +/- crit_A/T2[i]            +/- crit_D/T2[i]`,
`cutoff         1/(1+4 Pi^2 crit_A^2)     4 Pi crit_D/(1+4 Pi^2 crit_D^2)`,
`default value             1                           10`,
` `,
`cutoff is the absolute value of the minimum intensity relative to the`,
`extreme in the lineshape that will be displayed using the super2d`,
`procedure.`,
` `,
`EXAMPLES:`,
`> crit_A:=2;`,
`> crit_D:=15;`,
` `,
`SEE ALSO: super2d, pA, pD, lineshape`):
`help/text/crit_A`:=`help/text/pof/crit`:
`help/text/crit_D`:=`help/text/pof/crit`:


`help/text/Jv`:=TEXT(` `,
`GLOBAL: Jv - table of numerical coupling values`,
` `,
`ACCESSING SEQUENCE: Jv[A,B];`,
` `,
`PARAMETERS: A, B - spin`,
` `,
`SYNOPSIS:`,
`This symmetric table contains the numeric values of the coupling`,
`constants in Hz. This is needed for the numeric evaluation of spectrum`,
`intensities, required in all nmr plot procedures.`,
` `,
`EXAMPLES:`,
`> Jv:=table(symmetric,[(A,B)=2,(A,C)=3,(B,C)=10]); # assigment of 3 J's`,
`> Jv[A,B]:=3;`,
` `,
`SEE ALSO: nmrplot, nmrplot2d, super2d`):

`help/text/Wv`:=TEXT(` `,
`GLOBAL: Wv - table of numerical chemical shift values`,
` `,
`ACCESSING SEQUENCE: Wv[A];`,
` `,
`PARAMETER: A - spin`,
` `,
`SYNOPSIS:`,
`This table contains the numeric values of the symbolic chemical shift in`,
`Hz. This needed for the numeric evaluation of spectrum intensities,`,
`required in all nmr plot procedures.`,
` `,
`EXAMPLES:`,
`> Wv:=table([A=0,B=30,C=60]): # assigment of 3 shifts`,
`> Wv[B]:=30:`,
` `,
`SEE ALSO: nmrplot, nmrplot2d, super2d`):


`help/text/T2`:=TEXT(` `,
`GLOBAL: T2 - table of relaxation times`,
` `,
`ACCESSING SEQUENCE: T2[A];`,
` `,
`PARAMETER: A - spin`,
` `,
`SYNOPSIS:`,
`This table contains the numeric values if the T2 relaxation rate, in`,
`seconds. This is needed for the numeric evaluation of the lineshapes,`,
`pA and pB, used in all nmr plot procedures.`,
` `,
`In case the peak position is not dependant on a chemical shift, as is`,
`possible in spin-echo experiments like the J-resolved pulse sequence,`,
`the spin '0' is used so that T2[0] needs to be defined.`,
` `,
`EXAMPLES:`,
`> T2:=table([A=1,B=1,C=1]); # assigment of 3 T2 relaxation times`,
`> T2[B]:=1;`):


`help/text/spinsystem`:=TEXT(` `,
`FUNCTION: spinsystem - initialization of globals and spinstate`,
` `,
`CALLING SEQUENCE: spinsystem(l);`,
` `,
`PARAMETER: l - spin system list`,
` `,
`SYNOPSIS:`,
`Returns the equilibrium spinstate (all spins Iz) and initializes the`,
`global variables J, W, and T.`,
` `,
`Equivalent spins can be defined as a lists within the spin system list`,
`l. The first spin in those sub lists will be used for indexing the`,
`global variable tables J, W, Jv, Wv,  and T2.`,
` `,
`EXAMPLES:`,
`> spinsystem([[A,A2],B]); # definition of an A2B system`,
`            Iz[A]+Iz[A2]+Iz[B]`,
`> J[A,A2];                # yields  0`,
`> J[A2,B];                # yields  J[A,B]`,
`> W[A2];                  # yields  W[A]`):

`help/text/pof/cartesianpulse`:=TEXT(` `,
`FUNCTION: xpulse, ypulse, zpulse - pulse along cartesian axis`,
` `,
`CALLING SEQUENCE: xpulse(s,l,a); ypulse(s,l,a); zpulse(s,l,a);`,
` `,
`PARAMETERS: s - spinstate with only cartesian operators`,
`            l - list or set of spins`,
`            a - angle in radian`,
` `,
`SYNOPSIS:`,
`Returns the result of a pulse of angle a directed along the x, y or z`,
`axis, respectively, on all spins in l present in spinstate expression`,
`s.`,
` `,
`Note that in order to pulse on all spins in an equivalent set, all the`,
`equivalent spins have to be present in l.`,
` `,
`In order to apply the pulse to all spins present, the global list T can`,
`be used for parameter l.`,
` `,
`EXAMPLES:`,
`> xpulse(Iz[A]+Iz[B],{A,B},Pi/2);  # yields  - Iy[A] - Iy[B]`,
`> ypulse(Ix[A]+Ix[B],[A],Pi);      # yields  - Ix[A] + Ix[B]`,
`> zpulse(Ix[A]+Iy[B],{B},Pi);      # yields    Ix[A] - Iy[B]`,
` `,
`SEE ALSO: pulse, QFpulse`):
`help/text/xpulse`:=`help/text/pof/cartesianpulse`:
`help/text/ypulse`:=`help/text/pof/cartesianpulse`:
`help/text/zpulse`:=`help/text/pof/cartesianpulse`:

`help/text/pulse`:=TEXT(` `,
`FUNCTION: pulse - tilted or arbitrary phase pulse`,
` `,
`CALLING SEQUENCE: pulse(s,l,d,a);`,
` `,
`PARAMETERS: s - spinstate with only cartesian operators`,
`            l - list or set of spins`,
`            d - direction in radian`,
`            a - angle in radian`,
` `,
`GLOBAL: T - if l is empty`,
` `,
`SYNOPSIS:`,
`Returns the result of a pulse of angle a along direction d on all spins`,
`in l, or T of l is empty, present in spinstate expression s. Note that`,
`in order to pulse on all spins in an equivalent set, all the equivalent`,
`spins have to be present in l.`,
` `,
`The directional argument, d, can be one of two forms:`,
`- a list of two angles, [theta,phi], for a tilted rf pulse.`,
`  In this case, theta is angle of the direction along which the pulse`,
`  occurs with the z-axis, and phi that of its projection on the xy-plane`,
`  with the x-axis, i.e., polar coordinates`,
`- a single angle, phi, for an arbitrary phase pulse in the xy-plane.`,
`  Here, phi is the angle of the direction along which the pulse occurs`,
`  with the x-axis. This means that it is equivalent to a titled pulse`,
`  with a theta of Pi/2.`,
` `,
`EXAMPLES:`,
`> pulse(Iz[A],{A},Pi/2,Pi/2);             # yields    Ix[A]`,
`> pulse(Iz[A],{A},-Pi/2,Pi/2);            # yields  - Ix[A]`,
`> pulse(Iz[A],{A},[Pi/2,-Pi/2],Pi/2);     # yields  - Ix[A]`,
`> pulse(spinsystem([A,B]),{},Pi/2,Pi/2);  # yields    Ix[A]+Ix[B]`,
` `,
`SEE ALSO: xpulse, ypulse, zpulse, QFpulse`):

`help/text/QFpulse`:=TEXT(` `,
`FUNCTION: QFpulse - quantum filtering pulse`,
` `,
`CALLING SEQUENCE: QFpulse(s,l,d,a,p,n);`,
` `,
`PARAMETERS: s - spinstate with only cartesian operators`,
`            l - list or set of spins`,
`            d - direction in radian`,
`            a - angle in radian`,
`            p - coherence jump order, integer`,
`            n - selectivity, integer`,
` `,
`GLOBAL: T`,
` `,
`SYNOPSIS:`,
`Returns the result of a pulse along direction d on all spins in l, or T`,
`of l is empty, present in spinstate expression s but retains only the`,
`terms that have a jump in quantum coherences order of p + i n, with i =`,
`0, 1, ... with respect to the quantum coherence order of the term before`,
`the pulse.`,
` `,
`The directional argument, d, can be one of the same two forms as for`,
`the pulse procedure:`,
`- a list of two angles, [theta,phi], for a tilted rf pulse.`,
`- a single angle, phi, for an arbitrary phase pulse in the xy-plane.`,
` `,
`Note that for straight forward quantum filtering, as used in multiple`,
`quantum filtered COSY spectra, the procedure QF can be used`,
` `,
`EXAMPLES:`,
`> T:=[A,B]: QFpulse(Iy[A],{A},0,Pi/2,0,2);         # yields    0`,
`> T:=[A,B]: QFpulse(Iy[A]*Iz[B],{A,B},0,Pi/2,0,2);`,
`   - Iz[A] Iy[B]`,
` `,
`SEE ALSO: QF, pulse`):

`help/text/shift`:=TEXT(` `,
`FUNCTION: shift - chemical shift evolution`,
` `,
`CALLING SEQUENCE: shift(s,l,t);`,
` `,
`PARAMETERS: s - spinstate with only cartesian operators`,
`            l - list or set of spins`,
`            t - time domain`,
` `,
`GLOBAL: T - if l is empty`,
` `,
`SYNOPSIS:`,
`Returns the result of the chemical shift evolution of spins in l, or T`,
`if l is empty, in spinstate s during time domain t.`,
` `,
`EXAMPLES:`,
`> shift(Ix[A]+Iy[B],[A],t1);`,
`            Ix[A] Cos(2 Pi W[A] t1) + Iy[A] Sin(2 Pi W[A] t1)`,
`> T:=[A]: shift(Ix[A],{},t1);`,
`            Ix[A] Cos(2 Pi W[A] t1) + Iy[A] Sin(2 Pi W[A] t1)`,
` `,
`SEE ALSO: spinstate, T, couple, evolve, observe`):

`help/text/couple`:=TEXT(` `,
`FUNCTION: couple - coupling evolution`,
` `,
`CALLING SEQUENCE: couple(s,t);`,
` `,
`PARAMETERS: s - spinstate with only cartesian operators`,
`            t - time domain`,
` `,
`GLOBAL: T`,
` `,
`SYNOPSIS:`,
`Returns the result of the coupling evolution of all possible couplings,`,
`not equal to zero, based on the contents of the global spin list T.`,
`Equivalent spins will not couple since their coupling is set to 0 by the`,
`spinsystem procedure.`,
` `,
`EXAMPLE:`,
`> xpulse(spinsystem([A,X]),{A},Pi/2): couple(",t1);`,
`   - Iy[A] Cos(Pi J[A, X] t1) + 2 Ix[A] Iz[X] Sin(Pi J[A, X] t1) + Iz[X]`,
` `,
`SEE ALSO: spinstate, T, shift, evolve, observe`):

`help/text/evolve`:=TEXT(` `,
`FUNCTION: evolve - coupling and shift evolution`,
` `,
`CALLING SEQUENCE: evolve(s,l,t);`,
` `,
`PARAMETERS: s - spinstate with only cartesian operators`,
`            l - list or set of spins`,
`            t - time domain`,
` `,
`GLOBAL: T`,
` `,
`SYNOPSIS:`,
`Returns the result of the chemical shift evolution of spins in l, or T`,
`if l is empty, and coupling evolution of all possible couplings, not`,
`equal to zero, based on the contents of the global spin list T in spin`,
`state s during time domain t.`,
` `,
`This procedure is equivalent to : couple(shift(s,l,t),t);`,
` `,
`EXAMPLE:`,
`> xpulse(spinsystem([A,X]),{A},Pi/2):evolve(",{},t1);`,
`       - Cos(%1) Iy[A] Cos(Pi J[A, X] t1)`,
`       + 2 Cos(%1) Ix[A] Iz[X] Sin(Pi J[A, X] t1)`,
`       + Sin(%1) Ix[A] Cos(Pi J[A, X] t1)`,
`       + 2 Sin(%1) Iy[A] Iz[X] Sin(Pi J[A, X] t1) + Iz[X]`,
`   %1 :=  2 Pi W[A] t1`,
` `,
`SEE ALSO: spinstate, T, shift, couple, observe`):

`help/text/observe`:=TEXT(` `,
`FUNCTION: observe - observe spinstate`,
` `,
`CALLING SEQUENCE: observe(s,l,t,p);`,
` `,
`PARAMETERS: s - spinstate with only cartesian operators`,
`            l - list or set of spins`,
`            t - time domain`,
`            p - phase in radian`,
` `,
`GLOBAL: T`,
` `,
`SYNOPSIS:`,
`Returns the FID that is the result of quadrature detection with a phase`,
`angle p with the x-axis during time domain t, in which both the chemical`,
`shift of spins in l, or T of l is empty, and all possible couplings`,
`evolve.`,
` `,
`EXAMPLE:`,
`> xpulse(spinsystem([A,X]),{A},Pi/2): observe(",{A},t,0);`,
`   - 1/2 Cos(2 Pi W[A] t) I Cos(Pi J[A, X] t)`,
`   + 1/2 Sin(2 Pi W[A] t) Cos(Pi J[A, X] t)`,
` `,
`SEE ALSO: spinstate, FID, T, shift, couple, evolve`):


`help/text/QF`:=TEXT(` `,
`FUNCTION: QF - quantum filtering`,
` `,
`CALLING SEQUENCE: QF(s,q);`,
` `,
`PARAMETERS: s - spinstate with only cartesian operators`,
`            q - coherence order`,
` `,
`GLOBAL: T`,
` `,
`SYNOPSIS:`,
`Returns the terms in spinstate s, that have coherence order of i q,`,
`with i = 1, 2, ... .`,
` `,
`EXAMPLES:`,
`> T:=[A,B]: QF(Ix[A]*Iz[B],2);    # yields 0`,
`> T:=[A,B]: QF(Ix[A]*Iy[B]+Iy[A]*Ix[B],2);`,
`                     Ix[A]*Iy[B]+Iy[A]*Ix[B]`,
` `,
`SEE ALSO: QFpulse`):


`help/text/pm_xy`:=TEXT(` `,
`FUNCTION: pm_xy - convert step operators to cartesian operators`,
` `,
`CALLING SEQUENCE: pm_xy(s);`,
` `,
`PARAMETER: s - spinstate with only step operators, or Iz`,
` `,
`GLOBAL: T`,
` `,
`SYNOPSIS:`,
`Returns the result of the conversion of step operators, Ip and Im, to`,
`cartesian operators in spinstate s.`,
` `,
`EXAMPLES:`,
`> T:=[A]: pm_xy(Ip[A]);  # yields  Ix[A] + I Iy[A]`,
`> T:=[A]: pm_xy(Im[A]);  # yields  Ix[A] - I Iy[A]`,
` `,
`SEE ALSO: xy_pm`):

`help/text/xy_pm`:=TEXT(` `,
`FUNCTION: xy_pm - convert cartesian operators to step operators`,
` `,
`CALLING SEQUENCE: xy_pm(s);`,
` `,
`PARAMETER: s - spinstate with only cartesian operators`,
` `,
`GLOBAL: T`,
` `,
`SYNOPSIS:`,
`Returns the result of the conversion of cartesian operators, Ix and Iy,`,
`to step operators in spinstate s.`,
` `,
`EXAMPLES:`,
`> T:=[A]: xy_pm(Ix[A]);  # yields  1/2 Ip[A] + 1/2 Im[A]`,
`> T:=[A]: xy_pm(Iy[A]);  # yields  1/2 I Im[A] - 1/2 I Ip[A]`,
`> T:=[A]: xy_pm(Iz[A]);  # yields  Iz[A]`,
` `,
`SEE ALSO: pm_xy`):

`help/text/QC`:=TEXT(` `,
`FUNCTION: QC - determine quantum coherence order`,
` `,
`CALLING SEQUENCE: QC(s);`,
` `,
`PARAMETER: s - single spinstate term with only step, and/or Iz`,
`                operators`,
` `,
`SYNOPSIS:`,
`Returns the quantum coherence order of the single spinstate term s.`,
` `,
`EXAMPLES:`,
`> QC(Ip[A]*Ip[B]);  # yields 2`,
`> QC(Ip[A]*Im[B]);  # yields 0`,
` `,
`SEE ALSO: QCset`):

`help/text/QCset`:=TEXT(` `,
`FUNCTION: QCset - determine set of quantum coherence orders`,
` `,
`CALLING SEQUENCE: QCset(s);`,
` `,
`PARAMETER: s - spinstate with only cartesian operators`,
` `,
`GLOBAL: T`,
` `,
`SYNOPSIS:`,
`Returns the set of all quantum coherences present in spinstate s.`,
` `,
`EXAMPLES:`,
`> T:=[A]: QCset(Ix[A]);          # yields  {-1, 1}`,
`> T:=[A,B]: QCset(Ix[A]*Iy[B]);  # yields  {0, -2, 2}`,
` `,
`SEE ALSO: QC`):

`help/text/cleanup`:=TEXT(` `,
`FUNCTION: cleanup - normalized spinstate or FID expression`,
` `,
`CALLING SEQUENCE: cleanup(s);`,
` `,
`PARAMETER: s - spinstate or FID`,
` `,
`SYNOPSIS:`,
`Returns the 'cleaned-up,' or normalized version of spinstate or FID s.`,
` `,
`In order to do that:`,
`- modulations with a constant argument are expressed in trigonometric`,
`  form, i.e. sin and cos in stead of Sin and Cos`,
`- products of modulations with the same indeterminates are expressed as`,
`  sums, or differences of modulation functions, of the sum, or`,
`  differences, of the arguments`,
`- higher powers of Iz[i] are expressed in Iz[i].`,
` `,
`EXAMPLES:`,
`> cleanup(Cos(Pi/2));        # yields  0`,
`> cleanup(Cos(2*x)*Sin(x));  # yields  1/2 Sin(3 x) - 1/2 Sin(x)`,
`> cleanup(Sin(x)^3);         # yields  3/4 Sin(x) - 1/4 Sin(3 x)`,
`> cleanup(Iz[A]^5);          # yields  1/16 Iz[A]`,
` `,
`SEE ALSO: spinstate, FID, nmrsubs`):

`help/text/nmrsubs`:=TEXT(` `,
`FUNCTION: nmrsubs - substitute in spinstate or FID expression`,
` `,
`CALLING SEQUENCE: nmrsubs(e_1,e_2,...,e_n,s);`,
` `,
`PARAMETERS: e_1,...e_n - equations or sets or lists of equations`,
`            s - spinstate or FID`,
` `,
`SYNOPSIS:`,
`Returns the cleaned up result of the substitutions of e_1, e_2,..., e_n`,
`in spinstate s.`,
`This procedure is equivalent to : cleanup(subs(e_1,e_2,...,e_n,s));`,
` `,
`EXAMPLE:`,
`> nmrsubs(J[A,B]=0,Sin(Pi*J[A,B]*t1));  # yields 0`,
` `,
`SEE ALSO: cleanup, spinstate, FID`):

`help/text/FT`:=TEXT(` `,
`FUNCTION: FT - symbolical comples Fourier transform`,
` `,
`CALLING SEQUENCE: FT(s,p,t,v);`,
` `,
`PARAMETERS: s - FID or mixed FID/spectrum`,
`            p - phase angle in radian`,
`            t - time domain`,
`            v - frequency domain`,
` `,
`SYNOPSIS:`,
`Returns the complex Fourier transformed result of s, with a phase`,
`correction p, for time domain t, turning it into peak functions in`,
`frequency domain v.`,
` `,
`Complex Fourier transformation is required for the time domain that has`,
`complex modulations, i.e., the observation time domain.`,
` `,
`EXAMPLES:`,
`> FT(Cos(2*Pi*W[A]*t)*Sin(Pi*J[A,B]*t),Pi/2,t,v);`,
`     1/4 Ab(W[A] + 1/2 J[A, B], v) + 1/4 I Di(W[A] + 1/2 J[A, B], v)`,
`   - 1/4 Ab(W[A] - 1/2 J[A, B], v) - 1/4 I Di(W[A] - 1/2 J[A, B], v)`,
`> FT(Cos(2*Pi*W[A]*t1)*Cos(2*Pi*W[B]*t2),0,t2,v2);`,
`                 1/2 Cos(2 Pi W[A] t1) Ab(W[B], v2)`,
`               + 1/2 Cos(2 Pi W[A] t1) I Di(W[B], v2)`,
` `,
`SEE ALSO: FID, spectrum, CosFT`):

`help/text/CosFT`:=TEXT(` `,
`FUNCTION: CosFT - real, or cosine, Fourier Transform`,
` `,
`CALLING SEQUENCE: CosFT(s,p,t,v);`,
` `,
`PARAMETERS: s - FID or mixed FID/spectrum`,
`            p - phase angle in radian`,
`            t - time domain`,
`            v - frequency domain`,
` `,
`SYNOPSIS:`,
`Returns the cosine, or real, Fourier transformed result of s, with a`,
`phase correction p, for time domain t, turning it into peak functions in`,
`frequency domain v.`,
` `,
`EXAMPLES:`,
`> CosFT(Cos(2*Pi*W[A]*t)*Sin(Pi*J[A,B]*t),Pi/2,t,v);`,
`      1/4 Ab(W[A] + 1/2 J[A, B], v) - 1/4 Ab(W[A] - 1/2 J[A, B], v)`,
`> CosFT(Cos(2*Pi*W[A]*t1)*Cos(2*Pi*W[B]*t2),0,t2,v2);`,
`                 1/2 Cos(2 Pi W[A] t1) Ab(W[B], v2)`,
` `,
`SEE ALSO: FID, spectrum, FT`):

`help/text/lineshape`:=TEXT(` `,
`FUNCTIONS: pA, pD - absorbtion and dispersion lineshape functions`,
` `,
`CALLING SEQUENCE: pA(v0,v,T2); pD(v0,v,T2);`,
` `,
`PARAMETERS: v0 - peak position in Hz`,
`            v - frequency domain`,
`            T2 - relaxation time in seconds`,
` `,
`SYNOPSIS:`,
`Returns the algebraic expression for a absorption (pA) and dispersion`,
`(pD) peak centered at position v0 Hz, in frequency domain v, with a`,
`relaxation time of T2 seconds.`,
` `,
`EXAMPLES:`,
`> evalf(pA(0,crit_A/T2,T2)/pA(0,0,T2));`,
`                                .02470452302`,
`> evalf(pD(0,crit_D/T2,T2)/pD(0,1/(2*Pi*T2),T2));`,
`                                .03182292777`,
`> map(expand,{solve(diff(pD(v0,v,T2),v)=0,v)}); # dispersion extremes`,
`                                 1             1`,
`                        {v0 - -------, v0 + -------}`,
`                              2 Pi T2       2 Pi T2`,
`> plot({pA(v,0,2.0),pD(v,0,2.0)},v=-1..1);`,
` `,
`SEE ALSO: crit_A, crit_D`):
`help/text/pA`:=`help/text/lineshape`:
`help/text/pD`:=`help/text/lineshape`:


`help/text/nmrplot`:=TEXT(` `,
`FUNCTION: nmrplot - create a 1D NMR plot from a spectrum`,
` `,
`CALLING SEQUENCE: nmrplot(s,v=a..b,...);`,
` `,
`PARAMETERS: s - FID or spectrum`,
`            v - frequency or time range`,
`            a,b - real constants`,
` `,
`GLOBALS: Jv, Wv, T2`,
` `,
`SYNOPSIS:`,
`Plots the one-dimensional NMR spectrum s with frequency axis v ranging`,
`from a to b. The peak routines Ab and Di are substituted with their`,
`numeric counterparts, pA and pD. If certain necessary global variables`,
`are not defined, the plot will remain empty.`,
` `,
`This procedure can also be used to plot a one-dimensional subspectrum`,
`from a higher dimensional spectrum by using the proper substitutions.`,
` `,
`Optional parameters are the same as for plot.`,
` `,
`EXAMPLES:`,
`> Jv[A,B]:=2: Wv[A]:=0: T2[A]:=1:       # define required globals`,
`> nmrplot(Ab(W[A]+J[A,B]/2,v),v=0..2);`,
`> nmrplot(subs(v1=Wv[A]-Jv[A,B]/2,spc2),v2=-20..100);`,
`   # where spc2 is a 2 dimensional spectrum`,
` `,
`SEE ALSO: plot, Jv, Wv, T2`):

`help/text/nmrplot2d`:=TEXT(` `,
`FUNCTION: nmrplot2d - create a 2D NMR plot from a spectrum`,
` `,
`CALLING SEQUENCE: nmrplot2d(s,v1=a..b,v2=c..d,...);`,
` `,
`PARAMETERS: s - FID, spectrum , or mixed FID/spectrum`,
`            v1 - frequency or time range 1`,
`            v2 - frequency or time range 2`,
`            a,b,c,d - real constants`,
` `,
`GLOBALS: Jv, Wv, T2`,
` `,
`SYNOPSIS:`,
`Plots the two-dimensional FID, spectrum or mixed FID/spectrum s with`,
`axes v1 ranging from a to b, and v2 ranging from c to d. The peak`,
`routines Ab and Di are substituted with their numeric counterparts, pA`,
`and pD. If certain necessary global variables are not defined, the plot`,
`will remain empty.`,
` `,
`This procedure has drawbacks:`,
`- it can take quite a bit of time if there are several peaks present`,
`- when the top of the peak is not on a grid point the peak may look`,
`  asymmetrical.`,
`To avoid these problems in case of plotting a spectrum use the procedure`,
`super2d.`,
` `,
`This procedure can also be used to plot a two-dimensional subspectrum`,
`from a higher dimensional spectrum by using the proper substitutions.`,
` `,
`Optional parameters are the same as for plot3d.`,
` `,
`EXAMPLE:`,
`> Wv:=table([A=0,B=4]): T2:=table([A=1,B=1]):   # required globals`,
`> nmrplot2d(Ab(W[A],v1)*Di(W[B],v2),v1=-1..1,v2=3..5,axes=FRAME);`,
` `,
`SEE ALSO: nmrplot2d, plot3d[options], Jv, Wv, T2`):


`help/text/super2d`:=TEXT(` `,
`FUNCTION: super2d - create a 2d NMR plot of superpositioned peaks`,
` `,
`CALLING SEQUENCES: super2d(s,v1,v2);`,
`                   super2d(s,v1,v2,...);`,
` `,
`PARAMETERS: s - spectrum`,
`            v1 - frequency axis 1`,
`            v2 - frequency axis 2`,
` `,
`GLOBALS: Jv, Wv, T2, crit_A, crit_D`,
` `,
`SYNOPSIS:`,
`Plots the superposition of all terms present in a two-dimensional`,
`spectrum s with frequency axes v1 and v2. The peak routines Ab and Di`,
`are substituted with their numeric counterparts, pA and pD. If certain`,
`necessary global variables are not defined, the plot will remain empty.`,
` `,
`This procedure has drawbacks:`,
`- it is not smart with collisions, i.e., when a peak consists of the sum`,
`  of two lineshape functions, these two are not added together but drawn`,
`  on top of eachother. To avoid this, one can eliminate all dispersion`,
`  peaks (see Di).`,
`- in order to be sure that the centers of the absorption peaks are on`,
`  grid points, set the number of gridpoints equal to 2n*2n.`,
` `,
`This procedure can also be used to plot a 2 dimensional subspectrum from`,
`a higher dimensional spectrum by using the proper substitutions.`,
` `,
`Optional parameters are the same as for plot3d.`,
` `,
`EXAMPLE:`,
`> Wv:=table([A=0,B=6]): T2:=table([A=1,B=1]): J[A,B]:=2:`,
`> spec:= Ab(W[A]+J[A,B]/2,v1)*Ab(W[B],v2)`,
`        +Ab(W[A]-J[A,B]/2,v1)*Ab(W[B],v2):`,
`> super2d(spec,v2,v1,numpoints=6*6,axes=FRAME,orientation=[120,60]);`,
` `,
`SEE ALSO: nmrplot2d, plot3d[options], Di, crit_A, crit_D, Jv, Wv, T2`):

# NOTE the following two assignments had to be made to make sure that
# I get the help I defined for T and J, and not the other ones.
#`help/orthopoly/text/T`:=`help/text/T`:
#`help/numtheory/text/jacobi`:=`help/text/J`:


# end of the pofhelp.map file

# print(`POF-NMR procedures saved in file pof.m`);
print(`On-line help included : try ?pof;`);

#save `pof.m`:
#quit
