Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
f7d1cf0
Pixi 159 (#26)
mohana-xw Jun 3, 2025
5cb8c72
PIXI-163, PIXI-183 completing a full implementation of Biodistributio…
ian-xnatworks Jun 4, 2025
9b7f349
PIXI-165: CMO Template Generator
mohana-xw Jun 4, 2025
5d13c58
PIXI-165: CMO Submission improvement
mohana-xw Jun 13, 2025
5ac5b0b
Making biod upload only available to owner level permissions. (#29)
ian-xnatworks Jun 13, 2025
4367dee
PIXI-197: Hardcoded scan type to BLI
mohana-xw Jun 13, 2025
9ed6cf3
PIXI-165: Improved experiment lookup
mohana-xw Jun 13, 2025
b663891
PIXI-197: FIxed modality
mohana-xw Jun 13, 2025
0b82380
PIXI-201 trimming cell values before reading on import.
ian-xnatworks Jun 13, 2025
e46eeaf
PIXI-198 fixing uploader description section.
ian-xnatworks Jun 13, 2025
27005c7
PIXI-204: Moved summary rendering to Statistics Dashboard plugin
mohana-xw Jun 13, 2025
c433c19
PIXI-199 Adding error checking for empty upload sheet.
ian-xnatworks Jun 13, 2025
289229e
Merge pull request #31 from preclinical-imaging/PIXI-165
mohana-xw Jun 13, 2025
91cc944
Setting Type to BLI
mohana-xw Jun 13, 2025
6168cbb
Merge pull request #30 from preclinical-imaging/PIXI-197
mohana-xw Jun 13, 2025
c324ec5
Merge pull request #32 from preclinical-imaging/PIXI-204
mohana-xw Jun 13, 2025
1fe7127
PIXI-202 making dates which are right format but not functional clear…
ian-xnatworks Jun 13, 2025
0722043
Adding printout of available date times for the site to exception han…
ian-xnatworks Jun 13, 2025
bd1b3e3
PIXI-203 Fixing return message for overlapping data
ian-xnatworks Jun 13, 2025
8ac72ed
Merge pull request #33 from preclinical-imaging/Biod-importer-qa-changes
mohana-xw Jun 14, 2025
b4f9466
Updated changelog
mohana-xw Jun 14, 2025
3240068
Updated changelog: Fixed display
mohana-xw Jun 15, 2025
82cb464
PIXI-164: Fixed BioD report (#34)
mohana-xw Jun 15, 2025
a0f8f4d
Pixi 206 Adding parsing banner to biod importer (#35)
ian-xnatworks Jun 24, 2025
95f0105
Pixi 216, PIXI-208, PIXI-210 (#37)
mohana-xw Jul 9, 2025
da08f01
Pixi 217 (#39)
mohana-xw Jul 15, 2025
1af8008
PIXI-211 (#38)
mohana-xw Jul 15, 2025
f15b92b
XNAT-8099 (#40)
ian-xnatworks Aug 13, 2025
3c67dfb
PIXI-103: Change text of project Delete button
willhorton-xw Aug 18, 2025
9e35338
Add file
willhorton-xw Aug 18, 2025
1aebd80
Remove extraneous file
willhorton-xw Aug 18, 2025
9ad8406
Update button text for additional friendliness
willhorton-xw Aug 19, 2025
9599f90
PIXI-103 - Edit Project Delete Button Text
willhorton-xw Aug 19, 2025
1c2b84a
PIXI-217: Fixed typo in role name (#43)
mohana-xw Aug 26, 2025
6c80d2a
Pixi 223 - Adding documentation for the biodistribution upload proces…
ian-xnatworks Sep 13, 2025
8c877a3
PIXI-228 (#46)
mohana-xw Sep 19, 2025
fb8e8e9
Update installation docs to include Summary Stats
willhorton-xw Oct 7, 2025
855c8a0
Merge pull request #47 from preclinical-imaging/fixes/PIXI-224
willhorton-xw Oct 8, 2025
8c6f9bf
PIXI-219, PIXI-220, PIXI-221, PIXI-222, PIXI-183, PIXI-225, PIXI-226,…
ian-xnatworks Nov 25, 2025
5f43045
Pixi 1.5.0 release documentation (#48)
ian-xnatworks Dec 2, 2025
3c6204b
Removing CMO files to put that work on hold. (#49)
ian-xnatworks Dec 2, 2025
d39ef62
PIXI-234, PIXI-183, PIXI-220 Addressing QA comments for 1.5 release (…
ian-xnatworks Dec 4, 2025
70d801d
1.5 release notes (#51)
ian-xnatworks Dec 4, 2025
767a60b
Updating version.
ian-xnatworks Dec 4, 2025
6bd18a1
Update version to 1.5.0-SNAPSHOT for release prep
willhorton-xw Dec 5, 2025
bf60a01
Update version to 1.5.0-SNAPSHOT for release prep
willhorton-xw Dec 5, 2025
7464583
Update version to 1.5.0-RC-SNAPSHOT
willhorton-xw Dec 5, 2025
7f34ac7
Update version to 1.5.0 for release
willhorton-xw Jan 14, 2026
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
27 changes: 27 additions & 0 deletions CHANGELOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,33 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.5.0] - 2025-12-4

This release includes ability to:

- import BioDistribution datatype

- ability to generate Statistics Summary for the BioDistribution data [Statistics Dashboard Plugin](https://bitbucket.org/xnatx/statisticsdashboard_plugin)

- integration of Contrast Data implementation within PIXI which was added to core XNAT in version 1.9.3

- bug fixes relating to PDX and cell line datatypes


### Added
- [PIXI-159](https://radiologics.atlassian.net/browse/PIXI-159): Add a Biodistribution subject assessor
- [PIXI-163](https://radiologics.atlassian.net/browse/PIXI-163): Create importer for Biodistribution data from CSV input
- [PIXI-164](https://radiologics.atlassian.net/browse/PIXI-164): Create Biodistribution Report with Summary Statistics

### Fixed
- [PIXI-197](https://radiologics.atlassian.net/browse/PIXI-197): BLI Session and Scans do not contain the modality field
- [PIXI-215](https://radiologics.atlassian.net/browse/PIXI-215): Editing of PDX and removing passage number does not work via the Action -> Edit
- [PIXI-228](https://radiologics.atlassian.net/browse/PIXI-228): XFT cast error when saving cell line

### Changed
- [PIXI-204](https://radiologics.atlassian.net/browse/PIXI-204): Remove Statistics Dashboard files from Pixi Plugin. This is now located in the dedicated [Statistics Dashboard Plugin](https://bitbucket.org/xnatx/statisticsdashboard_plugin)
- [PIXI-217](https://radiologics.atlassian.net/browse/PIXI-217): Tumor data model should be handled by Data Manager Role rather than the site admin

## [1.4.0] - 2024-12-19

This release mainly addresses compatibility issues with XNAT 1.9. Prior releases may not work with XNAT 1.9.
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ This is the repository for the PIXI XNAT plugin. PIXI is designed to help manage

For detailed information, installation instructions, and usage guidelines, please visit [pixi.org](https://pixi.org).

This plugin depends on the statisticsdashboard_plugin from XNAT

## Build

To build the PIXI XNAT plugin, run the following command:
Expand Down
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ plugins {
}

group "org.nrg.xnatx.plugins"
version "1.4.0"
version "1.5.0"
description "PIXI Plugin for XNAT."

repositories {
Expand Down Expand Up @@ -105,6 +105,7 @@ java {
}

jar {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
manifest = project.manifest {
from gitManifest
}
Expand Down
Binary file added docs/source/images/biod_open_upload_page.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/images/biod_upload_file_complete.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/images/biod_upload_successful.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/images/invalid_sample_type.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 6 additions & 1 deletion docs/source/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,16 @@ These are available on the `XNAT Downloads Page <https://www.xnat.org/download>`
+-----------------------------+------------------------------------+
| `Container Service`_ | Highly Recommended |
+-----------------------------+------------------------------------+
| `Summary Statistics`_ | Highly Recommended |
+-----------------------------+------------------------------------+
| `Batch Launch`_ | Extends Container Service |
+-----------------------------+------------------------------------+
| `JupyterHub Integration`_ | XNAT/Python Integrated Environment |
+-----------------------------+------------------------------------+

Note that `Container Service`_ is required for using PIXI's hotel image splitting feature.
Notes:
- `Container Service`_ is required for using PIXI's hotel image splitting feature.
- `Summary Statistics`_ is required for using PIXI's biodistribution group comparison feature.

------------------------
Installation Environment
Expand Down Expand Up @@ -137,6 +141,7 @@ when you install Docker.
.. _XNAT Setup - First Time Configuration: https://wiki.xnat.org/documentation/xnat-setup-first-time-configuration
.. _XNAT OHIF Viewer: https://wiki.xnat.org/xnat-ohif-viewer
.. _Container Service: https://wiki.xnat.org/container-service/
.. _Summary Statistics: https://bitbucket.org/xnatx/statisticsdashboard_plugin/
.. _Batch Launch: https://wiki.xnat.org/xnat-tools/batch-launch-plugin
.. _JupyterHub Integration: https://wiki.xnat.org/jupyter-integration
.. _XNAT Installation Guide page: https://wiki.xnat.org/documentation/xnat-installation-guide
Expand Down
118 changes: 111 additions & 7 deletions docs/source/usage.rst

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package org.nrg.xdat.om.base;

import org.nrg.xdat.XDAT;
import org.nrg.xdat.om.base.auto.AutoPixiBiodistributiondata;
import org.nrg.xft.ItemI;
import org.nrg.xft.security.UserI;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import java.util.Hashtable;


@SuppressWarnings({"unchecked", "rawtypes"})
public abstract class BasePixiBiodistributiondata extends AutoPixiBiodistributiondata {

public BasePixiBiodistributiondata(ItemI item) {
super(item);
}

public BasePixiBiodistributiondata(UserI user) {
super(user);
}

/*
* @deprecated Use BasePixiBiodistributiondata(UserI user)
**/
public BasePixiBiodistributiondata() {
}

public BasePixiBiodistributiondata(Hashtable properties, UserI user) {
super(properties, user);
}

public static Integer getCountForSubject(final String subject_id) {
final NamedParameterJdbcTemplate template = XDAT.getContextService().getBean(NamedParameterJdbcTemplate.class);
return template.queryForObject(QUERY_COUNT_EXPERIMENTS_BY_SUBJECT_ID, new MapSqlParameterSource(SUBJECT_ID_PARAMETER, subject_id), Integer.class);
}

private static final String SUBJECT_ID_PARAMETER = "subject_id";
private static final String QUERY_COUNT_EXPERIMENTS_BY_SUBJECT_ID = "SELECT COUNT(*) " +
"FROM pixi_biodistributiondata as biod INNER JOIN (" +
"SELECT id, subject_id " +
"FROM xnat_subjectassessordata " +
"WHERE subject_id = :subject_id" +
") as s " +
"ON biod.id = s.id";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.nrg.xnat.turbine.modules.screens;

import org.apache.turbine.util.RunData;
import org.apache.velocity.context.Context;
import org.nrg.xdat.turbine.modules.screens.SecureScreen;

public class Pixi_CMO_PDX_TemplateGenerator extends SecureScreen {

@Override protected void doBuildTemplate(RunData data, Context context) throws Exception {}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.nrg.xnat.turbine.modules.screens;

import org.apache.turbine.util.RunData;
import org.apache.velocity.context.Context;
import org.nrg.xdat.turbine.modules.screens.SecureScreen;

@SuppressWarnings("unused")
public class UploadBiodistribution extends SecureScreen {

@Override
protected void doBuildTemplate(RunData data, Context context) throws Exception {
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.nrg.xnat.turbine.modules.screens;

import org.apache.turbine.util.RunData;
import org.apache.velocity.context.Context;
import org.nrg.xdat.om.PixiBiodistributiondata;
import org.nrg.xdat.om.XnatSubjectdata;
import org.nrg.xdat.turbine.utils.TurbineUtils;
import org.nrg.xft.ItemI;
import org.nrg.xft.XFTItem;
import org.nrg.xft.security.UserI;

import java.time.LocalDate;
import java.util.Optional;

@SuppressWarnings("unused")
public class XDATScreen_edit_pixi_biodistributionData extends EditSubjectAssessorScreen {
static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(XDATScreen_edit_pixi_biodistributionData.class);

/* (non-Javadoc)
* @see org.nrg.xdat.turbine.modules.screens.EditScreenA#getElementName()
*/
public String getElementName() {
return "pixi:biodistributionData";
}

public ItemI getEmptyItem(RunData data) throws Exception {
final PixiBiodistributiondata pixiBiodistributiondata =
new PixiBiodistributiondata(XFTItem.NewItem(getElementName(), getUser()));

pixiBiodistributiondata.setDate(LocalDate.now());

final UserI user = getUser();
final Optional<Object> subject_id = Optional.ofNullable(TurbineUtils.GetPassedParameter("part_id", data));

if (subject_id.isPresent()) {
final int count = PixiBiodistributiondata.getCountForSubject((String) subject_id.get()) + 1;
final XnatSubjectdata subjectData = XnatSubjectdata.getXnatSubjectdatasById(subject_id.get(), getUser(), false);
final String label = subjectData.getLabel() + "_BIOD_" + count;
pixiBiodistributiondata.setLabel(label);
}

return pixiBiodistributiondata.getItem();
}

/* (non-Javadoc)
* @see org.nrg.xdat.turbine.modules.screens.SecureReport#finalProcessing(org.apache.turbine.util.RunData, org.apache.velocity.context.Context)
*/
public void finalProcessing(RunData data, Context context) {
super.finalProcessing(data, context);
}
}
10 changes: 9 additions & 1 deletion src/main/java/org/nrg/xnatx/plugins/pixi/PIXIPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.nrg.xnat.services.XnatAppInfo;
import org.nrg.xnat.services.system.HostInfoService;
import org.nrg.xnat.turbine.utils.IDGenerator;
import org.nrg.xnatx.plugins.pixi.biod.config.BiodConfig;
import org.nrg.xnatx.plugins.pixi.bli.config.BliConfig;
import org.nrg.xnatx.plugins.pixi.inveon.config.InveonConfig;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -78,11 +79,16 @@
singular = "BLI Scan",
plural = "BLI Scans",
code = "BLIScan"),
@XnatDataModel(value = PixiBiodistributiondata.SCHEMA_ELEMENT_NAME,
singular = "Biodistribution",
plural = "Biodistributions",
code = "BIOD"),
})
@ComponentScan({"org.nrg.xnatx.plugins.pixi.xenografts.entities",
"org.nrg.xnatx.plugins.pixi.xenografts.repositories",
"org.nrg.xnatx.plugins.pixi.xenografts.services.impl",
"org.nrg.xnatx.plugins.pixi.xenografts.rest",
"org.nrg.xnatx.plugins.pixi.xenografts.services",
"org.nrg.xnatx.plugins.pixi.hotelsplitter.services.impl",
"org.nrg.xnatx.plugins.pixi.hotelsplitter.rest",
"org.nrg.xnatx.plugins.pixi.hotelsplitter.initialize",
Expand All @@ -91,8 +97,10 @@
"org.nrg.xnatx.plugins.pixi.imageAcqCtx.rest",
"org.nrg.xnatx.plugins.pixi.imageAcqCtx.services.impl",
"org.nrg.xnatx.plugins.pixi.rest",
"org.nrg.xnatx.plugins.pixi.security",
"org.nrg.xnatx.plugins.pixi.cmo.rest"
})
@Import({BliConfig.class, InveonConfig.class})
@Import({BliConfig.class, InveonConfig.class, BiodConfig.class})
@Slf4j
public class PIXIPlugin {

Expand Down
8 changes: 8 additions & 0 deletions src/main/java/org/nrg/xnatx/plugins/pixi/PixiUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.nrg.xnatx.plugins.pixi;

public class PixiUtils {

public static final String BLI_SESSION_MODALITY = "BLI";
public static final String BLI_SCAN_MODALITY = "BLI";
public static final String PIXI_DATA_MANAGER_ROLE = "PIXIDataManager";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.nrg.xnatx.plugins.pixi.biod.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan({
"org.nrg.xnatx.plugins.pixi.biod.rest",
"org.nrg.xnatx.plugins.pixi.biod.services",
"org.nrg.xnatx.plugins.pixi.biod.services.impl",
"org.nrg.xnatx.plugins.pixi.biod.helpers",
"org.nrg.xnatx.plugins.pixi.biod.helpers.impl",
})
public class BiodConfig {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.nrg.xnatx.plugins.pixi.biod.helpers;

import lombok.extern.slf4j.Slf4j;
import org.nrg.xdat.model.XnatExperimentdataI;
import org.nrg.xdat.om.XnatExperimentdata;
import org.nrg.xft.security.UserI;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class DefaultXnatExperimentDataHelper implements XnatExperimentDataHelper {

@Override
public String createNewId() throws Exception {
return XnatExperimentdata.CreateNewID();
}

@Override
public XnatExperimentdataI getExptByProjectIdentifier(String project, String identifier, UserI user, boolean preLoad) {
return XnatExperimentdata.GetExptByProjectIdentifier(project, identifier, user, preLoad);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.nrg.xnatx.plugins.pixi.biod.helpers;

import org.nrg.xft.ItemI;
import org.nrg.xft.event.EventMetaI;
import org.nrg.xft.security.UserI;

public interface SaveItemHelper {

void authorizedSave(ItemI i, UserI user, boolean overrideSecurity, boolean quarantine, boolean overrideQuarantine, boolean allowItemRemoval, EventMetaI c) throws Exception;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.nrg.xnatx.plugins.pixi.biod.helpers;

import org.nrg.xdat.model.XnatExperimentdataI;
import org.nrg.xft.security.UserI;

public interface XnatExperimentDataHelper {

String createNewId() throws Exception;
XnatExperimentdataI getExptByProjectIdentifier(String project, String identifier, UserI user, boolean preLoad);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.nrg.xnatx.plugins.pixi.biod.helpers;

import org.nrg.xdat.om.XnatSubjectdata;
import org.nrg.xft.security.UserI;

public interface XnatSubjectDataHelper {

String createNewId() throws Exception;
XnatSubjectdata getSubjectByIdOrProjectlabelCaseInsensitive(String project, String identifier, UserI user, boolean preLoad);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.nrg.xnatx.plugins.pixi.biod.helpers.impl;

import lombok.extern.slf4j.Slf4j;
import org.nrg.xft.ItemI;
import org.nrg.xft.event.EventMetaI;
import org.nrg.xft.security.UserI;
import org.nrg.xnatx.plugins.pixi.biod.helpers.SaveItemHelper;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class DefaultSaveItemHelper implements SaveItemHelper {

@Override
public void authorizedSave(ItemI i, UserI user, boolean overrideSecurity, boolean quarantine, boolean overrideQuarantine, boolean allowItemRemoval, EventMetaI c) throws Exception {
org.nrg.xft.utils.SaveItemHelper.authorizedSave(i, user, overrideSecurity, quarantine, overrideQuarantine, allowItemRemoval, c);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.nrg.xnatx.plugins.pixi.biod.helpers.impl;

import lombok.extern.slf4j.Slf4j;
import org.nrg.xdat.om.XnatSubjectdata;
import org.nrg.xft.security.UserI;
import org.nrg.xnatx.plugins.pixi.biod.helpers.XnatSubjectDataHelper;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class DefaultXnatSubjectDataHelper implements XnatSubjectDataHelper {

@Override
public String createNewId() throws Exception {
return XnatSubjectdata.CreateNewID();
}

@Override
public XnatSubjectdata getSubjectByIdOrProjectlabelCaseInsensitive(String project, String identifier, UserI user, boolean preLoad) {
return XnatSubjectdata.GetSubjectByIdOrProjectlabelCaseInsensitive(project, identifier, user, preLoad);
}

}
Loading
Loading