Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
pykat
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Sebastian Steinlechner
pykat
Commits
9d9aafe6
Commit
9d9aafe6
authored
9 years ago
by
Daniel Toyra
Browse files
Options
Downloads
Patches
Plain Diff
More mirror map stuff. Basically finished now
parent
ad305e9e
No related branches found
No related tags found
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
pykat/optics/maps.py
+129
-46
129 additions, 46 deletions
pykat/optics/maps.py
with
129 additions
and
46 deletions
pykat/optics/maps.py
+
129
−
46
View file @
9d9aafe6
...
...
@@ -42,15 +42,17 @@ class MirrorROQWeights:
class
surfacemap
(
object
):
def
__init__
(
self
,
name
,
maptype
,
size
,
center
,
step_size
,
scaling
,
data
=
None
,
notNan
=
None
,
Rc
=
None
,
zOffset
=
None
,
xyOffset
=
None
):
notNan
=
None
,
Rc
=
None
,
zOffset
=
None
,
xyOffset
=
(.
0
,.
0
)
):
self
.
name
=
name
self
.
type
=
maptype
# Currently "beam center", i.e., mirror_center + xyOffset.
self
.
center
=
center
self
.
step_size
=
step_size
self
.
scaling
=
scaling
self
.
notNan
=
notNan
self
.
Rc
=
Rc
# Offset of fitted sphere. Proably unnecessary to have here.
self
.
zOffset
=
zOffset
self
.
__interp
=
None
self
.
_zernikeRemoved
=
{}
...
...
@@ -86,6 +88,33 @@ class surfacemap(object):
mapfile
.
write
(
"
%.15g
"
%
self
.
data
[
i
,
j
])
mapfile
.
write
(
"
\n
"
)
@property
def
xyOffset
(
self
):
'''
The offset from the mirror center measured in meters.
'''
return
self
.
_xyOffset
@xyOffset.setter
def
xyOffset
(
self
,
offset
):
'''
Give
'
offset
'
is in meters.
'''
x0new
=
self
.
center
[
0
]
+
(
-
self
.
xyOffset
[
0
]
+
offset
[
0
])
/
self
.
step_size
[
0
]
y0new
=
self
.
center
[
1
]
+
(
-
self
.
xyOffset
[
1
]
+
offset
[
1
])
/
self
.
step_size
[
1
]
# Checking so new suggested "center" is within the the mirror surface
if
(
x0new
>
0
and
x0new
<
self
.
size
[
0
]
-
1
and
y0new
>
0
and
y0new
<
self
.
size
[
1
]
-
1
and
self
.
notNan
[
round
(
x0new
),
round
(
y0new
)]):
self
.
center
=
(
x0new
,
y0new
)
self
.
_xyOffset
=
(
offset
[
0
],
offset
[
1
])
else
:
print
((
'
Error in xyOffset: ({:.2e}, {:.2e}) m --> pos = ({:.2f}, {:.2f})
'
+
'
is outside mirror surface.
'
).
format
(
offset
[
0
],
offset
[
1
],
x0new
,
y0new
))
@property
def
betaRemoved
(
self
):
...
...
@@ -419,6 +448,12 @@ class surfacemap(object):
def
rms
(
self
,
w
=
None
):
'''
Returns the root mean square value of the mirror map, expressed in the unit
given by self.scaling. If w [m] is specified, only the area inside the radius
is considered. The area is r<w is centered around the self.center, i.e., the
beam center (not mirror center).
'''
if
w
is
None
:
return
math
.
sqrt
((
self
.
data
[
self
.
notNan
]
**
2
).
sum
())
/
self
.
notNan
.
sum
()
else
:
...
...
@@ -433,6 +468,12 @@ class surfacemap(object):
return
math
.
sqrt
((
self
.
data
[
inside
]
**
2
).
sum
())
/
inside
.
sum
()
def
avg
(
self
,
w
=
None
):
'''
Returns the average height of the mirror map, expressed in the unit
given by self.scaling. If w [m] is specified, only the area inside the radius
is considered. The area is r<w is centered around the self.center, i.e., the
beam center (not mirror center).
'''
if
w
is
None
:
tot
=
self
.
data
[
self
.
notNan
].
sum
()
sgn
=
np
.
sign
(
tot
)
...
...
@@ -455,7 +496,10 @@ class surfacemap(object):
def
find_radius
(
self
,
method
=
'
max
'
,
unit
=
'
points
'
):
'''
Estimates the radius of the mirror in the xy-plane.
Estimates the radius of the mirror in the xy-plane. If xyOffset is different from
(0,0), then the radius will be the minimum distance from the beam center to the
nearest mirror edge.
method -
'
max
'
gives maximal distance from centre to the edge.
'
xy
'
returns the distance from centre to edge along x- and y-directions.
'
area
'
calculates the area and uses this to estimate the mean radius.
...
...
@@ -938,6 +982,7 @@ class surfacemap(object):
x0
=
float
(
cIndx
.
sum
())
/
len
(
cIndx
)
y0
=
float
(
rIndx
.
sum
())
/
len
(
rIndx
)
self
.
center
=
tuple
([
x0
,
y0
])
self
.
xyOffset
=
(.
0
,.
0
)
return
self
.
center
# -------------------------------------------------
...
...
@@ -948,6 +993,9 @@ class surfacemap(object):
Based on FT_remove_elements_outside_map.m by Charlotte Bond.
'''
# Saves the xyOffset to restore it afterwards
xyOffset
=
self
.
xyOffset
self
.
recenter
()
# Arrays of row and column indices where data is NaN.
r
,
c
=
np
.
where
(
self
.
notNan
==
False
)
# Sets the map center to index [0,0]
...
...
@@ -971,15 +1019,19 @@ class surfacemap(object):
# Radius inside data is kept. Don't know why R is set this way,
# but trusting Dr. Bond.
R
=
round
(
math
.
ceil
(
2.0
*
math
.
sqrt
(
r2
)
+
6.0
)
/
2.0
)
if
2
*
R
<
self
.
data
.
shape
[
0
]
and
2
*
R
<
self
.
data
.
shape
[
1
]:
if
(
2
*
R
<
self
.
data
.
shape
[
0
]
and
2
*
R
<
self
.
data
.
shape
[
1
]
and
R
<
self
.
center
[
0
]
and
R
<
self
.
center
[
1
]
and
R
<
(
self
.
size
[
0
]
-
self
.
center
[
0
])
and
R
<
(
self
.
size
[
1
]
-
self
.
center
[
1
])):
x0
=
round
(
self
.
center
[
0
])
y0
=
round
(
self
.
center
[
1
])
self
.
data
=
self
.
data
[
y0
-
R
:
y0
+
R
+
1
,
x0
-
R
:
x0
+
R
+
1
]
self
.
notNan
=
self
.
notNan
[
y0
-
R
:
y0
+
R
+
1
,
x0
-
R
:
x0
+
R
+
1
]
# Centering the new cropped map and restoring offset
self
.
recenter
()
self
.
xyOffset
=
xyOffset
def
createSurface
(
self
,
Rc
,
X
,
Y
,
zOffset
=
0
,
x0
=
0
,
y0
=
0
,
xTilt
=
0
,
yTilt
=
0
,
isPlot
=
False
):
...
...
@@ -1164,13 +1216,13 @@ class surfacemap(object):
print
(
'
Writing result information to file...
'
)
# --------------------------------------------------------
filename
=
self
.
name
+
'
_finesse_info.txt
'
self
.
writeMapPrepResults
(
filename
)
self
.
writeMapPrepResults
(
filename
,
w
)
if
verbose
:
print
(
'
Result written to file {:s}
'
.
format
(
filename
))
# Printing results to terminal
print
(
'
--------------------------------------------------
'
)
print
(
'
Phase map prepared!
:D
'
)
print
(
'
Phase map prepared!
'
)
print
(
'
Name: {:s}
'
.
format
(
self
.
name
))
print
(
'
Type: {:s}
'
.
format
(
self
.
type
))
print
(
'
--------------------------------------------------
'
)
...
...
@@ -1192,16 +1244,14 @@ class surfacemap(object):
print
(
'
Stats: rms = {:.3e} nm
'
.
format
(
self
.
rms
(
w
)))
print
(
'
avg = {:.3e} nm
'
.
format
(
self
.
avg
(
w
)))
print
(
'
--------------------------------------------------
'
)
print
()
# Todo:
# Add "create aperture map"
def
writeMapPrepResults
(
self
,
filename
):
def
writeMapPrepResults
(
self
,
filename
,
w
):
'''
Writing results to file. Not yet finished.
'''
...
...
@@ -1211,7 +1261,11 @@ class surfacemap(object):
mapfile
.
write
(
'
Map: {:s}
\n
'
.
format
(
self
.
name
))
mapfile
.
write
(
'
Date: {:s}
\n
'
.
format
(
time
.
strftime
(
"
%d/%m/%Y %H:%M:%S
"
)))
mapfile
.
write
(
'
---------------------------------------
\n
'
)
mapfile
.
write
(
'
Diameter: {:.2f} cm
\n
'
.
format
(
self
.
find_radius
(
unit
=
'
meters
'
)
*
200.0
))
if
w
is
None
:
mapfile
.
write
(
'
Weights: None
'
)
else
:
mapfile
.
write
(
'
Weights: r = {:.2f} cm
'
.
format
(
w
*
100
))
mapfile
.
write
(
'
Diameter: D = {:.2f} cm
\n
'
.
format
(
self
.
find_radius
(
unit
=
'
meters
'
)
*
200.0
))
mapfile
.
write
(
'
Offset: A00 = {:.2f} nm
\n
'
.
format
(
self
.
zernikeRemoved
[
'
00
'
][
2
]))
mapfile
.
write
(
'
Tilt: A1-1 = {:.2f} nm
\n
'
.
format
(
self
.
zernikeRemoved
[
'
-11
'
][
2
]))
mapfile
.
write
(
'
A11 = {:.2f} nm, or
\n
'
.
format
(
self
.
zernikeRemoved
[
'
11
'
][
2
]))
...
...
@@ -1649,6 +1703,8 @@ def read_map(filename, mapFormat='finesse', scaling=1.0e-9, mapType='phase', fie
maptype
=
'
'
.
join
([
mapType
,
field
])
if
mapFormat
==
'
ligo
'
:
isLigo
=
True
# Unused, but need to set it to call the function.
isAscii
=
False
# Remove '_asc.dat' for output name
name
=
filename
.
split
(
'
_
'
)
name
=
'
_
'
.
join
(
name
[:
-
1
])
...
...
@@ -1663,8 +1719,13 @@ def read_map(filename, mapFormat='finesse', scaling=1.0e-9, mapType='phase', fie
isAscii
=
False
# Reading the zygo/ligo surface map file. Note that the intensity data
# iData is available here too, but at the moment it's not returned.
hData
,
data
,
iData
=
readZygoLigoMaps
(
filename
,
isLigo
=
False
,
isAscii
=
True
)
# iData is available here too when ascii zygo files are read, but at
# the moment it's not used.
out
=
readZygoLigoMaps
(
filename
,
isLigo
,
isAscii
)
if
len
(
out
)
==
3
:
hData
,
data
,
iData
=
out
else
:
hData
,
data
=
out
# Matrix with True where data element is NaN.
isNan
=
np
.
isnan
(
data
)
...
...
@@ -1674,7 +1735,6 @@ def read_map(filename, mapFormat='finesse', scaling=1.0e-9, mapType='phase', fie
data
[
isNan
]
=
0
# Scaling to the scaling chosesen as input.
data
[
notNan
]
=
(
hData
[
'
hScale
'
]
/
scaling
)
*
data
[
notNan
]
smap
=
surfacemap
(
name
,
maptype
,
hData
[
'
size
'
],
hData
[
'
center
'
],
hData
[
'
stepSize
'
],
scaling
,
data
,
notNan
)
smap
.
recenter
()
...
...
@@ -1777,28 +1837,45 @@ def readZygoLigoMaps(filename, isLigo=False, isAscii=True):
R
=
4096
elif
phaseRes
==
1
:
R
=
32768
else
:
print
(
'
Error, invalid phase resolution
'
)
return
0
if
not
isLigo
and
not
isAscii
:
# zygo .xyz files give phase data in microns.
hData
[
'
hScale
'
]
=
1.0e-6
else
:
# zygo .asc and ligo-files give phase data in
# internal units. To convert to m use hScale
# factor.
hData
[
'
hScale
'
]
=
S
*
O
*
lam
/
R
if
not
isLigo
and
not
isAscii
:
print
(
'
Not implemented yet, need a .xyz-file
'
+
'
to do this.
'
)
return
0
# Skipping three lines
for
k
in
range
(
3
):
f
.
readline
()
if
not
isLigo
:
if
not
isAscii
:
# For the zygo .xyz-format.
k
=
0
data
=
np
.
zeros
(
rows
*
cols
)
totRuns
=
cols
*
rows
# Skipping four lines
for
k
in
range
(
4
):
# Read data
while
k
<
cols
*
rows
:
line
=
f
.
readline
().
split
()
# Setting 'no data' to NaN
if
len
(
line
)
==
4
:
data
[
k
]
=
np
.
nan
# Reading value
elif
len
(
line
)
==
3
:
data
[
k
]
=
float
(
line
[
2
])
# Otherwise stop reading
else
:
k
=
cols
*
rows
k
+=
1
else
:
# Skipping one line
f
.
readline
()
if
not
isLigo
and
isAscii
:
# Reading intensity data
iData
=
np
.
array
([])
line
=
f
.
readline
().
split
()
...
...
@@ -1809,10 +1886,13 @@ def readZygoLigoMaps(filename, isLigo=False, isAscii=True):
iData
=
iData
.
reshape
(
iRows
,
iCols
).
transpose
()
iData
=
np
.
rot90
(
iData
)
else
:
# Skipping one line
f
.
readline
()
# Skipping lines until '#' is found.
while
f
.
readline
()[
0
]
!=
'
#
'
:
pass
if
isLigo
or
(
not
isLigo
and
isAscii
):
# Reading phase data
# ----------------------------------------------
# Array with the data
...
...
@@ -1862,7 +1942,10 @@ def readZygoLigoMaps(filename, isLigo=False, isAscii=True):
# xy-stepsize
hData
[
'
stepSize
'
]
=
tuple
([
xstep
,
ystep
])
if
not
isLigo
and
isAscii
:
return
hData
,
data
,
iData
else
:
return
hData
,
data
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment