Skip to content

Commit 4ae0886

Browse files
author
Thinh Nguyen
committed
Merge remote-tracking branch 'upstream/main'
2 parents a77a9f3 + 548e4fd commit 4ae0886

File tree

7 files changed

+104
-72
lines changed

7 files changed

+104
-72
lines changed

.github/workflows/u24_element_release_call.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ jobs:
1717
secrets:
1818
TWINE_USERNAME: ${{secrets.TWINE_TEST_USERNAME}}
1919
TWINE_PASSWORD: ${{secrets.TWINE_TEST_PASSWORD}}
20-
GOOGLE_ANALYTICS_KEY: ${{secrets.GOOGLE_ANALYTICS_KEY}}
2120
call_u24_elements_release_alpine:
2221
if: >-
2322
github.event.workflow_run.conclusion == 'success' && github.repository_owner == 'datajoint' && !contains(github.event.workflow_run.head_branch, 'test')
@@ -27,4 +26,3 @@ jobs:
2726
secrets:
2827
TWINE_USERNAME: ${{secrets.TWINE_USERNAME}}
2928
TWINE_PASSWORD: ${{secrets.TWINE_PASSWORD}}
30-
GOOGLE_ANALYTICS_KEY: ${{secrets.GOOGLE_ANALYTICS_KEY}}

CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,26 @@
33
Observes [Semantic Versioning](https://semver.org/spec/v2.0.0.html) standard and
44
[Keep a Changelog](https://keepachangelog.com/en/1.0.0/) convention.
55

6+
## [0.6.0] - 2023-07-26
7+
8+
+ Update - `prairieviewreader.py` -> `prairie_view_loader.py`
9+
+ Update - `get_pv_metadata()` -> `get_prairieview_metadata()`
10+
+ Update - Internal variable names within `prairie_view_loader.py`
11+
12+
## [0.5.4] - 2023-05-25
13+
14+
+ Fix - DANDI URL for uploads where `staging=False`.
15+
+ Fix - Docs to remove Google Analytics Key and add Markdown extensions
16+
17+
## [0.5.3] - 2023-05-11
18+
19+
+ Fix - `.ipynb` dark mode output for all notebooks.
20+
+ Fix - Remove `GOOGLE_ANALYTICS_KEY` from `u24_element_release_call.yml`.
21+
22+
## [0.5.2] - 2023-04-28
23+
24+
+ Fix - `.ipynb` output in tutorials is not visible in dark mode.
25+
626
## [0.5.1] - 2023-03-15
727

828
+ Fix - ingestion routine for multiple Z devices in `prairieviewreader.py`.
@@ -57,6 +77,10 @@ Observes [Semantic Versioning](https://semver.org/spec/v2.0.0.html) standard and
5777

5878
+ Add - Readers for: `ScanImage`, `Suite2p`, `CaImAn`.
5979

80+
[0.6.0]: https://github.com/datajoint/element-interface/releases/tag/0.6.0
81+
[0.5.4]: https://github.com/datajoint/element-interface/releases/tag/0.5.4
82+
[0.5.3]: https://github.com/datajoint/element-interface/releases/tag/0.5.3
83+
[0.5.2]: https://github.com/datajoint/element-interface/releases/tag/0.5.2
6084
[0.5.1]: https://github.com/datajoint/element-interface/releases/tag/0.5.1
6185
[0.5.0]: https://github.com/datajoint/element-interface/releases/tag/0.5.0
6286
[0.4.2]: https://github.com/datajoint/element-interface/releases/tag/0.4.2

docs/.docker/pip_requirements.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ mdx-truly-sane-lists
77
mkdocs-gen-files
88
mkdocs-literate-nav
99
mkdocs-exclude-search
10-
mkdocs-markdownextradata-plugin
10+
mkdocs-markdownextradata-plugin
11+
mkdocs-jupyter
12+
mkdocs-section-index

docs/mkdocs.yaml

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,14 @@ nav:
4242
# UPSTREAM_REPO=https://github.com/datajoint/element-{ELEMENT}.git \
4343
# HOST_UID=$(id -u) docker compose -f docs/docker-compose.yaml up --build
4444
# ```
45-
# 02. Site analytics depend on a local environment variable GOOGLE_ANALYTICS_KEY
46-
# You can find this in LastPass or declare with any string to suppress errors
47-
# 03. The API section will pull docstrings.
45+
# 02. The API section will pull docstrings.
4846
# A. Follow google styleguide e.g.,
4947
# https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html
5048
# With typing suggestions: https://docs.python.org/3/library/typing.html
5149
# B. To pull a specific workflow fork, change ./docs/src/api/make_pages.py#L19
52-
# 04. To see your fork of the workflow-{element} in this render, change the
50+
# 03. To see your fork of the workflow-{element} in this render, change the
5351
# URL in ./docs/src/api/make_pages.py#L19 to your fork.
54-
# 05. For redirecting options For redirect options, see 'redirects' below.
55-
# 06. To deploy this site on your fork,
52+
# 04. To deploy this site on your fork,
5653
# A. declare a branch called gh-pages
5754
# B. go to the your fork > settings > pages
5855
# C. direct pages to render from the gh-pages branch at root
@@ -87,9 +84,6 @@ theme:
8784
plugins:
8885
- markdownextradata: {}
8986
- search
90-
# - redirects: # OPTIONAL REDIRECTS
91-
# redirect_maps:
92-
# "index.md": "getting_started.md"
9387
- mkdocstrings:
9488
default_handler: python
9589
- gen-files:
@@ -120,13 +114,12 @@ markdown_extensions:
120114
linenums: true
121115
- pymdownx.inlinehilite
122116
- pymdownx.snippets
123-
117+
- pymdownx.magiclink # Displays bare URLs as links
118+
- pymdownx.tasklist: # Renders check boxes in tasks lists
119+
custom_checkbox: true
124120
extra:
125121
PATCH_VERSION: !ENV PATCH_VERSION
126122
generator: false # Disable watermark
127-
analytics:
128-
provider: google
129-
property: !ENV GOOGLE_ANALYTICS_KEY
130123
version:
131124
provider: mike
132125
social:

docs/src/.overrides/assets/stylesheets/extra.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,8 @@ html a[title="YouTube"].md-social__link svg {
9191
/* previous/next text */
9292
/* --md-footer-fg-color: var(--dj-white); */
9393
}
94+
95+
[data-md-color-scheme="slate"] td,
96+
th {
97+
color: var(--dj-black)
98+
}

element_interface/prairieviewreader.py renamed to element_interface/prairie_view_loader.py

Lines changed: 65 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5,107 +5,110 @@
55
import numpy as np
66

77

8-
def get_pv_metadata(pvtiffile: str) -> dict:
9-
"""Extract metadata for scans generated by PrairieView acquisition software.
8+
def get_prairieview_metadata(ome_tif_filepath: str) -> dict:
9+
"""Extract metadata for scans generated by Prairie View acquisition software.
1010
11-
The PrairieView software generates one .ome.tif imaging file per frame acquired. The
12-
metadata for all frames is contained one .xml file. This function locates the .xml
13-
file and generates a dictionary necessary to populate the DataJoint ScanInfo and
14-
Field tables. PrairieView works with resonance scanners with a single field.
15-
PrairieView does not support bidirectional x and y scanning. ROI information is not
16-
contained in the .xml file. All images generated using PrairieView have square
17-
dimensions(e.g. 512x512).
11+
The Prairie View software generates one `.ome.tif` imaging file per frame
12+
acquired. The metadata for all frames is contained in one .xml file. This
13+
function locates the .xml file and generates a dictionary necessary to
14+
populate the DataJoint `ScanInfo` and `Field` tables. Prairie View works
15+
with resonance scanners with a single field. Prairie View does not support
16+
bidirectional x and y scanning. ROI information is not contained in the
17+
`.xml` file. All images generated using Prairie View have square dimensions(e.g. 512x512).
1818
1919
Args:
20-
pvtiffile: An absolute path to the .ome.tif image file.
20+
ome_tif_filepath: An absolute path to the .ome.tif image file.
2121
2222
Raises:
2323
FileNotFoundError: No .xml file containing information about the acquired scan
24-
was found at path in parent directory at `pvtiffile`.
24+
was found at path in parent directory at `ome_tif_filepath`.
2525
2626
Returns:
2727
metainfo: A dict mapping keys to corresponding metadata values fetched from the
2828
.xml file.
2929
"""
3030

3131
# May return multiple xml files. Only need one that contains scan metadata.
32-
xml_files = pathlib.Path(pvtiffile).parent.glob("*.xml")
32+
xml_files_list = pathlib.Path(ome_tif_filepath).parent.glob("*.xml")
3333

34-
for xml_file in xml_files:
35-
tree = ET.parse(xml_file)
36-
root = tree.getroot()
37-
if root.find(".//Sequence"):
34+
for file in xml_files_list:
35+
xml_tree = ET.parse(file)
36+
xml_file = xml_tree.getroot()
37+
if xml_file.find(".//Sequence"):
3838
break
3939
else:
4040
raise FileNotFoundError(
41-
f"No PrarieView metadata XML file found at {pvtiffile.parent}"
41+
f"No PrarieView metadata .xml file found at {pathlib.Path(ome_tif_filepath).parent}"
4242
)
4343

4444
bidirectional_scan = False # Does not support bidirectional
4545
roi = 0
4646
n_fields = 1 # Always contains 1 field
47-
record_start_time = root.find(".//Sequence/[@cycle='1']").attrib.get("time")
47+
recording_start_time = xml_file.find(".//Sequence/[@cycle='1']").attrib.get("time")
4848

4949
# Get all channels and find unique values
5050
channel_list = [
5151
int(channel.attrib.get("channel"))
52-
for channel in root.iterfind(".//Sequence/Frame/File/[@channel]")
52+
for channel in xml_file.iterfind(".//Sequence/Frame/File/[@channel]")
5353
]
5454
n_channels = len(set(channel_list))
55-
n_frames = len(root.findall(".//Sequence/Frame"))
55+
n_frames = len(xml_file.findall(".//Sequence/Frame"))
5656
framerate = 1 / float(
57-
root.findall('.//PVStateValue/[@key="framePeriod"]')[0].attrib.get("value")
57+
xml_file.findall('.//PVStateValue/[@key="framePeriod"]')[0].attrib.get("value")
5858
) # rate = 1/framePeriod
5959

6060
usec_per_line = (
6161
float(
62-
root.findall(".//PVStateValue/[@key='scanLinePeriod']")[0].attrib.get(
62+
xml_file.findall(".//PVStateValue/[@key='scanLinePeriod']")[0].attrib.get(
6363
"value"
6464
)
6565
)
6666
* 1e6
6767
) # Convert from seconds to microseconds
6868

69-
scan_datetime = datetime.strptime(root.attrib.get("date"), "%m/%d/%Y %I:%M:%S %p")
69+
scan_datetime = datetime.strptime(
70+
xml_file.attrib.get("date"), "%m/%d/%Y %I:%M:%S %p"
71+
)
7072

71-
total_duration = float(
72-
root.findall(".//Sequence/Frame")[-1].attrib.get("relativeTime")
73+
total_scan_duration = float(
74+
xml_file.findall(".//Sequence/Frame")[-1].attrib.get("relativeTime")
7375
)
7476

75-
px_height = int(
76-
root.findall(".//PVStateValue/[@key='pixelsPerLine']")[0].attrib.get("value")
77+
pixel_height = int(
78+
xml_file.findall(".//PVStateValue/[@key='pixelsPerLine']")[0].attrib.get(
79+
"value"
80+
)
7781
)
7882
# All PrairieView-acquired images have square dimensions (512 x 512; 1024 x 1024)
79-
px_width = px_height
83+
pixel_width = pixel_height
8084

8185
um_per_pixel = float(
82-
root.find(
86+
xml_file.find(
8387
".//PVStateValue/[@key='micronsPerPixel']/IndexedValue/[@index='XAxis']"
8488
).attrib.get("value")
8589
)
8690

87-
um_height = um_width = float(px_height) * um_per_pixel
91+
um_height = um_width = float(pixel_height) * um_per_pixel
8892

8993
# x and y coordinate values for the center of the field
9094
x_field = float(
91-
root.find(
95+
xml_file.find(
9296
".//PVStateValue/[@key='currentScanCenter']/IndexedValue/[@index='XAxis']"
9397
).attrib.get("value")
9498
)
9599
y_field = float(
96-
root.find(
100+
xml_file.find(
97101
".//PVStateValue/[@key='currentScanCenter']/IndexedValue/[@index='YAxis']"
98102
).attrib.get("value")
99103
)
100104
if (
101-
root.find(
105+
xml_file.find(
102106
".//Sequence/[@cycle='1']/Frame/PVStateShard/PVStateValue/[@key='positionCurrent']/SubindexedValues/[@index='ZAxis']"
103107
)
104108
is None
105109
):
106-
107110
z_fields = np.float64(
108-
root.find(
111+
xml_file.find(
109112
".//PVStateValue/[@key='positionCurrent']/SubindexedValues/[@index='ZAxis']/SubindexedValue"
110113
).attrib.get("value")
111114
)
@@ -114,46 +117,53 @@ def get_pv_metadata(pvtiffile: str) -> dict:
114117
bidirection_z = False
115118

116119
else:
120+
bidirection_z = (
121+
xml_file.find(".//Sequence").attrib.get("bidirectionalZ") == "True"
122+
)
117123

118-
bidirection_z = root.find(".//Sequence").attrib.get("bidirectionalZ") == "True"
119-
120-
# One "Frame" per depth. Gets number of frames in first sequence
124+
# One "Frame" per depth in the .xml file. Gets number of frames in first sequence
121125
planes = [
122126
int(plane.attrib.get("index"))
123-
for plane in root.findall(".//Sequence/[@cycle='1']/Frame")
127+
for plane in xml_file.findall(".//Sequence/[@cycle='1']/Frame")
124128
]
125129
n_depths = len(set(planes))
126130

127-
z_controllers = root.findall(
131+
z_controllers = xml_file.findall(
128132
".//Sequence/[@cycle='1']/Frame/[@index='1']/PVStateShard/PVStateValue/[@key='positionCurrent']/SubindexedValues/[@index='ZAxis']/SubindexedValue"
129133
)
130-
if len(z_controllers) > 1:
131134

135+
# If more than one Z-axis controllers are found,
136+
# check which controller is changing z_field depth. Only 1 controller
137+
# must change depths.
138+
if len(z_controllers) > 1:
132139
z_repeats = []
133-
for controller in root.findall(
134-
".//Sequence/[@cycle='1']/Frame/[@index='1']/PVStateShard/PVStateValue/[@key='positionCurrent']/SubindexedValues/[@index='ZAxis']/"):
140+
for controller in xml_file.findall(
141+
".//Sequence/[@cycle='1']/Frame/[@index='1']/PVStateShard/PVStateValue/[@key='positionCurrent']/SubindexedValues/[@index='ZAxis']/"
142+
):
135143
z_repeats.append(
136144
[
137145
float(z.attrib.get("value"))
138-
for z in root.findall(
146+
for z in xml_file.findall(
139147
".//Sequence/[@cycle='1']/Frame/PVStateShard/PVStateValue/[@key='positionCurrent']/SubindexedValues/[@index='ZAxis']/SubindexedValue/[@subindex='{0}']".format(
140148
controller.attrib.get("subindex")
141149
)
142150
)
143151
]
144152
)
145-
146-
147-
controller_assert = [not all(z == z_controller[0] for z in z_controller) for z_controller in z_repeats]
148-
149-
assert sum(controller_assert)==1, "Multiple controllers changing z depth is not supported"
153+
controller_assert = [
154+
not all(z == z_controller[0] for z in z_controller)
155+
for z_controller in z_repeats
156+
]
157+
assert (
158+
sum(controller_assert) == 1
159+
), "Multiple controllers changing z depth is not supported"
150160

151161
z_fields = z_repeats[controller_assert.index(True)]
152-
162+
153163
else:
154164
z_fields = [
155165
z.attrib.get("value")
156-
for z in root.findall(
166+
for z in xml_file.findall(
157167
".//Sequence/[@cycle='1']/Frame/PVStateShard/PVStateValue/[@key='positionCurrent']/SubindexedValues/[@index='ZAxis']/SubindexedValue/[@subindex='0']"
158168
)
159169
]
@@ -176,15 +186,15 @@ def get_pv_metadata(pvtiffile: str) -> dict:
176186
bidirectional_z=bidirection_z,
177187
scan_datetime=scan_datetime,
178188
usecs_per_line=usec_per_line,
179-
scan_duration=total_duration,
180-
height_in_pixels=px_height,
181-
width_in_pixels=px_width,
189+
scan_duration=total_scan_duration,
190+
height_in_pixels=pixel_height,
191+
width_in_pixels=pixel_width,
182192
height_in_um=um_height,
183193
width_in_um=um_width,
184194
fieldX=x_field,
185195
fieldY=y_field,
186196
fieldZ=z_fields,
187-
recording_time=record_start_time,
197+
recording_time=recording_start_time,
188198
)
189199

190200
return metainfo

element_interface/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""Package metadata"""
22

3-
__version__ = "0.5.1"
3+
__version__ = "0.6.0"

0 commit comments

Comments
 (0)