Upgrades to argproc.py, finite rectangular lattice scatter script.

Former-commit-id: 36aba53dc445752cf50e1638883f5a280ccab753
This commit is contained in:
Marek Nečada 2019-12-14 13:26:40 +02:00
parent ef1c699861
commit dc5d2cde0b
2 changed files with 54 additions and 18 deletions

View File

@ -4,13 +4,9 @@ import math
from qpms.argproc import ArgParser
ap = ArgParser(['single_particle', 'single_omega', 'single_lMax'])
ap.add_argument("-p", "--period", type=float, required=True, help='square lattice period')
ap.add_argument("--Nx", type=int, required=True, help='Array size x')
ap.add_argument("--Ny", type=int, required=True, help='Array size y')
ap = ArgParser(['rectlattice2d_finite', 'single_particle', 'single_lMax', 'single_omega'])
ap.add_argument("-k", '--kx-lim', nargs=2, type=float, required=True, help='k vector', metavar=('KX_MIN', 'KX_MAX'))
# ap.add_argument("--kpi", action='store_true', help="Indicates that the k vector is given in natural units instead of SI, i.e. the arguments given by -k shall be automatically multiplied by pi / period (given by -p argument)")
ap.add_argument("--rank-tol", type=float, required=False)
ap.add_argument("-o", "--output", type=str, required=False, help='output path (if not provided, will be generated automatically)')
ap.add_argument("-N", type=int, default="151", help="Number of angles")
ap.add_argument("-O", "--plot-out", type=str, required=False, help="path to plot output (optional)")
@ -23,12 +19,14 @@ a=ap.parse_args()
import logging
logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO)
Nx, Ny = a.size
px, py = a.period
particlestr = ("sph" if a.height is None else "cyl") + ("_r%gnm" % (a.radius*1e9))
if a.height is not None: particlestr += "_h%gnm" % (a.height * 1e9)
defaultprefix = "%s_p%gnm_%dx%d_m%s_n%g_angles(%g_%g)_Ey_f%geV_L%d_cn%d" % (
particlestr, a.period*1e9, a.Nx, a.Ny, str(a.material), a.refractive_index, a.kx_lim[0], a.kx_lim[1], a.eV, a.lMax, a.N)
logging.info("Dafault file prefix: %s" % defaultprefix)
defaultprefix = "%s_p%gnmx%gnm_%dx%d_m%s_n%g_angles(%g_%g)_Ey_f%geV_L%d_cn%d" % (
particlestr, px*1e9, py*1e9, Nx, Ny, str(a.material), a.refractive_index, a.kx_lim[0], a.kx_lim[1], a.eV, a.lMax, a.N)
logging.info("Default file prefix: %s" % defaultprefix)
import numpy as np
@ -44,12 +42,9 @@ eh = eV/hbar
dbgmsg_enable(DebugFlags.INTEGRATION)
px=a.period
py=a.period
#Particle positions
orig_x = (np.arange(a.Nx/2) + (0 if (a.Nx % 2) else .5)) * px
orig_y = (np.arange(a.Ny/2) + (0 if (a.Ny % 2) else .5)) * py
orig_x = (np.arange(Nx/2) + (0 if (Nx % 2) else .5)) * px
orig_y = (np.arange(Ny/2) + (0 if (Ny % 2) else .5)) * py
orig_xy = np.stack(np.meshgrid(orig_x, orig_y), axis = -1)

View File

