Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .codespellrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[codespell]
# Ref: https://github.com/codespell-project/codespell#using-a-config-file
skip = .git,.git-meta,.gitignore,.gitattributes,*.pdf,*.svg,*.css,.codespellrc,*/jsPsych/*
check-hidden = true
ignore-regex = ^\s*"image/\S+": ".*
# ignore-words-list =
23 changes: 23 additions & 0 deletions .github/workflows/codespell.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Codespell configuration is within .codespellrc
---
name: Codespell

on:
push:
branches: [master]
pull_request:
branches: [master]

permissions:
contents: read

jobs:
codespell:
name: Check for spelling errors
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4
- name: Codespell
uses: codespell-project/actions-codespell@8f01853be192eb0f849a5c7d721450e7a467c579 # v2.2
2 changes: 1 addition & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ There you can find full example projects, demos of Psychopy integration, and emp

**Overview of RT-Cloud Components**
![](docs/rtcloud_schematic.png )<br>
- **data_streamer** (runs on machine that recieves/sends DICOMs)
- **data_streamer** (runs on machine that receives/sends DICOMs)
- Watches for new DICOM brain images and sends them to whatever machine is analysing the data
- Can simulate the transfer of DICOMs from the MRI scanner using a precollected folder of DICOMs or via an OpenNeuro dataset (OpenNeuroService)
- **data_analyser** (runs on machine that analyses data in real-time)
Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile.rttools
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ echo 'export FSLDIR PATH' >> ~/.bashrc && \
echo 'export LD_LIBRARY_PATH=${FSLDIR}/lib:${FSLDIR}/fslpython/lib:${LD_LIBRARY_PATH}' >> ~/.bashrc && \
echo "## FSL Install Complete ##" && \
# Remove bulk of FSL (including fsleyes!) leaving only binary analysis functions
echo "## Removing non-essential FSL utilites! ##" && \
echo "## Removing non-essential FSL utilities! ##" && \
source ~/.bashrc && \
cd $FSLDIR && \
yes | rm -r config data doc extras fslpython include lib python refdoc src tcl && \
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
# 2) AutoAPI uses code parsing instead of code imports, which means there's no
# need to install the full RT-Cloud conda environment (takes >10m on RTD).
autoapi_dirs = ['../rtCommon']
# autoapi_keep_files = True # Useful for debuggin warnings and errors
# autoapi_keep_files = True # Useful for debugging warnings and errors

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
Expand Down
8 changes: 4 additions & 4 deletions docs/for-developers.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ The experiment script doesn’t need to change anything to use the 3 ways of int
**Q:** I’m not sure i understand the difference between “ProjectServer with local services” and “ProjectServer with remote services”. (Especially because earlier in this document you say that if a module is running remotely then you call it a service — so i thought service means “remote”, but here you refer to local vs remote services)
- **A:** The projectServer and the experiment script always run on the same computer, this is baked into the code that the clientInterface is only allowed to make a localhost connection to the projectServer (for security reasons). So whether the dataInterface is running within the experiment script (case 1) or in the projectServer (case 2) it is still local to the computer that the experiment script is running on, so in that sense the data is local to the script.

**Q:** Even if I am just testing things out (using --test flag) by running two terminals on my local machine, one as projectServer + dataService, the other as subjectService, I still need to have a valid ssl cert? and I cant test out the exporting of text files with dequeueResult via the outputDir flag unless I am using a “remote” subjectservice right?
**Q:** Even if I am just testing things out (using --test flag) by running two terminals on my local machine, one as projectServer + dataService, the other as subjectService, I still need to have a valid ssl cert? and I can't test out the exporting of text files with dequeueResult via the outputDir flag unless I am using a “remote” subjectservice right?
- **A:** You don’t need an ssl cert with --test flag, but you must specify --test for each process you start (the subjectInterface as well as projectServer).
Yes, you need a remote subjectService to test the writing of text files.

Expand All @@ -107,10 +107,10 @@ Yes, you need a remote subjectService to test the writing of text files.


**Q:** What’s the difference between initWatch and initScannerStream?
- **A:** initWatch and initScannerStream both accomplish the same thing. We originally had the initWatch/watchFile interface. Then we added a more “streaming” interface with BIDS and the initScannerStream/getImageData is that. So the BIDS interface uses initScannerStream internally, but it can also be used for a Dicom stream. I would say use the initScrannerStream interface and consider the initWatch as deprecated (or for backward compatibility).
- **A:** initWatch and initScannerStream both accomplish the same thing. We originally had the initWatch/watchFile interface. Then we added a more “streaming” interface with BIDS and the initScannerStream/getImageData is that. So the BIDS interface uses initScannerStream internally, but it can also be used for a Dicom stream. I would say use the initScannerStream interface and consider the initWatch as deprecated (or for backward compatibility).

**Q:** Can I have the experiment script execute different code dependent on a subject’s button press? if so how would i let the experiment script have access to that information of what/if the subject pressed a button?
- **A:** There is some support for getResponses, and I made an example in the jsPsych feedback. For PsychoPy the subject responses would need to be queued and returned whenever the experiment script calls getResponse or getAllReponses. So the stubs are there, it just needs to be filled out some.
- **A:** There is some support for getResponses, and I made an example in the jsPsych feedback. For PsychoPy the subject responses would need to be queued and returned whenever the experiment script calls getResponse or getAllResponses. So the stubs are there, it just needs to be filled out some.

**Q:** How can I can test the VNC Viewer locally? Can I run the DISPLAY=:1 code in the experiment script file?
- **A:** You can install tigervnc and the websocket conda environment. See instructions [here](https://rt-cloud.readthedocs.io/en/latest/how-to-run.html?highlight=vnc#install-vnc-server-on-the-projectserver-computer).
Expand All @@ -119,5 +119,5 @@ The scripts/run-vnc.sh will then start the vnc server and create a websockify wr
Other Notes from discussion:
- How can I change the experiment script based on button presses? Answer: currently only implemented in javascript version of subjectinterface via getAllResponses(); not implemented in python subjectinterface yet; probably not good idea to go from control room machine to cloud directly.
- we also talked about some vnc viewer specifics — needs its own installation, new conda environment, etc
- also talked about how you cant easily view analyzed data on the control room machine (going from cloud back to the control room to bypass using VNC viewer), or you can depending on your MRI Center’s setup but we want rtcloud to be workable regardless of the setup
- also talked about how you can't easily view analyzed data on the control room machine (going from cloud back to the control room to bypass using VNC viewer), or you can depending on your MRI Center’s setup but we want rtcloud to be workable regardless of the setup
you can potentially bypass VNC Viewer by encoding the image you want to look at into a dictionary and sending that through to the presentation laptop, but at that point its probably not worth it compared to the initial setup cost of doing VNC viewer route
2 changes: 1 addition & 1 deletion docs/subject-feedback.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ The source code components of jsPsych live in the `web/` directory. File `web/js

2. Connect a web browser to the main page
- http://localhost:8888/
- Enter 'test' for both the usnername and password since we are running it in unsecure test mode.
- Enter 'test' for both the username and password since we are running it in insecure test mode.

3. Connect a web browser to the jsPsych feedback page
- http://localhost:8888/jspsych
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/bids_tutorial.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@
"events = archive.getEvents(subject='01', \n",
" task='languageproduction', run=1)\n",
"\n",
"# All event files can be retrieved when specifiying no entities\n",
"# All event files can be retrieved when specifying no entities\n",
"events = archive.getEvents()\n",
"\n",
"# Event files are returned as BIDSDataFile objects\n",
Expand Down
2 changes: 1 addition & 1 deletion docs/using-bids-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ https://bids-specification.readthedocs.io/en/stable/, a few key details are as
follows:

1. **Brain imaging data is stored in the Neuroimaging Informatics
Technology Initative (NIfTI) format.** NIfTI is a binary file format
Technology Initiative (NIfTI) format.** NIfTI is a binary file format
that starts with a header holding basic information about the brain
data contained in the file. The header is followed by the raw brain
data. A NIfTI volume's data typically has 4 dimensions, *x, y, z*
Expand Down
2 changes: 1 addition & 1 deletion environment-synthetic-data.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ channels:
- defaults
- conda-forge
dependencies:
- brainiak::brainiak # specifing the channel
- brainiak::brainiak # specifying the channel
- nomkl
- scikit-learn
6 changes: 3 additions & 3 deletions projects/dicomBidsStream/dicomBidsStream.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

Finally, this script is called from the projectInterface which has a web interface
and accepts commands to 'start' or 'stop' a run. When the 'start' button is
pressed it will run this scirpt passing in whatever conifgurations have been
pressed it will run this script passing in whatever configurations have been
set in the web page as a configuration file. Note that projectInterface is
started from the script 'run-projectInterface.sh'.

Expand Down Expand Up @@ -141,7 +141,7 @@ def doRuns(cfg, clientInterfaces):
accidentally grab a dicom before it's fully acquired)
"""
if verbose:
print("• initalize a watch for the dicoms using 'initWatch'")
print("• initialize a watch for the dicoms using 'initWatch'")
entities = {'subject': cfg.subjectName, 'task': 'test', 'run': runNum}
streamId = bidsInterface.initDicomBidsStream(cfg.dicomDir, dicomScanNamePattern,
cfg.minExpectedDicomSize, **entities)
Expand Down Expand Up @@ -286,7 +286,7 @@ def main(argv=None):
argParser.add_argument('--scans', '-s', default=None, type=str,
help='Comma separated list of scan number')
argParser.add_argument('--yesToPrompts', '-y', default=False, action='store_true',
help='automatically answer tyes to any prompts')
help='automatically answer yes to any prompts')

# Some additional parameters only used for this sample project
argParser.add_argument('--noVerbose', '-nv', default=False, action='store_true',
Expand Down
2 changes: 1 addition & 1 deletion projects/openNeuroClient/openNeuroClient.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def main(argv=None):
argParser.add_argument('--runs', '-r', default=None, type=str,
help='Comma separated list of run numbers')
argParser.add_argument('--yesToPrompts', '-y', default=False, action='store_true',
help='automatically answer tyes to any prompts')
help='automatically answer yes to any prompts')
argParser.add_argument('--archive', '-a', default=False, action='store_true',
help='Create a Bids Archive from the incoming Bids Incrementals.')
args = argParser.parse_args(argv)
Expand Down
2 changes: 1 addition & 1 deletion projects/sample/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,6 @@ All of the functions we use within the real-time fMRI cloud framework live in th
- **`fileClient` script**
- The functions enable you to interact with files, from starting a lookout (or watch) for a specific type of file to displaying all of the allowed file types.
- **`projectUtils` script**
- The functions here allow you to interface between the cloud and the consol computer. For instance, if you want to download files from the cloud there's a function to help you do that here!
- The functions here allow you to interface between the cloud and the console computer. For instance, if you want to download files from the cloud there's a function to help you do that here!
- **`imageHandling` script**
- The purpose of these functions is to help you (1) transfer dicom files back and forth from the cloud and (2) convert the dicom files to nifti files, which is a file format that is better for data analyses.
2 changes: 1 addition & 1 deletion projects/sample/finalize.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
initialize.py (Last Updated: 01/26/2021)

The purpose of this script is to finalize the rt-cloud session. Specifically,
here we want to dowload any important files from the cloud back to the stimulus
here we want to download any important files from the cloud back to the stimulus
computer and maybe even delete files from the cloud that we don't want to
stay there (maybe for privacy purposes).

Expand Down
6 changes: 3 additions & 3 deletions projects/sample/initialize.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"-----------------------------------------------------------------------------\n"
"The purpose of this script is to show you the ways in which you can utilize\n"
"an initialization function. You will notice some comments printed on the\n"
"html browser, but if you want more details please look at initalize.py.\n"
"html browser, but if you want more details please look at initialize.py.\n"
"-----------------------------------------------------------------------------")

import os
Expand Down Expand Up @@ -141,9 +141,9 @@ def main(argv=None):

if __name__ == "__main__":
"""
If 'initalize.py' is invoked as a program, then actually go through all of the
If 'initialize.py' is invoked as a program, then actually go through all of the
portions of this script. This statement is not satisfied if functions are called
from another script using "from initalize.py import FUNCTION"
from another script using "from initialize.py import FUNCTION"
"""
main()
sys.exit(0)
8 changes: 4 additions & 4 deletions projects/sample/sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

Finally, this script is called from the projectInterface which has a web interface
and accepts commands to 'start' or 'stop' a run. When the 'start' button is
pressed it will run this scirpt passing in whatever conifgurations have been
pressed it will run this script passing in whatever configurations have been
set in the web page as a configuration file. Note that projectInterface is
started from the script 'run-projectInterface.sh'.

Expand Down Expand Up @@ -82,7 +82,7 @@ def doRuns(cfg, dataInterface, subjInterface, webInterface):

INPUT:
[1] cfg - configuration file with important variables)
[2] dataInterface - this will allow this script runnin in the cloud to access
[2] dataInterface - this will allow this script running in the cloud to access
files from the stimulus computer, which receives dicom files directly
from the MRI Scanner console
[3] subjInterface - this allows sending feedback (e.g. classification results)
Expand Down Expand Up @@ -165,7 +165,7 @@ def doRuns(cfg, dataInterface, subjInterface, webInterface):
accidentally grab a dicom before it's fully acquired)
"""
if verbose:
print("• initalize a watch for the dicoms using 'initWatch'")
print("• initialize a watch for the dicoms using 'initWatch'")
dataInterface.initWatch(cfg.dicomDir, dicomScanNamePattern,
cfg.minExpectedDicomSize, demoStep=demoTimeDelay)

Expand Down Expand Up @@ -408,7 +408,7 @@ def main(argv=None):
argParser.add_argument('--scans', '-s', default=None, type=str,
help='Comma separated list of scan number')
argParser.add_argument('--yesToPrompts', '-y', default=False, action='store_true',
help='automatically answer tyes to any prompts')
help='automatically answer yes to any prompts')

# Some additional parameters only used for this sample project
argParser.add_argument('--useInitWatch', '-w', default=False, action='store_true',
Expand Down
2 changes: 1 addition & 1 deletion rtCommon/bidsArchive.py
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,7 @@ def appendBidsRun(self, run: BidsRun) -> None:
Append a BIDS Run to this archive.

Args:
run: Run to append to the archvie.
run: Run to append to the archive.

Examples:
>>> archive1 = BidsArchive('/tmp/dataset1')
Expand Down
4 changes: 2 additions & 2 deletions rtCommon/bidsCommon.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"Authors": ["The RT-Cloud Authors",
"The Dataset Author"]}

# Deafult readme text for RT-Cloud
# Default readme text for RT-Cloud
DEFAULT_README = "Generated BIDS-Incremental Dataset from RT-Cloud"

# Required columns for the BIDS events files
Expand Down Expand Up @@ -81,7 +81,7 @@ class BidsFileExtension(Enum):
EVENTS = '.tsv'


# BIDS Entitiy information dict
# BIDS Entity information dict
class BidsEntityKeys(Enum):
ENTITY = "entity"
FORMAT = "format"
Expand Down
4 changes: 2 additions & 2 deletions rtCommon/bidsIncremental.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ def __setstate__(self, state):

def _preprocessMetadata(self, imageMetadata: dict) -> dict:
"""
Pre-process metadata to extract any additonal metadata that might be
Pre-process metadata to extract any additional metadata that might be
embedded in the provided metadata, like ProtocolName, and ensure that
certain metadata values (e.g., RepetitionTime) are within
BIDS-specified ranges.
Expand Down Expand Up @@ -496,7 +496,7 @@ def getImageData(self) -> np.ndarray:
BEGIN BIDS-I ARCHIVE EMULTATION API

A BIDS-I is meant to emulate a valid BIDS archive. Thus, an API is included
that enables generating paths and filenames that would corresopnd to this
that enables generating paths and filenames that would correspond to this
BIDS-I's data if it were actually in an on-disk archive.

"""
Expand Down
6 changes: 3 additions & 3 deletions rtCommon/bidsInterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def __init__(self, dataRemote=False, allowedDirs=[], scannerClockSkew=0):
def initDicomBidsStream(self, dicomDir, dicomFilePattern, dicomMinSize,
anonymize=True, **entities) -> int:
"""
Intialize a data stream that watches a directory for DICOM files to be written that
Initialize a data stream that watches a directory for DICOM files to be written that
match the given file pattern. When a DICOM is written it will be converted to a BIDS
incremental and returned.

Expand Down Expand Up @@ -176,7 +176,7 @@ def getClockSkew(self, callerClockTime: float, roundTripTime: float) -> float:
# Adjust the caller's clock forward by 1/2 round trip time
callerClockAdjToNow = callerClockTime + roundTripTime / 2.0
now = time.time()
# calcluate the time this server's clock is ahead of the caller's clock
# calculate the time this server's clock is ahead of the caller's clock
skew = now - callerClockAdjToNow
# add the time skew from this server to the scanner clock
totalSkew = skew + self.scannerClockSkew
Expand All @@ -201,7 +201,7 @@ def __init__(self, allowedDirs=[]):
def initStream(self, dicomDir, dicomFilePattern, dicomMinSize,
anonymize=True, **entities):
"""
Intialize a new DicomToBids stream, watches for Dicoms and streams as BIDS
Initialize a new DicomToBids stream, watches for Dicoms and streams as BIDS

Args:
dicomDir: The directory where the scanner will write new DICOM files
Expand Down
Loading
Loading