Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parameter improvment and some small new abilities #348

Merged
merged 18 commits into from
May 18, 2018
Merged
Show file tree
Hide file tree
Changes from 16 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
30 changes: 30 additions & 0 deletions src/main/java/fact/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -534,4 +534,34 @@ public static double[] flatten2dArray(double[][] array2d) {
.toArray();
}


/**
* Check if the dataitem has the timestamp key, if not return the MC data default timestamp
*
* @param item The event to process
* @return The timestamp of the event
*/
public static ZonedDateTime getTimeStamp(Data item) {
return getTimeStamp(item, "timestamp");
}

/**
* Check if the dataitem has the timestamp key, if not return the MC data default timestamp
*
* @param item The event to process
* @return The timestamp of the event
*/
public static ZonedDateTime getTimeStamp(Data item, String timeStampKey) {
ZonedDateTime timeStamp = null;
if (item.containsKey(timeStampKey)) {
Utils.isKeyValid(item, timeStampKey, ZonedDateTime.class);
timeStamp = (ZonedDateTime) item.get(timeStampKey);
} else {
// MC Files don't have a UnixTimeUTC in the data item. Here the timestamp is hardcoded to 1.1.2000
// => The 12 bad pixels we have from the beginning on are used.
timeStamp = ZonedDateTime.of(2000, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC);
}

return timeStamp;
}
}
11 changes: 1 addition & 10 deletions src/main/java/fact/cleaning/TwoLevelTimeMedian.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,7 @@ public class TwoLevelTimeMedian extends BasicCleaning implements Processor {
@Override
public Data process(Data item) {

ZonedDateTime timeStamp;
if (item.containsKey("UnixTimeUTC") == true) {
Utils.isKeyValid(item, "UnixTimeUTC", int[].class);
int[] eventTime = (int[]) item.get("UnixTimeUTC");
timeStamp = Utils.unixTimeUTCToZonedDateTime(eventTime);
} else {
// MC Files don't have a UnixTimeUTC in the data item. Here the timestamp is hardcoded to 1.1.2000
// => The 12 bad pixels we have from the beginning on are used.
timeStamp = ZonedDateTime.of(2000, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC);
}
ZonedDateTime timeStamp = Utils.getTimeStamp(item);

double[] photonCharge = Utils.toDoubleArray(item.get(photonChargeKey));
double[] arrivalTimes = Utils.toDoubleArray(item.get(arrivalTimeKey));
Expand Down
11 changes: 1 addition & 10 deletions src/main/java/fact/cleaning/TwoLevelTimeNeighbor.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,7 @@ public Data process(Data item) {
Utils.isKeyValid(item, arrivalTimeKey, double[].class);
Utils.isKeyValid(item, photonChargeKey, double[].class);

ZonedDateTime timeStamp = null;
if (item.containsKey("UnixTimeUTC") == true) {
Utils.isKeyValid(item, "UnixTimeUTC", int[].class);
int[] eventTime = (int[]) item.get("UnixTimeUTC");
timeStamp = Utils.unixTimeUTCToZonedDateTime(eventTime);
} else {
// MC Files don't have a UnixTimeUTC in the data item. Here the timestamp is hardcoded to 1.1.2000
// => The 12 bad pixels we have from the beginning on are used.
timeStamp = ZonedDateTime.of(2000, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC);
}
ZonedDateTime timeStamp = Utils.getTimeStamp(item);

double[] photonCharge = Utils.toDoubleArray(item.get(photonChargeKey));
double[] arrivalTimes = Utils.toDoubleArray(item.get(arrivalTimeKey));
Expand Down
122 changes: 93 additions & 29 deletions src/main/java/fact/datacorrection/DrsCalibration.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package fact.datacorrection;

import fact.Constants;
import fact.Utils;
import fact.io.hdureader.BinTable;
import fact.io.hdureader.BinTableReader;
import fact.io.hdureader.FITS;
Expand All @@ -26,21 +27,34 @@
* either as File or URL and will read the DRS data from that. This data is then
* applied to all FactEvents processed by this class.
*
* @author Christian Bockermann <[email protected]>
* @author Christian Bockermann <[email protected]> , Michael Bulinski <[email protected]>
*/
public class DrsCalibration implements StatefulProcessor {
static Logger log = LoggerFactory.getLogger(DrsCalibration.class);

@Parameter
@Parameter(required = false, description = "The data key that will hold the resulting data array.")
public String outputKey = "DataCalibrated";

@Parameter(required = false, description = "Data array to be calibrated", defaultValue = "Data")
public String key = "Data";

@Parameter(required = false, description = "Key to the StartCellData.")
public String startCellKey = "StartCellData";

@Parameter(required = false, description = "A URL to the DRS calibration data (in FITS formats)",
defaultValue = "Null. Will try to find path to drsFile from the stream.")
public URL url = null;

@Parameter(required = false, description = "The name of the key that holds the drs filename.",
defaultValue = "@drsFile")
public String drsKey = "@drsFile";

@Parameter(required = false, description = "Whether to reverse the process.", defaultValue = "false")
public boolean reverse = false;

private double dconv = 2000.0f / 4096.0f;

Data drsData = null;

private File currentDrsFile = new File("");

Expand Down Expand Up @@ -84,7 +98,6 @@ protected void loadDrsData(URL in) {
this.drsTriggerOffsetRms = row.getFloatArray("TriggerOffsetRms").orElseThrow(() -> new RuntimeException("File does not contain key TriggerOffsetRms"));
this.drsGainMean = row.getFloatArray("GainMean").orElseThrow(() -> new RuntimeException("File does not contain key GainMean"));
this.drsGainRms = row.getFloatArray("GainRms").orElseThrow(() -> new RuntimeException("File does not contain key GainRms"));

} catch (IOException e) {
throw new RuntimeException(e);
}
Expand All @@ -99,7 +112,7 @@ public Data process(Data data) {

if (this.url == null) {
//file not loaded yet. try to find by magic.
File drsFile = (File) data.get("@drsFile");
File drsFile = (File) data.get(drsKey);
if (drsFile != null) {
if (!drsFile.equals(currentDrsFile)) {
currentDrsFile = drsFile;
Expand All @@ -108,46 +121,59 @@ public Data process(Data data) {
loadDrsData(drsFile.toURI().toURL());
} catch (MalformedURLException e) {
//pass.
throw new RuntimeException("URL malformed");
}
}
} else {
throw new IllegalArgumentException("No drs file set or no @drsFile key in data stream");
}
}

double[] rawfloatData;
log.debug("Processing Data item by applying DRS calibration...");
short[] rawData = (short[]) data.get(key);
if (rawData == null) {
log.error(" data .fits file did not contain the value for the key "
+ key + ". cannot apply drscalibration");
throw new RuntimeException(
" data .fits file did not contain the value for the key \"" + key + "\". Cannot apply drs calibration)");
}
if (!reverse) {
short[] rawData = (short[]) data.get(key);
if (rawData == null) {
log.error(" data .fits file did not contain the value for the key "
+ key + ". cannot apply drscalibration");
throw new RuntimeException(
" data .fits file did not contain the value for the key \""
+ key + "\". Cannot apply drs calibration)");
}

double[] rawfloatData = new double[rawData.length];
// System.arraycopy(rawData, 0, rawfloatData, 0, rawfloatData.length);
for (int i = 0; i < rawData.length; i++) {
rawfloatData[i] = rawData[i];
rawfloatData = new double[rawData.length];
for (int i = 0; i < rawData.length; i++) {
rawfloatData[i] = rawData[i];
}
} else {
Utils.isKeyValid(data, key, double[].class);
rawfloatData = (double[]) data.get(key);
}

short[] startCell = (short[]) data.get("StartCellData");
short[] startCell = (short[]) data.get(startCellKey);
if (startCell == null) {
log.error(" data .fits file did not contain startcell data. cannot apply drscalibration");
return null;
}
log.debug("raw data has {} elements", rawData.length);
log.debug("raw data has {} elements", rawfloatData.length);
log.debug("StartCellData has {} elements", startCell.length);

double[] output = rawfloatData;
if (!key.equals(outputKey)) {
output = new double[rawData.length];
output = new double[rawfloatData.length];
}

double[] calibrated = applyDrsCalibration(rawfloatData, output, startCell);

data.put(outputKey, calibrated);

// add color value if set
if (!reverse) {
double[] calibrated = applyDrsCalibration(rawfloatData, output, startCell);
data.put(outputKey, calibrated);
} else {
double[] calibrated = reverseDrsCalibration(rawfloatData, output, startCell);
short[] decalibratedShortData = new short[calibrated.length];
for (int i = 0; i < calibrated.length; i++) {
decalibratedShortData[i] = (short) calibrated[i];
}
data.put(outputKey, decalibratedShortData);
}

return data;
}
Expand Down Expand Up @@ -225,7 +251,6 @@ public double[] applyDrsCalibration(double[] data, double[] destination,
// TrueValue[c][s] = ( RawValue[c][s] - Offset[c][ (c+t)%1024 ] ) /
// Gain[c][ (c+t)%1024 ] * 1907.35 - TriggerOffset[c][s]

double dconv = 2000.0f / 4096.0f;
double vraw;

int pos, offsetPos, triggerOffsetPos;
Expand All @@ -234,15 +259,15 @@ public double[] applyDrsCalibration(double[] data, double[] destination,

pos = pixel * roi + slice;
// Offset and Gain vector *should look the same
int start = startCellVector[pixel] != -1 ? startCellVector[pixel]
: 0;
int start = startCellVector[pixel] != -1 ? startCellVector[pixel] : 0;

offsetPos = pixel * drsBaselineMean.length / Constants.N_PIXELS
+ ((slice + start) % (drsBaselineMean.length / Constants.N_PIXELS));

triggerOffsetPos = pixel * drsTriggerOffsetMean.length / Constants.N_PIXELS + slice;

vraw = data[pos] * dconv;
vraw = data[pos];
vraw *= dconv;
vraw -= drsBaselineMean[offsetPos];
vraw -= drsTriggerOffsetMean[triggerOffsetPos];
vraw /= drsGainMean[offsetPos];
Expand All @@ -264,6 +289,47 @@ public double[] applyDrsCalibration(double[] data, double[] destination,
return destination;
}

/**
* Reverses the drsCalibration performed in applyDrsCalibration.
*
* @param data The calibrated data the decalibrate.
* @param destination If given use this as the destination array otherwise a new one is created.
* @param startCellVector The array containing the start cells used to know which calibration constants to use.
* @return The decalibrated data array
*/
public double[] reverseDrsCalibration(double[] data, double[] destination, short[] startCellVector) {
if (destination == null || destination.length != data.length)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe throwing in case the length do not match is better, what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was legacy code, but yeah i can't think of any reason where giving a different length is intentional and not an error or lazyness. Changed in the next commit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice

destination = new double[data.length];
int roi = data.length / Constants.N_PIXELS;

double vraw;

int pos, offsetPos, triggerOffsetPos;
for (int pixel = 0; pixel < Constants.N_PIXELS; pixel++) {
for (int slice = 0; slice < roi; slice++) {

pos = pixel * roi + slice;
// Offset and Gain vector *should look the same
int start = startCellVector[pixel] != -1 ? startCellVector[pixel] : 0;

offsetPos = pixel * drsBaselineMean.length / Constants.N_PIXELS
+ ((slice + start) % (drsBaselineMean.length / Constants.N_PIXELS));

triggerOffsetPos = pixel * drsTriggerOffsetMean.length / Constants.N_PIXELS + slice;

vraw = data[pos];
vraw /= 1907.35;
vraw *= drsGainMean[offsetPos];
vraw += drsTriggerOffsetMean[triggerOffsetPos];
vraw += drsBaselineMean[offsetPos];
vraw /= dconv;

destination[pos] = vraw;
}
}

return destination;
}

@Override
public void init(ProcessContext processContext) throws Exception {
Expand All @@ -286,6 +352,4 @@ public void resetState() throws Exception {
public void finish() throws Exception {

}


}
12 changes: 1 addition & 11 deletions src/main/java/fact/datacorrection/InterpolatePixelArray.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,7 @@ public Data process(Data item) {

double[] input = (double[]) item.get(inputKey);

ZonedDateTime timeStamp;

if (item.containsKey("UnixTimeUTC")) {
Utils.isKeyValid(item, "UnixTimeUTC", int[].class);
int[] eventTime = (int[]) item.get("UnixTimeUTC");
timeStamp = Utils.unixTimeUTCToZonedDateTime(eventTime);
} else {
// MC Files don't have a UnixTimeUTC in the data item. Here the timestamp is hardcoded to 1.1.2000
// => The 12 bad pixels we have from the beginning on are used.
timeStamp = ZonedDateTime.of(2000, 1, 1, 0, 0,0,0, ZoneOffset.UTC);
}
ZonedDateTime timeStamp = Utils.getTimeStamp(item);
PixelSet badPixelsSet = calibService.getBadPixels(timeStamp);

double[] output;
Expand Down
20 changes: 8 additions & 12 deletions src/main/java/fact/datacorrection/InterpolateTimeSeries.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ public class InterpolateTimeSeries implements Processor {
@Parameter(required = false, description = "The minimum number of neighboring pixels required for interpolation", defaultValue = "3")
public int minPixelToInterpolate = 3;

@Parameter(required = false, description = "The key for the resulting badPixelSet.")
public String badPixelKey = "badPixels";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this an xml Parameter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use the processor twice, so i added this in case someone want to preserve the output and not override the key with the second processor. I think it is cleaner this way, but I can remove it.


@Parameter(required = false, description = "The key to the timestamp of the Event.")
public String timeStampKey = "timestamp";

private FactPixelMapping pixelMap = FactPixelMapping.getInstance();


Expand All @@ -44,17 +50,7 @@ public Data process(Data item) {
Utils.isKeyValid(item, dataKey, double[].class);
double[] data = (double[]) item.get(dataKey);

ZonedDateTime timeStamp = null;

if (item.containsKey("UnixTimeUTC") == true) {
Utils.isKeyValid(item, "UnixTimeUTC", int[].class);
int[] eventTime = (int[]) item.get("UnixTimeUTC");
timeStamp = Utils.unixTimeUTCToZonedDateTime(eventTime);
} else {
// MC Files don't have a UnixTimeUTC in the data item. Here the timestamp is hardcoded to 1.1.2000
// => The 12 bad pixels we have from the beginning on are used.
timeStamp = ZonedDateTime.of(2000, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC);
}
ZonedDateTime timeStamp = Utils.getTimeStamp(item, timeStampKey);

PixelSet badPixelSet = calibService.getBadPixels(timeStamp);

Expand All @@ -67,7 +63,7 @@ public Data process(Data item) {
}

item.put(dataOutputKey, data);
item.put("badPixels", badPixelSet);
item.put(badPixelKey, badPixelSet);
return item;
}

Expand Down
7 changes: 5 additions & 2 deletions src/main/java/fact/datacorrection/PatchJumpRemoval.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ public class PatchJumpRemoval implements Processor {
@Parameter(required = true)
public String startCellKey = null;

@Parameter(required = false, description = "The key containing the UnixTimeUTC")
public String unixTimeKey = "UnixTimeUTC";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this a parameter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use this processor twice for different inputs with different times one will use 'UnixTimeUTC' the other 'LONS_UnixTimeUTC'. This is due to the fact that i have to calibrate the pedestal that I superimpose.


@Parameter
public double jumpLimit = 5.0;

Expand Down Expand Up @@ -94,10 +97,10 @@ public Data process(Data item) {
Utils.isKeyValid(item, prevEventsKey, PreviousEventInfoContainer.class);
Utils.isKeyValid(item, startCellKey, short[].class);
Utils.isKeyValid(item, "NROI", Integer.class);
Utils.isKeyValid(item, "UnixTimeUTC", int[].class);
Utils.isKeyValid(item, unixTimeKey, int[].class);

// Get variables out of data item
int[] currentTime = (int[]) item.get("UnixTimeUTC");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This processor apperently still uses UnixTimeUTC and not timestamp

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is currently intentional, this is because the previousEventInfo holds UnixTimeUTC and not timestamp, this would need to be changed. I would suggest its own PR, especially as the SamplePedestalEvent processor needs also to be changed (currently in its own branch, PR will be created once this PR is finished).

int[] currentTime = (int[]) item.get(unixTimeKey);
roi = (Integer) item.get("NROI");
short[] currentStartCells = (short[]) item.get(startCellKey);
double[] data = (double[]) item.get(dataKey);
Expand Down
6 changes: 2 additions & 4 deletions src/main/java/fact/extraction/BasicExtraction.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,11 @@ public class BasicExtraction implements Processor {
public Data process(Data item) {
Utils.mapContainsKeys(item, dataKey, "NROI");


double[] integralGains;
int[] unixTimeUTC = (int[]) item.get("UnixTimeUTC");
if (unixTimeUTC == null) {
if (!item.containsKey("timestamp")) {
integralGains = gainService.getSimulationGains();
} else {
ZonedDateTime timestamp = Utils.unixTimeUTCToZonedDateTime(unixTimeUTC);
ZonedDateTime timestamp = Utils.getTimeStamp(item);
integralGains = gainService.getGains(timestamp);
}

Expand Down
Loading