@ -3,13 +3,28 @@ Common snippets for argument processing in command line scripts; legacy scripts
'''
import argparse
import sys
def make_action_sharedlist(opname, listname):
class opAction(argparse.Action):
def __call__(self, parser, args, values, option_string=None):
if (not hasattr(args, listname)) or getattr(args, listname) is None:
setattr(args, listname, list())
getattr(args, listname).append((opname, values))
return opAction
class AppendTupleAction(argparse.Action):
''' A variation on the 'append' builtin action from argparse, but uses tuples for the internal groupings instead of lists '''
def __call__(self, parser, args, values, option_string=None):
if (not hasattr(args, self.dest)) or getattr(args, self.dest) is None:
setattr(args, self.dest, list())
getattr(args, self.dest).append(tuple(values))
class ArgParser:
''' Common argument parsing engine for QPMS python CLI scripts. '''
atomic_arguments = {
'sqlat_period': lambda ap: ap.add_argument("-p", "--period", type=float, required=True, help='square lattice period'),
'rectlat_Nx': lambda ap: ap.add_argument("--Nx", type=int, required=True, help='array size x'),
'rectlat_Ny': lambda ap: ap.add_argument("--Ny", type=int, required=True, help='array size y'),
'rectlattice2d_periods': lambda ap: ap.add_argument("-p", "--period", type=float, nargs='+', required=True, help='square/rectangular lattice periods', metavar=('px','[py]')),
'rectlattice2d_counts': lambda ap: ap.add_argument("--size", type=int, nargs=2, required=True, help='rectangular array size (particle column, row count)', metavar=('NCOLS', 'NROWS')),
'single_frequency_eV': lambda ap: ap.add_argument("-f", "--eV", type=float, required=True, help='radiation angular frequency in eV'),
'single_material': lambda ap: ap.add_argument("-m", "--material", help='particle material (Au, Ag, ... for Lorentz-Drude or number for constant refractive index)', default='Au', required=True),
'single_radius': lambda ap: ap.add_argument("-r", "--radius", type=float, required=True, help='particle radius (sphere or cylinder)'),
@ -19,9 +34,10 @@ class ArgParser:
'bg_refractive_index': lambda ap: ap.add_argument("-n", "--refractive-index", type=float, default=1.52, help='background medium refractive index'),
'single_lMax': lambda ap: ap.add_argument("-L", "--lMax", type=int, required=True, default=3, help='multipole degree cutoff'),
'single_lMax_extend': lambda ap: ap.add_argument("--lMax-extend", type=int, required=False, default=6, help='multipole degree cutoff for T-matrix calculation (cylindrical particles only'),
'outfile': lambda ap: ap.add_argument("-o", "--output", type=str, required=False, help='output path (if not provided, will be generated automatically)'),
'outfile': lambda ap: ap.add_argument("-o", "--output", type=str, required=False, help='output path (if not provided, will be generated automatically)'), # TODO consider type=argparse.FileType('w')
'plot_out': lambda ap: ap.add_argument("-O", "--plot-out", type=str, required=False, help="path to plot output (optional)"),
'plot_do': lambda ap: ap.add_argument("-P", "--plot", action='store_true', help="if -p not given, plot to a default path"),
'lattice2d_basis': lambda ap: ap.add_argument("-b", "--basis-vector", action=AppendTupleAction, help="basis vector in xy-cartesian coordinates (two required)", dest='basis_vectors', metavar=('X', 'Y')),
}
feature_sets_available = { # name : (description, dependencies, atoms not in other dependencies, methods called after parsing)
@ -29,6 +45,9 @@ class ArgParser:
'single_particle': ("Single particle definition (shape [currently spherical or cylindrical]) and materials, incl. background)", ('background',), ('single_material', 'single_radius', 'single_height', 'single_lMax_extend'), ('_eval_single_tmgen',)),
'single_lMax': ("Single particle lMax definition", (), ('single_lMax',), ()),
'single_omega': ("Single angular frequency", (), ('single_frequency_eV',), ('_eval_single_omega',)),
'lattice2d': ("Specification of a generic 2d lattice (spanned by the x,y axes)", (), ('lattice2d_basis',), ('_eval_lattice2d',)),
'rectlattice2d': ("Specification of a rectangular 2d lattice; conflicts with lattice2d", (), ('rectlattice2d_periods',), ('_eval_rectlattice2d',)),
'rectlattice2d_finite': ("Specification of a rectangular 2d lattice; conflicts with lattice2d", ('rectlattice2d',), ('rectlattice2d_counts',), ()),
}
@ -43,7 +62,7 @@ class ArgParser:
def add_feature(self, feat):
if feat not in self.features_enabled:
if feat not in ArgParser.feature_sets_available:
raise ValueError("Unknown ArgParser feature: %s", feat)
raise ValueError("Unknown ArgParser feature: %s" % feat)
#resolve dependencies
_, deps, atoms, atparse = ArgParser.feature_sets_available[feat]
for dep in deps:
@ -99,4 +118,26 @@ class ArgParser:
from .constants import eV, hbar
self.omega = self.args.eV * eV / hbar
def _eval_lattice2d(self): # feature: lattice2d
l = len(self.args.basis_vectors)
if l != 2: raise ValueError('Two basis vectors must be specified (have %d)' % l)
from .qpms_c import lll_reduce
self.direct_basis = lll_reduce(self.args.basis_vector, delta=1.)
# import numpy as np
# self.reciprocal_basis1 = np.linalg.inv(self.direct_basis)
# self.reciprocal_basis2pi = 2 * np.pi * self.reciprocal_basis1
def _eval_rectlattice2d(self): # feature: rectlattice2d
a = self.args
l = len(a.period)
if (l == 1): # square lattice
a.period = (a.period[0], a.period[0])
else:
a.period = (a.period[0], a.period[1])
if (l > 2):
raise ValueError("At most two lattice periods allowed for a rectangular lattice (got %d)" % l)
import numpy as np
a.basis_vectors = [(a.period[0], 0.), (0., a.period[1])]
self.direct_basis = np.array(a.basis_vectors)