Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
finesse
pykat
Commits
f14d8882
Commit
f14d8882
authored
Aug 12, 2015
by
Daniel Toyra
Browse files
Added function that reads the binary metroPro files
parent
06194b20
Changes
1
Hide whitespace changes
Inline
Side-by-side
pykat/optics/maps.py
View file @
f14d8882
...
...
@@ -399,6 +399,24 @@ class surfacemap(object):
return
fig
def
rescaleData
(
self
,
scaling
):
'''
Rescaling data. Assumes that the current map is scaled correctly, i.e.,
surfacemap.scaling*surfacemap.data would give the data in meters.
Input: scaling
scaling - float number that representing the new scaling. E.g.,
scaling = 1.0e-9 means that surfacemap.data is converted to
being given in nano meters.
'''
if
isinstance
(
scaling
,
float
):
self
.
data
[
self
.
notNan
]
=
self
.
data
[
self
.
notNan
]
*
self
.
scaling
/
scaling
self
.
scaling
=
scaling
else
:
print
(
'Error: Scaling factor must be of type float, {:s} found'
.
format
(
type
(
scaling
)))
def
rms
(
self
,
w
=
None
):
if
w
is
None
:
return
math
.
sqrt
((
self
.
data
[
self
.
notNan
]
**
2
).
sum
())
/
self
.
notNan
.
sum
()
...
...
@@ -1821,44 +1839,186 @@ def read_map(filename, mapFormat='finesse', scaling=1.0e-9):
# map with surfacemap.plot().
data
[
isNan
]
=
0
return
surfacemap
(
name
,
maptype
,
size
,
center
,
step
,
scaling
,
data
,
notNan
)
return
surfacemap
(
name
,
maptype
,
(
0
,
0
),
center
,
step
,
scaling
,
data
,
notNan
)
if
mapFormat
==
'metroPro'
:
# Remove '.dat' for output name
name
=
filename
.
split
(
'.'
)[
0
]
# Reading file
data
,
hData
,
x1
,
y1
=
readMetroProData
(
filename
)
# xy-stepsize in meters
stepSize
=
(
hData
[
'cameraRes'
],
hData
[
'cameraRes'
])
# Temporary center
center
=
((
len
(
data
[
0
,:])
-
1
)
/
2.0
,(
len
(
data
[:,
0
])
-
1
)
/
2.0
)
# Keeping track of nan's
isNan
=
np
.
isnan
(
data
)
notNan
=
isNan
==
False
data
[
isNan
]
=
0
# Change this:
mType
=
'phase'
fType
=
'both'
maptype
=
' '
.
join
([
mType
,
fType
])
# Unnecessary size, remove from class later
size
=
data
.
shape
[::
-
1
]
smap
=
surfacemap
(
name
,
maptype
,
size
,
center
,
stepSize
,
1.0
,
data
,
notNan
)
smap
.
rescaleData
(
scaling
)
smap
.
recenter
()
# TODO: Add options for reading virgo maps, and .xyz zygo
# maps (need .xys file for this). Binary ligo-maps?
# The intensity data is not used to anything here. Remove
# or add to pykat?
return
smap
def
readMetroProData
(
filename
):
'''
Reading the metroPro binary data files.
Translated from 'LoadMetroProData.m' by Hiro Yamamoto.
'''
f
=
BinaryReader
(
filename
)
# Read header
hData
=
readHeaderMP
(
f
)
if
hData
[
'format'
]
<
0
:
print
(
'Error: Format unknown to readMetroProData()
\n
filename: {:s}'
.
format
(
filename
))
return
0
# Read phase map data
# Skipping header and intensity data
f
.
seek
(
hData
[
'size'
]
+
hData
[
'intNBytes'
])
# Reading data
dat
=
f
.
read
(
'int32'
,
size
=
hData
[
'Nx'
]
*
hData
[
'Ny'
])
# Marking unmeasured data as NaN
dat
[
dat
>=
hData
[
'invalid'
]]
=
np
.
nan
# Scale data to meters
dat
=
dat
*
hData
[
'convFactor'
]
# Reshaping into Nx * Ny matrix
dat
=
dat
.
reshape
(
hData
[
'Ny'
],
hData
[
'Nx'
])
# Flipping up/down, i.e., change direction of y-axis.
dat
=
dat
[::
-
1
,:]
# Auxiliary data to return
dxy
=
hData
[
'cameraRes'
]
print
(
dxy
)
x1
=
dxy
*
np
.
arange
(
-
(
len
(
dat
[
0
,:])
-
1
)
/
2
,
(
len
(
dat
[
0
,:])
-
1
)
/
2
+
1
)
y1
=
dxy
*
np
.
arange
(
-
(
len
(
dat
[:,
0
])
-
1
)
/
2
,
(
len
(
dat
[:,
1
])
-
1
)
/
2
+
1
)
## def rnm(n,m,rho):
## '''
## Based on 'FT_Rnm.m'.
## Calculates radial part of the Zernike polynomial for given n and m, and rho.
## n - Radial coordinate
## m - Azimuthal coordinate
## rho - Matrix with normalised radial coordinates, i.e., rho[i,j] <= 1.
## '''
return
dat
,
hData
,
x1
,
y1
def
readHeaderMP
(
f
):
'''
Reads header of the metroPro format files.
## m = abs(m)
## Rnm = 0
## # If n<=25 we use original formula, otherwise recurrence formula as factorials lead
## # to very large numbers.
## if n<=25:
## # Radial term
## S = int((n-m)/2)
## for k in range(S+1):
## a = ((-1)**k)*math.factorial(n-k)/\
## (math.factorial(k)*math.factorial((n+m)/2.0-k)*math.factorial((n-m)/2.0-k))
## p = a*rho**(n-2*k)
## Rnm = Rnm+p
## else:
## # Use recurrence formula
## pass
Translated from the readerHeader() function within the
'LoadMetroProData.m' function written by Hiro Yamamoto.
'''
hData
=
{}
hData
[
'magicNum'
]
=
f
.
read
(
'uint32'
)
hData
[
'format'
]
=
f
.
read
(
'int16'
)
hData
[
'size'
]
=
f
.
read
(
'int32'
)
# Check if the magic string and format are known ones.
if
not
(
hData
[
'format'
]
>=
1
and
hData
[
'format'
]
<=
3
and
hData
[
'magicNum'
]
-
hData
[
'format'
]
==
int
(
'881B036E'
,
16
)):
hData
[
'format'
]
=
-
1
# Read necessary data
hData
[
'invalid'
]
=
int
(
'7FFFFFF8'
,
16
)
f
.
seek
(
60
)
# Intensity data, which we will skip over.
hData
[
'intNBytes'
]
=
f
.
read
(
'int32'
)
# Top-left coordinates, which are useless.
hData
[
'X0'
]
=
f
.
read
(
'int16'
)
hData
[
'Y0'
]
=
f
.
read
(
'int16'
)
# Number of data points alng x and y
hData
[
'Nx'
]
=
f
.
read
(
'int16'
)
hData
[
'Ny'
]
=
f
.
read
(
'int16'
)
# Total data, 4*Nx*Ny
hData
[
'phaNBytes'
]
=
f
.
read
(
'int32'
)
f
.
seek
(
218
)
# Scale factor determined by phase resolution tag
phaseResTag
=
f
.
read
(
'int16'
)
if
phaseResTag
==
0
:
phaseResVal
=
4096
elif
phaseResTag
==
1
:
phaseResVal
=
32768
elif
phaseResTag
==
2
:
phaseResVal
=
131072
else
:
phaseResVal
=
0
f
.
seek
(
164
)
intf_scale_factor
=
f
.
read
(
'float'
)
hData
[
'waveLength'
]
=
f
.
read
(
'float'
)
f
.
seek
(
176
)
obliquity_factor
=
f
.
read
(
'float'
)
# Eq. in p12-6 in MetroPro Reference Guide
hData
[
'convFactor'
]
=
intf_scale_factor
*
obliquity_factor
*
\
hData
[
'waveLength'
]
/
phaseResVal
# Bin size of each measurement
f
.
seek
(
184
)
hData
[
'cameraRes'
]
=
f
.
read
(
'float'
)
## return Rnm
return
hData
import
struct
class
BinaryReaderEOFException
(
Exception
):
def
__init__
(
self
):
pass
def
__str__
(
self
):
return
'Not enough bytes in file to satisfy read request'
class
BinaryReader
:
# Map well-known type names into struct format characters.
typeNames
=
{
'int8'
:
'b'
,
'uint8'
:
'B'
,
'int16'
:
'h'
,
'uint16'
:
'H'
,
'int32'
:
'i'
,
'uint32'
:
'I'
,
'int64'
:
'q'
,
'uint64'
:
'Q'
,
'float'
:
'f'
,
'double'
:
'd'
,
'char'
:
's'
}
def
__init__
(
self
,
fileName
):
self
.
file
=
open
(
fileName
,
'rb'
)
def
read
(
self
,
typeName
,
size
=
None
):
typeFormat
=
BinaryReader
.
typeNames
[
typeName
.
lower
()]
typeFormat
=
'>'
+
typeFormat
typeSize
=
struct
.
calcsize
(
typeFormat
)
if
size
is
None
:
value
=
self
.
file
.
read
(
typeSize
)
if
typeSize
!=
len
(
value
):
raise
BinaryReaderEOFException
unpacked
=
struct
.
unpack
(
typeFormat
,
value
)[
0
]
else
:
value
=
self
.
file
.
read
(
size
*
typeSize
)
if
size
*
typeSize
!=
len
(
value
):
raise
BinaryReaderEOFException
unpacked
=
np
.
zeros
(
size
)
for
k
in
range
(
size
):
i
=
k
*
typeSize
unpacked
[
k
]
=
struct
.
unpack
(
typeFormat
,
value
[
i
:
i
+
typeSize
])[
0
]
return
unpacked
def
seek
(
self
,
offset
,
refPos
=
0
):
'''
offset in bytes and refPos gives reference position, where 0
means origin of the file, 1 uses current position and 2 uses
the end of the file.
'''
self
.
file
.
seek
(
offset
,
refPos
)
def
__del__
(
self
):
self
.
file
.
close
()
# TODO: Add options for reading virgo maps, and .xyz zygo
# maps (need .xys file for this). Binary ligo-maps?
# The intensity data is not used to anything here. Remove
# or add to pykat?
...
...
@@ -1870,5 +2030,3 @@ def read_map(filename, mapFormat='finesse', scaling=1.0e-9):
# [map3,x_tilt,y_tilt,offset2]=FT_remove_piston_from_mirror_map(map2,w, display_style);
# map3=FT_invert_mirror_map(map3, invert);
# Understand the internal coordinate system of the
# maps/matrices.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment