Skip to content

Commit

Permalink
Merge pull request #1044 from wright-group/from_solis-metadata
Browse files Browse the repository at this point in the history
from_Solis - handle missing metadata on import
  • Loading branch information
kameyer226 committed Jan 13, 2022
2 parents 820b0b7 + c84b170 commit 69d6703
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).

## [Unreleased]

## Fixed
- `data.from_Solis`: import works without metadata


## [3.4.3]

### Added
Expand Down
53 changes: 45 additions & 8 deletions WrightTools/data/_solis.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import os
import pathlib
import time
import warnings

import numpy as np

Expand Down Expand Up @@ -43,8 +44,20 @@ def from_Solis(filepath, name=None, parent=None, verbose=True) -> Data:
Returns
-------
data
data : WrightTools.Data
New data object.
Channels: `signal`. If exposure time is in metadata, signal is given as a count rate (Hz).
Variables, Axes: `yindex` and `xindex` (no grating) or `wm` (grating)
Notes
-----
When exporting as ascii, including metadata is optional.
It is _strongly recommended_ that you include metadata in exports.
Metadata informs the image creation date, exposure time, and axes.
However, if metadata is not present, this importer will make its best guesses to populate these fields accurately.
Saving processed data (e.g. vertically-binned data) in Solis software can remove/omit important metadata, so we advise exporting the raw camera images.
"""
# parse filepath
filestr = os.fspath(filepath)
Expand Down Expand Up @@ -102,9 +115,17 @@ def get_frames(f, arr, axis0):
attrs[key.strip()] = val.strip()

f.close()
created = attrs["Date and Time"] # is this UTC?
created = time.strptime(created, "%a %b %d %H:%M:%S %Y")
created = timestamp.TimeStamp(time.mktime(created)).RFC3339

try:
created = attrs["Date and Time"] # is this UTC?
created = time.strptime(created, "%a %b %d %H:%M:%S %Y")
created = timestamp.TimeStamp(time.mktime(created)).RFC3339
except KeyError: # use file creation time
created = os.stat(filepath).st_mtime
created = timestamp.TimeStamp(created).RFC3339
warnings.warn(
f"{filepath.name} has no 'Date and Time' field: using file modified time instead: {created}"
)

kwargs = {"name": name, "kind": "Solis", "source": filestr, "created": created}
if parent is None:
Expand All @@ -113,7 +134,15 @@ def get_frames(f, arr, axis0):
data = parent.create_data(**kwargs)

axis0 = np.array(axis0)
if float(attrs["Grating Groove Density (l/mm)"]) == 0:
try:
groove_density = float(attrs["Grating Groove Density (l/mm)"])
except KeyError: # assume no grating
warnings.warn(
f"{filepath.name} has no 'Grating Groove Density (1/mm)' field: guessing x axis units."
)
groove_density = isinstance(axis0[0], float)

if groove_density == 0:
xname = "xindex"
xunits = None
else:
Expand All @@ -135,9 +164,17 @@ def get_frames(f, arr, axis0):
axes = ["frame"] + axes

data.transform(*axes)
arr /= float(attrs["Exposure Time (secs)"])
# signal has units of Hz because time normalized
data.create_channel(name="signal", values=arr, signed=False, units="Hz")
try:
exposure_time = float(attrs["Exposure Time (secs)"])
if exposure_time == 0:
raise ZeroDivisionError
arr /= exposure_time
except (KeyError, ZeroDivisionError) as e: # do not normalize
warnings.warn(f"{filepath.name} camera signal cannot be given as a count rate.")
data.create_channel(name="signal", values=arr, signed=False)
else:
# signal has units of Hz because time normalized
data.create_channel(name="signal", values=arr, signed=False, units="Hz")

for key, val in attrs.items():
data.attrs[key] = val
Expand Down

0 comments on commit 69d6703

Please sign in to comment.