Running ALPACA from Python Console

Hello, I am trying to run ALPACA from the Python console.

I am accessing the logic with:

import ALPACA
AlpacaLogic = ALPACA.ALPACALogic()
Then I define my paths and directories as inputs for ALPACA batch mode.
I set skipScaling to False

When I try to run:
AlpacaLogic.process(sourceModelPath, sourceLandmarkPath, targetModelDirectory, outputDirectory, skipScaling)

i get the error:

Traceback (most recent call last):
File “”, line 10, in
File “C:/Users/eherbst/AppData/Local/slicer.org/Slicer 5.6.2/slicer.org/Extensions-32448/SlicerMorph/lib/Slicer-5.6/qt-scripted-modules/ALPACA.py”, line 3085, in process
“InputVolume”: inputVolume.GetID(),
AttributeError: ‘str’ object has no attribute ‘GetID’

I see in the ALPACA.py code that running Alpaca also requires the ProjectionFactor and Parameters, but if I do not define them as inputs, does it just use the defaults?

hank you,
Eva

AlpacaLogic.process is a test utility and doesn’t run the method from the command line. The batch mode tab of the module is intended to handle bundled jobs, maybe if you could describe your use case for running this from the command line I can help find a solution?

I agree with Sara that the best way is probably just to run the batch mode in the UI.

If you want to run the batch mode in Python, you can use the function runLandmarkMultiprocess() in the ALPACALogic. There is a parameter self.parameterDictionary that would have all the required parameters. So far, the default parameters work for most of my cases.You can also check the function onApplyLandmarkMulti() to see how the batch mode runs using the runLandmarkMultiprocess function.

Thank you Sara and Chi!

My use case is that I process a lot of scans (segmentation → landmark transfer via Alpaca → cropping based on landmarks) and since the segmentation and cropping is automated, it would be nice to also automate the Alpaca step to run everything together without manual input.

I will try the runLandmarkMultiprocess function.

Thanks again!
Eva

1 Like

Hi all,

Thanks for your help!
I got it working with the following function:

def runAlpaca(scapulaModelOutputDir, sourceModelPath, sourceLandmarkPath, landmarkOutputDirectory):
import ALPACA
AlpacaLogic = ALPACA.ALPACALogic()
targetModelDirectory = scapulaModelOutputDir
scalingOption= True
projectionFactor = 0.01
useJSONFormat = True
parameters = { #from Alpaca defaults
“projectionFactor”: 0.01,
“pointDensity”: 1.00,
“normalSearchRadius”: 2,
“FPFHNeighbors”: 100,
“FPFHSearchRadius”: 5.00,
“distanceThreshold”: 3.00,
“maxRANSAC”: 1000000,
“ICPDistanceThreshold”: 1.50,
“alpha”: 2.0,
“beta”: 2.0,
“CPDIterations”: 100,
“CPDTolerance”: 0.001,
“Acceleration”: False,
“BCPDFolder”: “T:/Slicer/bcpd-master/bcpd-master/win”
}
AlpacaLogic.runLandmarkMultiprocess(sourceModelPath, sourceLandmarkPath, targetModelDirectory, landmarkOutputDirectory, scalingOption, projectionFactor, useJSONFormat, parameters)

I copied all of the default parameters from the GUI, since I couldn’t figure out how to retrieve them from the command line.
Maybe there is a more elegant solution that would update based on user inputs in the GUI, or the plugin’s defaults (in case they ever change).

Also, for projection factor, the default in the GUI is 1.0, but I saw that the code divides this by 100, so I did the same when hard coding the defaults (since it looks like the division happens and then the value is updated in the parameter list).

Setting it directly to 1.0 in the parameter list gave a bad landmark transfer so it looks like this scaling is very important.

Thanks again!
Eva

I am glad this worked.

However, what is the purpose of running ALPACA in this way? If you are going to use fixed parameters, I think batch mode will be easier. I thought maybe you are trying to do a parameter sweep (i.e., try many samples with different sets of parameters).

I want to batch process a lot of scans, and am using Alpaca to transfer landmarks to then fit an ROI to each bone and then analyse it. The steps before and after Alpaca are all run from python so it helps to run everything together in an automated way.

1 Like

Hello again,

I just tried running this after not using it for a while.

I am testing it with a single source model for now, which previously worked.

I previously specified the specific .ply and the mrk.json files in the code as the source model path and source landmark path, not just the directories (similar to how those individual files can be selected in the MALPACA GUI)

However, doing that now gives me an error that mrk.json file that it should be a directory:

NotADirectoryError: [WinError 267] The directory name is invalid:>
‘P:…/source_landmarks/lm_2NHJX1.mrk.json’

When I replace the specific files with directories, that prevents the above error about the directory but the results remain empty (medianEstimates and individualEstimates folders are created but empty)

My inputs look like this now (previously the first two were pointing to specific files.
sourceModelPath = …/source_scapula_model"
sourceLandmarkPath = “…/source_landmarks”
targetModelPath = “…/scapula_model_output”
targetLandmarkPath = “…/landmark_output”

Do you have any recommendations how to fix this issue to enable batch running Alpaca/Malpaca like I did before?

I checked the Alpaca logic on github but didnt see find changes that could explain this new error.

Thank you,
Eva

I haven’t tried MALPACA from scripting for a while. I think the batch mode in runLandmarkMultiProcess should simply iterate through sourceModelList from the source directory, then run pairwiseAlignment for each source model to generate a predicted lm array for each source, and then use np.median() to output the median:

Are there any other error printed out? If you have time to add print(array) after line 1548, will it print out the landmark array?

Thank you Chi, we will test this.
I also thought it shouldn’t be a problem to have a single landmark source.
I didn’t get any errors when specifying the overall folder paths for the source models and source landmarks which is strange.
The output landmark folders are created but empty.

We will try with the print(array) statement.

Thank you,
Eva

MALPACA is for multiple templates (multiple sources). If you have a single source, use ALPACA (single-template option).

If you are using MALPACA logic, then it is normal it is expecting a directory of inputs, as opposed to a single source file.

If you run MALPACA by scripting using multi-template option by putting a single file in the folder, it should simply iterate through that single file in the folder and export the median equivalent to the output that the single template. Hopefully it can be printed out.

When you specify “single template” in the batch mode, it should simply read that particular template file in the folder and run pairwiseAlignment and export the predictions of that template: :SlicerMorph/ALPACA/ALPACA.py at 259a0f496551d0e1c5a6851e4233946d672c1391 · SlicerMorph/SlicerMorph · GitHub

Then it will pass that single file to runLandmarkMultiProcess to do batch mode for a single template when the boolean function detects the sourceModelPath points to a particular file:

I’ll also see if I can try it over the weekend. I’m surprised that there’s no output there. If you run batch mode in ALPACA GUI, will it output things normally?

Thank you Murat and Chi!

We want to use MALPACA in the future but were testing with a single template for now, which worked in the past.

I think I might have found the error.

The landmarks and meshes were recreated after my initial tests by another member in my group and had slightly different names from each other. Apologies for my oversight in not catching this.
This would also explain why alpaca worked in the gui since there was just one template and it wouldn’t need to match in that case.

We will double check it tomorrow.

Thank you,
Eva

1 Like