Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
205 changes: 75 additions & 130 deletions examples/tiled.ipynb

Large diffs are not rendered by default.

27 changes: 18 additions & 9 deletions frontend/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ export default function App() {
status,
heatmapSettings,
handleHeatmapSettingChange,
metadata
metadata,
shotRecentArray,
shotNumber,
shotMeanArray,
shotStdArray,
} = useAPXPS({});

//Automatically start the websocket connection on page load
Expand All @@ -61,7 +65,7 @@ export default function App() {
{socketStatus === 'closed' ? <Button text="Start" cb={startWebSocket}/> : <Button text="stop" cb={closeWebSocket}/>}
</li>
</SidebarItem>
<SidebarItem title='Image Settings' icon={phosphorIcons.sliders}>
<SidebarItem title='Live Image Settings' icon={phosphorIcons.sliders}>
<Settings>
<FormContainer inputs={heatmapSettings} handleInputChange={handleHeatmapSettingChange}/>
</Settings>
Expand All @@ -72,19 +76,24 @@ export default function App() {
</Sidebar>

<Main >
<Widget title='Live Images' width='w-3/5' maxWidth='max-w-[1000px]' defaultHeight='h-full' maxHeight='max-h-[1400px]' expandedWidth='w-full'>
<Widget title={`Live Images - Current Shot #${shotNumber}`} width='w-3/5' maxWidth='max-w-[1000px]' defaultHeight='h-full' maxHeight='max-h-[1400px]' expandedWidth='w-full'>
<div className="w-full h-full overflow-auto flex">
<PlotlyHeatMap array={rawArray} title='RAW' xAxisTitle='Averaged Vertical Intensity' yAxisTitle='Frame' width='w-1/3' verticalScaleFactor={heatmapSettings.scaleFactor.value} showTicks={heatmapSettings.showTicks.value}/>
<PlotlyHeatMap array={vfftArray} title='VFFT' xAxisTitle='Averaged Vertical Intensity' yAxisTitle='Frame' width='w-1/3' verticalScaleFactor={heatmapSettings.scaleFactor.value} showTicks={heatmapSettings.showTicks.value}/>
<PlotlyHeatMap array={ifftArray} title='IFFT' xAxisTitle='Averaged Vertical Intensity' yAxisTitle='Frame' width='w-1/3' verticalScaleFactor={heatmapSettings.scaleFactor.value} showTicks={heatmapSettings.showTicks.value}/>
<PlotlyHeatMap array={rawArray} title='RAW' xAxisTitle='' yAxisTitle='' width='w-1/3' verticalScaleFactor={heatmapSettings.scaleFactor.value} showTicks={heatmapSettings.showTicks.value}/>
<PlotlyHeatMap array={vfftArray} title='VFFT' xAxisTitle='' yAxisTitle='' width='w-1/3' verticalScaleFactor={heatmapSettings.scaleFactor.value} showTicks={heatmapSettings.showTicks.value}/>
<PlotlyHeatMap array={ifftArray} title='IFFT' xAxisTitle='' yAxisTitle='' width='w-1/3' verticalScaleFactor={heatmapSettings.scaleFactor.value} showTicks={heatmapSettings.showTicks.value}/>
</div>
</Widget>

<div className='flex flex-wrap w-2/5'>
<Widget title='Recent Fitted Peaks' width='w-full' maxWidth='max-w-[1000px]' defaultHeight='h-1/2' maxHeight='max-h-96'>
<div className='flex flex-wrap w-2/5 h-full'>
<Widget title={`Shot Sum - Current Shot #${shotNumber}`} width='w-full' maxWidth='max-w-[1000px]' defaultHeight='h-1/2' maxHeight='max-h-[1000px]' contentStyles='flex-col space-y-1 pb-2'>
<PlotlyHeatMap array={shotRecentArray} title='Shot Recent' fixPlotHeightToParent={true} height="h-1/3" width='w-full' verticalScaleFactor={1} showTicks={false}/>
<PlotlyHeatMap array={shotMeanArray} title='Shot Mean' fixPlotHeightToParent={true} height="h-1/3" width='w-full' verticalScaleFactor={1} showTicks={false}/>
<PlotlyHeatMap array={shotStdArray} title='Shot Std' fixPlotHeightToParent={true} height="h-1/3" width='w-full' verticalScaleFactor={1} showTicks={false}/>
</Widget>
<Widget title='Recent Fitted Peaks' width='w-full' maxWidth='max-w-[1000px]' defaultHeight='h-1/4' maxHeight='max-h-96'>
<PlotlyScatterMultiple data={singlePeakData} title='Recent Fitted Peaks' xAxisTitle='x' yAxisTitle='y'/>
</Widget>
<Widget title='Cumulative Fitted Peaks' width='w-full' maxWidth='max-w-[1000px]' defaultHeight='h-1/2' maxHeight='max-h-96'>
<Widget title='Cumulative Fitted Peaks' width='w-full' maxWidth='max-w-[1000px]' defaultHeight='h-1/4' maxHeight='max-h-96'>
<PlotlyScatterMultiple data={allPeakData} title='Cumulative Fitted Peaks' xAxisTitle='x' yAxisTitle='y'/>
</Widget>
</div>
Expand Down
10 changes: 6 additions & 4 deletions frontend/src/components/PlotlyHeatMap.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ export default function PlotlyHeatMap({
colorScale = 'Viridis',
verticalScaleFactor = 0.1, // Scale factor for content growth
width = 'w-full',
height='h-full',
showTicks = false,
tickStep = 100
tickStep = 100,
fixPlotHeightToParent=false
}) {
const plotContainer = useRef(null);
const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
Expand Down Expand Up @@ -46,7 +48,7 @@ export default function PlotlyHeatMap({
const dynamicHeight = Math.max(array.length * verticalScaleFactor, 0); // Minimum height is 200px

return (
<div className={`h-full ${width} rounded-b-md pb-6 flex-col content-end relative`} ref={plotContainer}>
<div className={`${height} ${width} rounded-b-md pb-6 flex-col content-end relative`} ref={plotContainer}>
<Plot
data={data}
layout={{
Expand All @@ -68,7 +70,7 @@ export default function PlotlyHeatMap({
},
autosize: true,
width: dimensions.width,
height: dynamicHeight, // Dynamically set height
height: fixPlotHeightToParent ? dimensions.height : dynamicHeight, // Dynamically set height
margin: {
l: showTicks ? 50 : 10,
r: 10,
Expand All @@ -79,7 +81,7 @@ export default function PlotlyHeatMap({
config={{ responsive: true }}
className="rounded-b-md"
/>
<div className="absolute bottom-0 left-0 right-0 text-center py-2 text-md font-semibold">
<div className="absolute bottom-0 left-0 right-0 text-center text-md font-semibold">
{title}
</div>
</div>
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/components/Widget.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ export default function Widget({
maxHeight='max-h-3/4',
width='w-1/4',
maxWidth='max-w-full',
expandedWidth='w-full'
expandedWidth='w-full',
contentStyles=''
}) {
const [isExpanded, setIsExpanded] = useState(false);

Expand All @@ -35,7 +36,7 @@ export default function Widget({
</header>

{/* Main Body */}
<div className="h-[calc(100%-2.5rem)] rounded-b-md flex w-full">
<div className={`h-[calc(100%-2.5rem)] rounded-b-md flex w-full overflow-auto ${contentStyles}`}>
{children}
</div>
</div>
Expand Down
88 changes: 67 additions & 21 deletions frontend/src/hooks/useAPXPS.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,13 @@ export const useAPXPS = ({}) => {
const [ rawArray, setRawArray ] = useState([]);
const [ vfftArray, setVfftArray ] = useState([]);
const [ ifftArray, setIfftArray ] = useState([]);
const [ shotRecentArray, setShotRecentArray ] = useState([]);
const [ shotMeanArray, setShotMeanArray ] = useState([]);
const [ shotStdArray, setShotStdArray ] = useState([]);
const [ shotNumber, setShotNumber ] = useState(0);
const [ shotInfo, setShotInfo ] = useState({}); //TO DO: put state into here to track shots to frames and use for tick marks

const [ singlePeakData, setSinglePeakData ] = useState({x:[], y:[]});
const [ singlePeakData, setSinglePeakData ] = useState([]);
const [ allPeakData, setAllPeakData ] = useState([]);

const [ status, setStatus ] = useState({scan: 'N/A', websocket: 'N/A'});
Expand All @@ -33,7 +38,7 @@ export const useAPXPS = ({}) => {
scaleFactor: {
label: 'Scale Factor',
type: type.float,
value: '1',
value: '2',
description: 'Factor to scale the vertical axis of Raw, VFFT, and IFFT images in the heatmap. Larger number will increase the vertical height.'
},
showTicks: {
Expand Down Expand Up @@ -118,24 +123,44 @@ export const useAPXPS = ({}) => {
if ('raw' in newMessage) {
//console.log({newMessage})
//send in height as width and vice versa until height/width issues fixed
processArrayData(newMessage.raw, newMessage.height, newMessage.width, setRawArray)
//processArrayData(newMessage.raw, newMessage.height, newMessage.width, setRawArray);
processAndDownsampleArrayData(newMessage.raw, newMessage.height, newMessage.width, 2, setRawArray);
}
if ('vfft' in newMessage) {
//console.log({newMessage})
//send in height as width and vice versa until height/width issues fixed
processArrayData(newMessage.vfft, newMessage.height, newMessage.width, setVfftArray)
//processArrayData(newMessage.vfft, newMessage.height, newMessage.width, setVfftArray);
processAndDownsampleArrayData(newMessage.vfft, newMessage.height, newMessage.width, 2, setVfftArray);
}
if ('ifft' in newMessage) {
//console.log({newMessage})
//send in height as width and vice versa until height/width issues fixed
processArrayData(newMessage.ifft, newMessage.height, newMessage.width, setIfftArray)
//processArrayData(newMessage.ifft, newMessage.height, newMessage.width, setIfftArray);
processAndDownsampleArrayData(newMessage.ifft, newMessage.height, newMessage.width, 2, setIfftArray);
}

if ('msg_type' in newMessage) {
console.log({newMessage});
//add to metadata display and clear cumulative plots
handleStartDocument(newMessage);
}
if ('shot_recent' in newMessage) {
//technically metadata won't have f_reset due to stale state at time of function initilization, need to put it into a ref
var shotHeight = ("f_reset" in metadata) ? metadata.f_reset : (newMessage.shot_recent.length / newMessage.height)
processArrayData(newMessage.shot_recent, newMessage.height, shotHeight, setShotRecentArray)
}
if ('shot_mean' in newMessage) {
var shotHeight = ("f_reset" in metadata) ? metadata.f_reset : (newMessage.shot_mean.length / newMessage.height)
processArrayData(newMessage.shot_mean, newMessage.height, shotHeight, setShotStdArray)
}
if ('shot_std' in newMessage) {
var shotHeight = ("f_reset" in metadata) ? metadata.f_reset : (newMessage.shot_std.length / newMessage.height)
processArrayData(newMessage.shot_std, newMessage.height, shotHeight, setShotMeanArray)
}
if ('shot_num' in newMessage) {
setShotNumber(newMessage.shot_num);
}
console.log({newMessage})
} catch (error) {
console.error('Error processing WebSocket message:', error);
}
Expand All @@ -149,29 +174,46 @@ export const useAPXPS = ({}) => {
};

const processArrayData = (data=[], width, height, cb) => {
//console.time("processArrayData"); // Start timing

// average 0.58 ms / img
/* const newData = new Array(height);

for (let i = 0; i < height; i++) {
// Directly assign the sliced portion to the preallocated array
newData[i] = data.slice(i * width, (i + 1) * width);
}
*/



//convert a single dimensional array data into width and height to make suitable for heatmap
// average 0.54 ms / img
const newData = [];
for (let i = 0; i < height; i++) {
newData.push(data.slice(i * width, (i + 1) * width));
}
cb(newData);
};


//console.timeEnd("processArrayData"); // End timing and log duration
const processAndDownsampleArrayData = (data = [], width, height, scaleFactor = 1, cb) => {
if (scaleFactor < 1) throw new Error("Scale factor must be 1 or greater.");

const downsampledHeight = Math.floor(height / scaleFactor);
const downsampledWidth = Math.floor(width / scaleFactor);
const newData = [];

for (let row = 0; row < downsampledHeight; row++) {
const newRow = [];
for (let col = 0; col < downsampledWidth; col++) {
let sum = 0;
let count = 0;

// Sum up values within the scaleFactor x scaleFactor block
for (let i = 0; i < scaleFactor; i++) {
for (let j = 0; j < scaleFactor; j++) {
const originalRow = row * scaleFactor + i;
const originalCol = col * scaleFactor + j;
const index = originalRow * width + originalCol;

if (originalRow < height && originalCol < width) {
sum += data[index];
count++;
}
}
}
// Calculate the average value and add to the downsampled row
newRow.push(sum / count);
}
newData.push(newRow);
}
cb(newData);
};

Expand Down Expand Up @@ -343,6 +385,10 @@ export const useAPXPS = ({}) => {
status,
heatmapSettings,
handleHeatmapSettingChange,
metadata
metadata,
shotNumber,
shotRecentArray,
shotMeanArray,
shotStdArray
}
}
6 changes: 5 additions & 1 deletion src/_tests/test_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
import pytest

# from tr_ap_xps.pipeline.xps_operator import XPSProcessor
# from tr_ap_xps.schemas import XPSStart
# from tr_ap_xps.schemas import XPSRawEvent


@pytest.fixture
def integrated_frame():
return np.random.randint(0, 100, size=(5, 10), dtype="int32")


def test_xps_processor():
pass


# def test_XPSDataSet(client, integrated_frame):
# if "runs" not in client:
# runs_node = client.create_container("runs")
Expand Down
4 changes: 2 additions & 2 deletions src/tr_ap_xps/pipeline/fft.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def calculate_fft_items(array: np.array, repeat_factor: int = 20, width: int = 0

array = np.array(array)
vfft = get_vfft(array)
sum = get_sum(vfft)
# sum = get_sum(vfft)
ifft = get_ifft(array, repeat_factor, width)

return vfft, sum, ifft
return vfft, ifft
Loading
Loading