Skip to content

Commit

Permalink
refactor: drop jpype, use subprocess.call() instead
Browse files Browse the repository at this point in the history
  • Loading branch information
chanshing committed Nov 22, 2023
1 parent 91db56d commit 44b1466
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 38 deletions.
95 changes: 65 additions & 30 deletions src/actipy/AxivityReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
* Based on the OpenMovement implementation:
* https://github.com/digitalinteraction/openmovement/blob/72c992b0ea524275d898e86181c5b38a9622c529/Software/AX3/cwa-convert/java/src/newcastle/cwa/CwaBlock.java
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.nio.ByteOrder;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
Expand All @@ -13,6 +15,7 @@
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.io.IOException;


public class AxivityReader {
Expand All @@ -32,28 +35,39 @@ public class AxivityReader {
ITEM_NAMES_AND_TYPES = Collections.unmodifiableMap(itemNamesAndTypes);
}

private String accFile;
private String outFile;
private boolean verbose;
private static String accFile;
private static String outFile;
private static boolean verbose = true;

private LocalDateTime sessionStart = null;
private static LocalDateTime sessionStart = null;

private int statusOK = -1;
private float sampleRate = -1;
private int errCounter = 0;
private double lastBlockTime = 0;
private static int statusOK = -1;
private static float sampleRate = -1;
private static int errCounter = 0;
private static double lastBlockTime = 0;

private NpyWriter writer;
private static NpyWriter writer;


public AxivityReader(String accFile, String outFile, boolean verbose) {
this.accFile = accFile;
this.outFile = outFile;
this.verbose = verbose;
}

// public Map<String, String> read() {
public static void main(String[] args) {

public Map<String, String> read() {
// Parse args string. Example:
// $ java AxivityReader inputFile:/path/to/inputFile.bin outputFile:/path/to/outputFile.npy verbose:1
for (String arg : args) {
String[] argSplit = arg.split(":");
if (argSplit[0].equals("inputFile")) {
accFile = argSplit[1];
} else if (argSplit[0].equals("outputFile")) {
outFile = argSplit[1];
} else if (argSplit[0].equals("verbose")) {
verbose = argSplit[1].equals("1");
}
}
if (accFile == null || outFile == null) {
System.out.println("ERROR: Both accFile and outFile must be provided.");
System.exit(1);
}

Map<String, String> info = new HashMap<String, String>();

Expand Down Expand Up @@ -96,22 +110,43 @@ public Map<String, String> read() {
info.put("ReadErrors", String.valueOf(errCounter));
info.put("SampleRate", String.valueOf(sampleRate));

return info;
// Write to info.txt file. Each line is a key:value pair.
String infoFile = outFile.substring(0, outFile.lastIndexOf(File.separator)) + File.separator + "info.txt"; // use same dir as outFile
try {
FileWriter file = new FileWriter(infoFile);
for (Map.Entry<String, String> entry : info.entrySet()) {
file.write(entry.getKey() + ":" + entry.getValue() + "\n");
}
file.flush();
file.close();
} catch (IOException e) {
e.printStackTrace();
}

// return info;
return;

}


public static Map<String, String> read(String accFile, String outFile, boolean verbose) {
return new AxivityReader(accFile, outFile, verbose).read();
}
// public AxivityReader(String accFile, String outFile, boolean verbose) {
// this.accFile = accFile;
// this.outFile = outFile;
// this.verbose = verbose;
// }


public static Map<String, String> read(String accFile, String outFile) {
return new AxivityReader(accFile, outFile, true).read();
}
// public static Map<String, String> read(String accFile, String outFile, boolean verbose) {
// return new AxivityReader(accFile, outFile, verbose).read();
// }


// public static Map<String, String> read(String accFile, String outFile) {
// return new AxivityReader(accFile, outFile, true).read();
// }


private void parseCwaBlock(ByteBuffer block) {
private static void parseCwaBlock(ByteBuffer block) {
block.flip();
block.order(ByteOrder.LITTLE_ENDIAN);
String header = (char) block.get() + "";
Expand Down Expand Up @@ -237,7 +272,7 @@ private void parseCwaBlock(ByteBuffer block) {
}


private LocalDateTime getCwaLocalDateTime(int cwaTimeInfo) {
private static LocalDateTime getCwaLocalDateTime(int cwaTimeInfo) {
int year = (int) ((cwaTimeInfo >> 26) & 0x3f) + 2000;
int month = (int) ((cwaTimeInfo >> 22) & 0x0f);
int day = (int) ((cwaTimeInfo >> 17) & 0x1f);
Expand All @@ -249,20 +284,20 @@ private LocalDateTime getCwaLocalDateTime(int cwaTimeInfo) {
}


private long getCwaTimestamp(int cwaTimeInfo) {
private static long getCwaTimestamp(int cwaTimeInfo) {
LocalDateTime ldt = getCwaLocalDateTime(cwaTimeInfo);
long timestamp = ldt.toEpochSecond(ZoneOffset.UTC);
return timestamp;
}


private LocalDateTime getCwaHeaderLoggingStartTime(ByteBuffer block) {
private static LocalDateTime getCwaHeaderLoggingStartTime(ByteBuffer block) {
int delayedLoggingStartTime = (int) getUnsignedInt(block, 13);
return getCwaLocalDateTime(delayedLoggingStartTime);
}


public String getOutFile() {
public static String getOutFile() {
return outFile;
}

Expand All @@ -279,12 +314,12 @@ private static int getUnsignedShort(ByteBuffer bb, int position) {
}


private void setupWriter() {
private static void setupWriter() {
writer = new NpyWriter(outFile, ITEM_NAMES_AND_TYPES);
}


private void closeWriter() {
private static void closeWriter() {
try {
writer.close();
} catch (Exception e) {
Expand Down
30 changes: 22 additions & 8 deletions src/actipy/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
import zipfile
import gzip
import pathlib
import json
import numpy as np
import pandas as pd
import subprocess
import jpype

from actipy import processing as P
Expand Down Expand Up @@ -241,25 +243,37 @@ def _read_device(input_file, verbose=True):
print("Error: %s - %s." % (e.filename, e.strerror))


def java_read_device(input_file, output_file, verbose):
def java_read_device(input_file, output_file, verbose=True):
""" Core function that calls the Java method to read device data """

setupJVM()

if input_file.lower().endswith('.cwa'):
info = jpype.JClass('AxivityReader').read(input_file, output_file, verbose)
java_reader = 'AxivityReader'

elif input_file.lower().endswith('.gt3x'):
info = jpype.JClass('ActigraphReader').read(input_file, output_file, verbose)
java_reader = 'ActigraphReader'

elif input_file.lower().endswith('.bin'):
info = jpype.JClass('GENEActivReader').read(input_file, output_file, verbose)
java_reader = 'GENEActivReader'

else:
raise ValueError(f"Unknown file extension: {input_file}")

# Convert the Java HashMap object to Python dictionary
info = {str(k): str(info[k]) for k in info}
command = [
"java",
"-XX:ParallelGCThreads=1",
"-cp", pathlib.Path(__file__).parent,
java_reader,
f"inputFile:{input_file}",
f"outputFile:{output_file}",
f"verbose:{int(verbose)}",
]

subprocess.run(command, check=True)

# Load info.txt file. Each line is a key:value pair.
with open(os.path.join(os.path.dirname(output_file), "info.txt"), 'r') as f:
info = dict([line.split(':') for line in f.read().splitlines()])

info['ReadOK'] = int(info['ReadOK'])
info['ReadErrors'] = int(info['ReadErrors'])
info['SampleRate'] = float(info['SampleRate'])
Expand Down

0 comments on commit 44b1466

Please sign in to comment.