Skip to content

Commit 7744f24

Browse files
authored
Fix skydDataId on TargetedMSRun (#526)
- Added a method to update skydDataId set on TargetedMSRun if the corresponding ExpData is not associated with an ExpRun. - Updated test
1 parent 27764f0 commit 7744f24

File tree

2 files changed

+134
-1
lines changed

2 files changed

+134
-1
lines changed

panoramapublic/src/org/labkey/panoramapublic/PanoramaPublicFileImporter.java

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import org.labkey.api.pipeline.PipelineService;
1717
import org.labkey.api.query.BatchValidationException;
1818
import org.labkey.api.security.User;
19+
import org.labkey.api.targetedms.TargetedMSService;
1920
import org.labkey.api.writer.VirtualFile;
2021
import org.labkey.panoramapublic.pipeline.CopyExperimentPipelineJob;
2122

@@ -25,6 +26,7 @@
2526
import java.nio.file.Paths;
2627
import java.util.List;
2728
import java.util.Objects;
29+
import java.util.Optional;
2830

2931
/**
3032
* This importer does a file move instead of copy to the temp directory and creates a symlink in place of the original
@@ -90,6 +92,7 @@ public void process(@Nullable PipelineJob job, FolderImportContext ctx, VirtualF
9092
PanoramaPublicSymlinkManager.get().moveAndSymLinkDirectory(expJob, ctx.getContainer(), sourceFiles, targetFiles, log);
9193

9294
alignDataFileUrls(expJob.getUser(), ctx.getContainer(), log);
95+
updateSkydDataIds(expJob.getUser(), ctx.getContainer(), log);
9396
}
9497
}
9598

@@ -154,6 +157,78 @@ private void alignDataFileUrls(User user, Container targetContainer, Logger log)
154157
}
155158
}
156159

160+
/**
161+
* Fixes incorrect skydDataId reference in TargetedMSRun. This happens when the relative locations of the sky.zip
162+
* and .skyd file are non-standard in the folder being copied.
163+
*
164+
* When a sky.zip file or its exploded folder are moved, post-import, so that the relative locations of sky.zip and
165+
* its corresponding .skyd file are non-standard, two ExpData rows are created for the skyd file in the Panorama Public
166+
* copy pipeline job.
167+
* The first ExpData (linked to the ExpRun) is created during XAR import.
168+
* The second ExpData (not linked to the ExpRun) is created in the SkylineDocumentParser.parseChromatograms() method.
169+
* Normally, while running the copy pipeline job, SkylineDocumentParser.parseChromatograms() does not have to create
170+
* a new ExpData, since an ExpData with the expected path already exists.
171+
* Having 2 ExpDatas causes:
172+
* 1. The skydDataId in TargetedMSRun references an ExpData not linked to the ExpRun. It refers to a file in the
173+
* 'export' directory which gets deleted after folder import.
174+
* 2. FK violations during cleanup (CopyExperimentFinalTask.cleanupExportDirectory()) prevents deletion of ExpData
175+
* corresponding to the skydDataId
176+
*
177+
* This method finds a match and updates skydDataId in TargetedMSRun in the case where the skyDataId is not linked
178+
* to the ExpRun.
179+
*/
180+
private void updateSkydDataIds(User user, Container targetContainer, Logger log) throws BatchValidationException, ImportException
181+
{
182+
log.info("Updating skydDataIds in folder: " + targetContainer.getPath());
183+
184+
boolean errors = false;
185+
ExperimentService expService = ExperimentService.get();
186+
List<? extends ExpRun> runs = expService.getExpRuns(targetContainer, null, null);
187+
188+
TargetedMSService tmsService = TargetedMSService.get();
189+
for (ExpRun run : runs)
190+
{
191+
var targetedmsRun = tmsService.getRunByLsid(run.getLSID(), targetContainer);
192+
if (targetedmsRun == null) continue;
193+
194+
var skydDataId = targetedmsRun.getSkydDataId();
195+
if (skydDataId == null) continue;
196+
197+
var skydData = expService.getExpData(skydDataId);
198+
if (skydData == null)
199+
{
200+
log.error("Could not find a row for skydDataId " + skydDataId + " for run " + targetedmsRun.getFileName());
201+
errors = true;
202+
}
203+
else if (skydData.getRun() == null)
204+
{
205+
// skydData is not associated with an ExpRun. Find an ExpData associated with the ExpRun that matches
206+
// the skydName and update the skydDataId on the run.
207+
String skydName = skydData.getName();
208+
Optional<? extends ExpData> matchingData = run.getAllDataUsedByRun().stream()
209+
.filter(data -> Objects.equals(skydName, data.getName()))
210+
.findFirst();
211+
212+
if (matchingData.isPresent())
213+
{
214+
ExpData data = matchingData.get();
215+
log.debug("Updating skydDataId for run " + targetedmsRun.getFileName() + " to " + data.getRowId());
216+
tmsService.updateSkydDataId(targetedmsRun, data, user);
217+
}
218+
else
219+
{
220+
log.error("Could not find matching skyData for run " + targetedmsRun.getFileName());
221+
errors = true;
222+
}
223+
}
224+
}
225+
226+
if (errors)
227+
{
228+
throw new ImportException("Could not update skydDataIds");
229+
}
230+
}
231+
157232
public static class Factory extends AbstractFolderImportFactory
158233
{
159234
@Override

panoramapublic/test/src/org/labkey/test/tests/panoramapublic/PanoramaPublicMoveSkyDocTest.java

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,46 @@ public void testExperimentCopy()
5858
moveDocument(SKY_FILE_2, targetFolder, 2);
5959

6060
goToProjectFolder(projectName, targetFolder);
61-
log("Importing " + SKY_FILE_3 + " in folder " + skyDocSourceFolder);
61+
log("Importing " + SKY_FILE_3 + " in folder " + targetFolder);
6262
importData(SKY_FILE_3, 3);
6363

64+
// Test moving the sky.zip to a subdirectory in the file root, while the .skyd remains in the original location.
65+
//
66+
// If the sky.zip file and the .skyd file are not in their typical relative locations, the skydDataId in
67+
// TargetedMSRun has to be updated after the folder is copied to Panorama Public. Without the update the
68+
// copy pipeline job fails.
69+
// Example:
70+
// -------------------------
71+
// BEFORE MOVE:
72+
// SmallMolLibA.sky.zip
73+
// SmallMolLibA
74+
// - SmallMolLibA.sky
75+
// - SmallMolLibA.skyd
76+
// -------------------------
77+
// AFTER MOVE:
78+
// - SkylineFiles
79+
// - SmallMolLibA.sky.zip (new location after move)
80+
// SmallMolLibA
81+
// - SmallMolLibA.sky
82+
// - SmallMolLibA.skyd
83+
// This results in:
84+
// Two ExpData rows created for the .skyd file in folder copy on Panorama Public.
85+
// 1. @files/export/.../Run<id>/SkylineFiles/SmallMolLibA/SmallMolLibA.skyd
86+
// 2. @files/SmallMolLibA/SmallMolLibA.skyd
87+
// #1 is set as the skydDataId in TargetedMSRuns, but it is not linked to the ExpRun (runId is null)
88+
// #2 is linked to the ExpRun. This is the ExpData that skydDataId in TargetedMSRun *should* refer to.
89+
// This situation causes two problems
90+
// 1. ExpData cleanup in CopyExperimentFinalTask fails due to FK violation - cannot delete ExpData #1 since
91+
// skydDataId in TargetedMSRun points to it.
92+
// 2. Even if we were not cleaning up ExpData referring to files in the 'export' directory, chromatogram data
93+
// would become unavailable since the "export" directory gets deleted after folder import.
94+
//
95+
// PanoramaPublicFileImporter.updateSkydDataId() fixes the skydDataId, if required.
96+
String subDir = "SkylineFiles";
97+
log("Moving " + SKY_FILE_3 + " to sub directory " + subDir + " in the Files browser");
98+
// Move the .sky.zip file to a subdirectory
99+
moveSkyZipToSubDir(SKY_FILE_3, subDir);
100+
64101
log("Creating and submitting an experiment");
65102
String experimentTitle = "Experiment to test moving Skyline documents from other folders";
66103
var expWebPart = createExperimentCompleteMetadata(experimentTitle);
@@ -75,6 +112,15 @@ public void testExperimentCopy()
75112
verifyRunFilePathRoot(SKY_FILE_1, PANORAMA_PUBLIC, panoramaCopyFolder);
76113
verifyRunFilePathRoot(SKY_FILE_2, PANORAMA_PUBLIC, panoramaCopyFolder);
77114
verifyRunFilePathRoot(SKY_FILE_3, PANORAMA_PUBLIC, panoramaCopyFolder);
115+
116+
// Verify that we can view chromatograms for the Skyline document that was moved to a subdirectory.
117+
goToDashboard();
118+
clickAndWait(Locator.linkContainingText(SKY_FILE_3));
119+
clickAndWait(Locator.linkContainingText("2 replicates"));
120+
clickAndWait(Locator.linkContainingText("FU2_2017_0915_RJ_05_1ab_30").index(0));
121+
assertTextPresent("Sample File Summary");
122+
assertTextPresent("Total Ion Chromatogram");
123+
assertTextNotPresent("Unable to load chromatogram");
78124
}
79125

80126
private void moveDocument(String skylineDocName, String targetFolder, int jobCount)
@@ -96,6 +142,18 @@ private void moveDocument(String skylineDocName, String targetFolder, int jobCou
96142
verifyRunFilePathRoot(skylineDocName, getProjectName(), targetFolder);
97143
}
98144

145+
private void moveSkyZipToSubDir(String documentName, String subDir)
146+
{
147+
portalHelper.goToModule("FileContent");
148+
waitForText(documentName);
149+
if (!_fileBrowserHelper.fileIsPresent(subDir))
150+
{
151+
_fileBrowserHelper.createFolder(subDir);
152+
}
153+
_fileBrowserHelper.moveFile(documentName, subDir);
154+
}
155+
156+
99157
private void verifyRunFilePathRoot(String skylineDocName, String projectName, String targetFolder)
100158
{
101159
// Verify that exp.run filePathRoot is set to the target folder

0 commit comments

Comments
 (0)