Creating a histogram from a large file - c

I have two large files containing float-type data. I want to create a histogram using the two files. However, to access the 256^3 data values, I tried using a nested for-loop in C which failed with a segmentation fault.
Is there an alternative method that I can use to access the data values that would not result in a segmentation fault?
Here is my code:
int main () {
int i,j,k,n_grid;
float pc,mass_g,spat_res,vol_pix,max_vel,min_vel;
float velocity,density,max;
long start,index,index1,index2,counter,lSize,dim;
FILE *p,*q;
pc = 3.085677e-18; //1 parsec in cm
n_grid = 256; //dimension of observed portion of input grid
mass_g = 0.0;
spat_res = pc*0.71/512; //spatial resolution of grid in cm
vol_pix = pow(spat_res,3); //volume of each voxel in cm^3
p = fopen("../dens_104/rho_052.dat","rb");
q = fopen("../dens_104/velz.dat","rb");
if (!p){
printf("Unable to open dens file!");
return 0;
}
else if (!q){
printf("Unable to open the velx file!");
return 0;
}
//obtain file size(s)
fseek(p,0,SEEK_END);
lSize = ftell(p);
rewind(p);
dim = pow(lSize/sizeof(float),1.0/3.0); //actual size of input grid
max = 0;
counter = 0;
index = 0;
while(fread(&density,sizeof(float),1,p),!feof(p) && !ferror(p)) {
if(density > max) max = density,index = counter;
counter += 1;
}
start = index - (pow(dim,2)+dim+1)*(n_grid/2-1);
printf("Starting pixel value: %lu, Dimension of cube: %d\n",start,
(int)dim);
printf("The maximum density is: %e with index: %lu \n", max,index);
rewind(p);
fseek(p,start*sizeof(float),SEEK_SET);
fseek(q,start*sizeof(float),SEEK_SET);
max_vel = 0.0;
min_vel = 0.0;
index1 = 0;
index2 = 0;
while(fread(&velocity,sizeof(float),1,q),!feof(q) && !ferror(q)) {
if(velocity > max_vel) max_vel = velocity,index1=counter;
if(velocity < min_vel) min_vel = velocity,index2=counter;
counter += 1;
}
printf("The maximum velocity is: %e with index: %lu\n", max_vel,index1);
printf("The minimum velocity is: %e with index: %lu\n", min_vel,index2);
density = 0.;
for (k=0;k<n_grid;k++){
fseek(p,(start+k*dim*dim)*sizeof(float),SEEK_SET);
for (j=0;j<n_grid;j++){
fseek(p,(start+j*dim+k*dim*dim)*sizeof(float),SEEK_SET);
for (i=0;i<n_grid;i++){
fread(&density,sizeof(float),1,p);
mass_g += density*vol_pix;
}
}
}
printf("The mass of the observed cube is: %e \n", mass_g);
}

Related

Is it possible to compare the strings inside a 2D array and do calculation in the 2D array?

is it possible to compare the strings inside a 2D array and do calculation in the 2D array? I've wrritten the code out and it doesn't shows me any error, but it stopped executing after the data in the file was stored into fdata[][] 2D array.
#define BSIZE 1024
char fdata[BSIZE][100];
float total;
int line = 0, ctr = 0, x = 4;
int remove_dataX_Fquantity(char fdata[BSIZE], int x);
int remove_dataX_Fcode(char fdata[BSIZE], int x);
fopen_s(&fptr, "Dist.txt", "r");
while (!feof(fptr) && !ferror(fptr)) // read into fdata[]
{
if (fgets(fdata[line], 100, fptr) != NULL)
line++;
}
fclose(fptr);
for (ctr = 0; ctr < line; ctr++) //print out each row in fdata[] from 0 to line
{
printf("row %d: %s", ctr,fdata[ctr]);
}
do //compiler doesn't execute the code starting from here and it stopped at the code above this line.
{
if (strcmp(fdata[ctr], fdata[x]) == 0) //start to compare the string within the array
{
if (fdata[x] == NULL)
x = 0;
else
{
total = atof(fdata[ctr + 1]) + atof(fdata[x+1]); //accumulate
*fdata[ctr + 1] = total;
remove_dataX_Fquantity(fdata[x+1], x);
remove_dataX_Fcode(fdata[x], x);
printf("Code: %s, Accumulated Quantity: %.1f", fdata[ctr], total);
ctr+4;
x+4;
}
}
else if (strcmp(fdata[ctr], fdata[x]) != 0)
{
x+4;
}
} while (fdata[ctr] != NULL);
Here is the test data
fm
10.0
hospital a
sm
5.0
hospital b
fm
15.0
hospital b
sm
10.0
hospital c
om
3.0
hospital a

multiple analog inputs to produce individual averages for each channel

I am trying to put four analog inputs into individual channels that contain an array. Once that happens I am trying to get an average of each channel's array getting a single int or float. Lastly, I want to compare the averages in an if statement to get a serial print and divide the compared averages.
I am just confused on what in the code I pieced together is necessary.
Thank you for any advice or help.
Here is my code below
#include <Servo.h>
float sVal0 = 0.0;
float sVal1 = 0.0;
float sVal2 = 0.0;
float sVal3 = 0.0;
float sVal02 = 0.0;
float sVal13 = 0.0;
const int numReadings = 10; //# of readings needed to average
const int numChannels = 4; // 4 analog outputs
int readings[numChannels][numReadings]; // the readings from the analog input
int index; // the index of the current reading
void setup () {
Serial.begin(9600);
}
void loop () {
sVal0 = analogRead(A0);
sVal1 = analogRead(A1);
sVal2 = analogRead(A2);
sVal3 = analogRead(A3);
for (int chan = 0; chan <= numChannels; ++chan ){
Serial.println(sVal0[chan]); // serial print each array
Serial.println(sVal1[chan]);
Serial.println(sVal2[chan]);
Serial.println(sVal3[chan]);
for (int thisReading = 0; thisReading < numReadings; thisReading++) {
readings[thisReading] = 0;
index = index + 1;
}
if (index >= numReadings) {
index = 0;
sVal0_avg = sVal0[chan]/numReadings; // get average
sVal1_avg = sVal0[chan]/numReadings;
sVal2_avg = sVal0[chan]/numReadings;
sVal3_avg = sVal0[chan]/numReadings;
}
}
if (sVal1_avg > sVal3_avg) {
Serial.print("1 avg: );
Serial.println(sVal1_avg);
sVal31 = sVal3_avg / sVal1_avg;
Serial.print("comparison : ");
Serial.println(sVal31);
}
}

Finding the largest difference between multiple sets of numbers

I've attempted to create a program which processes a list of outcomes for football games while also processing the results.
The way my program works is you input the number of matches that have been played then you list the results of each match.
Each row in the list has the form of HOME_TEAM_ID | AWAY_TEAM_ID | HOME_TEAM_GOALS | AWAY_TEAM_GOALS
So for example if the user entered (the first line is the number of matches):
2
0 1 5 0
2 3 0 5
My program will then output a row containing: team id, win ratio, win ratio on home games, average point difference in won games ( -1 in case of no home games.) The largest (in terms of point difference) win in a single game and then the ID of that opponent.
0 1.000 1.000 5.000
1 0.000 -1 -1
2 0.000 0.000 -1
3 1.000 -1 5.000
I've completed most of my program but I'm having difficulty implementing one last part. I want to find out the the largest (in terms of goal difference) win in a single game for each team and then the ID of the opponent which they had their largest win in terms of goal difference. (If there aren't any wins then it should simply output -1.)
My first thought was to just loop through the array, setting a variable to the largest win. For each element, check if its point difference is higher than the variable. If it is, replace the variable with the current element's difference.
However I'm getting a compiler error.
1079.c: In function 'main':
1079.c:153:11: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
maximum = resultTable[0];
^
1079.c:157:24: warning: comparison between pointer and integer
if (resultTable[n] > maximum)
^
1079.c:159:17: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
maximum = resultTable[n];
Any help about how to find the largest average point difference, over multiple games, against one particular opponent, would be greatly appreciated.
Here's my full code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//My local variables
int n;
int i;
int input = 0;
int TEAM_ID = 0, NUM_OF_GAMES = 1, WINS = 3, HOME_GAMES = 2, HOME_WINS = 4, HOME_WIN_RATIO = 6, WIN_RATIO = 5, GD = 7;
int homeTeamID, awayTeamID, homeGoals, awayGoals;
static const int NUM_COLUMNS = 10;
static const int NUM_TEAMS = 30;
double resultTable[30][10];
int BEST_WIN_DIFF = 8, BEST_WIN_OPPONENT = 9;
void takeInput();
void sortData();
void printer();
//This method takes the input from the user for homeTeamID, awayTeamID,homeGoals and awayGoals
void takeInput()
{
scanf("%d", &input);
for (n = 0; n < input; n++) {
scanf("%d %d %d %d", &homeTeamID, &awayTeamID, &homeGoals, &awayGoals);
//calls the sortData function
sortData();
}
}
//The table fnction which uses the resultTable variable to put the infomation in a table
void sortData()
{
int goalDiff = homeGoals - awayGoals;
//This will increment the home games,home game counter and the away game
resultTable[homeTeamID][NUM_OF_GAMES]++;
resultTable[homeTeamID][HOME_GAMES]++;
resultTable[awayTeamID][NUM_OF_GAMES]++;
//If the awaygoals is larger than the homegoals then it will set the winner in the results table
if (homeGoals < awayGoals) {
resultTable[awayTeamID][WINS]++; //increment away wins
}
//If the homegoals is larger than the awaygoals then it will set the winner in the results table
else if (homeGoals > awayGoals) {
resultTable[homeTeamID][WINS]++;
resultTable[homeTeamID][HOME_WINS]++; //increment home wins
}
//The goal difference for home and away
resultTable[homeTeamID][GD] = resultTable[homeTeamID][GD] + (homeGoals - awayGoals);
resultTable[awayTeamID][GD] = resultTable[awayTeamID][GD] + (awayGoals - homeGoals);
if (goalDiff > resultTable[homeTeamID][BEST_WIN_DIFF]) {
resultTable[homeTeamID][BEST_WIN_DIFF] = goalDiff;
resultTable[homeTeamID][BEST_WIN_OPPONENT] = awayTeamID;
}
if (-goalDiff > resultTable[awayTeamID][BEST_WIN_DIFF]) {
resultTable[awayTeamID][BEST_WIN_DIFF] = -goalDiff;
resultTable[awayTeamID][BEST_WIN_OPPONENT] = homeTeamID;
}
}
//Calculates the win ratio
void winRatio()
{
for (n = 0; n < 30; n++) {
//This if determines the home win ratio
if (resultTable[n][HOME_GAMES] > 0) {
resultTable[n][HOME_WIN_RATIO] = resultTable[n][HOME_WINS]
/ resultTable[n][HOME_GAMES];
}
if (resultTable[n][NUM_OF_GAMES] > 0) {
resultTable[n][GD] = resultTable[n][GD] / resultTable[n][NUM_OF_GAMES];
}
//This if determines the win ratio
if (resultTable[n][NUM_OF_GAMES] > 0) {
resultTable[n][WIN_RATIO] = resultTable[n][WINS]
/ resultTable[n][NUM_OF_GAMES];
}
}
}
//This method prints out the results
void printer()
{
for (n = 0; n < NUM_TEAMS; n++) {
if (resultTable[n][NUM_OF_GAMES] != 0) {
if (resultTable[n][HOME_WIN_RATIO] == -1) {
printf("%d %.3f %.0f %.3f %.0f %.0f\n", n,
resultTable[n][WIN_RATIO],
resultTable[n][HOME_WIN_RATIO],
resultTable[n][GD],
resultTable[n][BEST_WIN_DIFF],
resultTable[n][BEST_WIN_OPPONENT]);
}
else {
printf("%d %.3f %.3f %.3f %.0f %.0f\n", n,
resultTable[n][WIN_RATIO],
resultTable[n][HOME_WIN_RATIO],
resultTable[n][GD],
resultTable[n][BEST_WIN_DIFF],
resultTable[n][BEST_WIN_OPPONENT]);
}
}
}
}
//My main function which will be used to call everyother function
int main(void)
{
for (n = 0; n < NUM_TEAMS; n++) {
for (i = 1; i < NUM_COLUMNS; i++) {
resultTable[n][i] = 0;
}
resultTable[n][TEAM_ID] = n;
resultTable[n][HOME_WIN_RATIO] = -1;
resultTable[n][BEST_WIN_DIFF] = -HUGE_VAL;
}
int maximum, location = 1;
for (n = 0; n < 30; n++)
scanf("%d", &resultTable[n]);
maximum = resultTable[0];
for (n = 0; n < 30; n++)
{
if (resultTable[n] > maximum)
{
maximum = resultTable[n];
location = n+1;
}
}
printf("Maximum element is present at location %d and it's value is %d.\n", location, maximum);
return 0;
takeInput();
winRatio();
printer();
return EXIT_SUCCESS;
}
You can't get the information you want (the largest etcetera) from the data you enter into the array because you throw away information you need later to calculate this.
You need to store the input data unchanged into the array, then you can calculate anything from it you want.
In particular, with
//The goal difference for home and away
resultTable[homeTeamID][GD] = resultTable[homeTeamID][GD] + (homeGoals - awayGoals);
resultTable[awayTeamID][GD] = resultTable[awayTeamID][GD] + (awayGoals - homeGoals);
you remember the difference, but that is not enough to calculate the largest win in a single game for each team. Instead, store both homeGoals and awayGoalsand then later calculate the information you want.
Include math.h for HUGE_VAL.
#include <math.h>
Add two extra columns.
static const int NUM_COLUMNS = 10;
static const int NUM_TEAMS = 30;
double resultTable[NUM_TEAMS][NUM_COLUMNS];
int BEST_WIN_DIFF = 8, BEST_WIN_OPPONENT = 9;
Add them to the table function.
void table()
{
int i;
for (n = 0; n < NUM_TEAMS; n++) {
for (i = 1; i < NUM_COLUMNS; i++) {
resultTable[n][i] = 0;
}
resultTable[n][TEAM_ID] = n;
resultTable[n][HOME_WIN_RATIO] = -1;
resultTable[n][BEST_WIN_DIFF] = -HUGE_VAL;
}
}
Add the new code to the end of sortData.
void sortData()
{
...
int goalDiff = homeGoals - awayGoals;
if (goalDiff > resultTable[homeTeamID][BEST_WIN_DIFF]) {
resultTable[homeTeamID][BEST_WIN_DIFF] = goalDiff;
resultTable[homeTeamID][BEST_WIN_OPPONENT] = awayTeamID;
}
if (-goalDiff > resultTable[awayTeamID][BEST_WIN_DIFF]) {
resultTable[awayTeamID][BEST_WIN_DIFF] = -goalDiff;
resultTable[awayTeamID][BEST_WIN_OPPONENT] = homeTeamID;
}
}
and finally update printer to include the extra columns.
void printer()
{
for (n = 0; n < NUM_TEAMS; n++) {
if (resultTable[n][NUM_OF_GAMES] != 0) {
if (resultTable[n][HOME_WIN_RATIO] == -1) {
printf("%d %.3f %.0f %.3f %.0f %.0f\n", n,
resultTable[n][WIN_RATIO],
resultTable[n][HOME_WIN_RATIO],
resultTable[n][GD],
resultTable[n][BEST_WIN_DIFF],
resultTable[n][BEST_WIN_OPPONENT]);
}
else {
printf("%d %.3f %.3f %.3f %.0f %.0f\n", n,
resultTable[n][WIN_RATIO],
resultTable[n][HOME_WIN_RATIO],
resultTable[n][GD],
resultTable[n][BEST_WIN_DIFF],
resultTable[n][BEST_WIN_OPPONENT]);
}
}
}
}
double resultTable[30][10];
resultTable[x] is a pointer to double [10]
resultTable[x] is a pointer of double *
resultTable[x][y] is double
That is the reason you get the warning
You have more problems in your code
you scanf integers, but pass pointer to double etc etc.

Segmentation Error 11 in C while writing a file to disk and using buffers

This program is designed to create an output sine wave file with user inputs for duration, amplitude, sampling rate and frequency, filling a buffer with values and applying an short attack and decay ramp before writing a new .aiff file with the data.
Although my program compiles fine, it runs into a 'Segmentation Error 11' when ran with arguments, which after some quick googling seems linked to running out of memory. I've checked my code several times (mainly the areas that deal with the buffer size and pointers to it).
/* playsine.c */
/* Creates a sine wave audio file with input outfile - duration - amplitude - sampling
rate - frequency */
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <portsf.h>
int makeSine(float *buffer, double amplitude, long numFrames, double sineFreq,
double samplingPeriod){
long i;
double time;
double twoPi = 2 * M_PI;
for(i = 0, time = 0; i < numFrames; i++){
buffer[i] = amplitude * sin(twoPi * sineFreq * time);
time += samplingPeriod;
}
return i;
}
long attack(float *buffer, long attackFrames){
long i = 0;
double factor = 0.0, increment = 1.0/attackFrames;
while(factor <= 1.0 && i < attackFrames){
buffer[i] = factor * buffer[i];
factor += increment;
++i;
}
return i;
}
long decay(float *endBuffer, long decayFrames){
long i = 0;
double factor = 1.0, decrement = 1.0/decayFrames;
while(factor >= 0.0 && i < decayFrames){
endBuffer[i] = decayFrames * endBuffer[i];
factor -= decrement;
++i;
}
return i;
}
enum {nameArg, outArg, durArg, ampArg, sampArg, freqArg, numArg};
int main(int argc, char* argv[]){
if(argc < numArg){
printf("Usage:\toutfile.aiff\tduration(s)\tamplitude(0-1)\tsampling rate\t\
frequency(hz)\n");
return 1;
}
if(psf_init()){
printf("Error: Unable to open portsf library\n");
return 1;
}
PSF_PROPS props;
int outfile;
long numFrames, samplingRate = atol(argv[sampArg]);
double amps = atof(argv[ampArg]), samplingPeriod = 1.0/samplingRate;
double sineFreq = atof(argv[freqArg]), attackFrames = 0.005 * samplingRate;
double decayFrames = 0.01 * samplingRate;
float *buffer, duration = atof(argv[durArg]);
numFrames = (long)duration * samplingRate;
float *endBuffer = buffer + (numFrames - (long)decayFrames);
//Fill structure
props.srate = samplingRate;
props.chans = 1;
props.samptype = PSF_SAMP_16;
props.format = PSF_AIFF;
props.chformat = MC_MONO;
//Assign buffer
buffer = (float*)malloc(numFrames * props.chans * sizeof(float));
if(buffer == 0){
printf("Error: unable to allocate buffer\n");
return 1;
}else{
//Fill buffer
if(makeSine(buffer, amps, numFrames, sineFreq, samplingPeriod) != numFrames){
printf("Error: unable to create sinewave\n");
return 1;
}
attack(buffer, attackFrames);
decay(endBuffer, decayFrames);
}
//Create an outfile
outfile = psf_sndCreate(argv[outArg], &props, 0, 0, PSF_CREATE_RDWR);
if(outfile < 0){
printf("Error: unable to create %s\n", argv[outArg]);
return 1;
}
//Write buffer to file
printf("Writing %s ...\n", argv[outArg]);
if(psf_sndWriteFloatFrames(outfile, buffer, numFrames) != numFrames){
printf("Warning: error writing %s\n", argv[outArg]);
return 1;
}
//Close file
if(psf_sndClose(outfile)){
printf("Warning: error closing %s\n", argv[outArg]);
return 1;
}
psf_finish();
return 1;
}
Two immediate problems that I see in decay() and attack():
long attack (float *buffer, long attackFrames) {
long i;
...
buffer[i] = factor * buffer[i]; //Oops, i is never initialized
The variable i is never initialized. This is undefined behaviour and could well lead to crashes. I assume you actually wanted to do something like:
long attack (float *buffer, long attackFrames) {
long i = 0;
double factor = 0.0, increment = 1.0/attackFrames;
while(factor <= 1.0 && i < attackFrames) {
buffer[i] = factor * buffer[i];
factor += increment;
++i;
}
return i;
}
Edit: Another problem is you reference uninitialized memory with endBuffer:
float *buffer; // Buffer not initialized
float *endBuffer = buffer + (numFrames - (long)decayFrames); // Oops!
...
buffer = (float*)malloc(numFrames * props.chans * sizeof(float));
//endBuffer still points to buffer's original address which is who-knows-where
You should assign endBuffer after you use malloc() to allocate buffer.

Caculating the PSD using FFTW

I'm sound file that I've record using the `ALSA' lib using following setups :
Fs = 96000; // sample frequency
channelNumber = 1 ;
format =int16 ;
length = 5sec;
meaning that I get 480000 16bit value. Now I want to calculate the PSD of the set of that to get something like :
what I'm trying to do is tto save the result as a bunch of double value in a extra data so I can plot them of evaluating them ( I'm not sure if that's correct) :
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <fftw3.h>
int main(){
char fileName[] = "sound.raw";
char magnFile[] = "data.txt";
FILE* inp = NULL;
FILE* oup = NULL;
float* data = NULL;
fftwf_complex* out;
int index = 0;
fftwf_plan plan;
double var =0;
short wert = 0;
float r,i,magn;
int N = 512;
data =(float*)fftwf_malloc(sizeof(float)*N);
out = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex)*N);
//Allocating the memory for the input data
plan = fftwf_plan_dft_r2c_1d(N,data,out, FFTW_MEASURE);
// opening the file for reading
inp = fopen(fileName,"r");
oup = fopen(magnFile,"w+");
if(inp== NULL){
printf(" couldn't open the file \n ");
return -1;
}
if(oup==NULL){
printf(" couldn't open the output file \n");
}
while(!feof(inp)){
if(index < N){
fread(&wert,sizeof(short),1,inp);
//printf(" Wert %d \n",wert);
data[index] = (float)wert;
//printf(" Wert %lf \n",data[index]);
index = index +1;
}
else{
index = 0;
fftwf_execute(plan);
//printf("New Plan \n");
//printf(" Real \t imag \t Magn \t \n");
for(index = 0 ; index<N; index++){
r=out[index][0];
i =out[index][1];
magn = sqrt((r*r)+(i*i));
printf("%.10lf \t %.10lf \t %.10lf \t \n",r,i,magn);
//fwrite(&magn,sizeof(float),1,oup);
//fwrite("\n",sizeof(char),1,oup);
fprintf(oup,"%.10lf\n ", magn);
}
index = 0 ;
fseek(inp,N,SEEK_CUR);
}
}
fftwf_destroy_plan(plan);
fftwf_free(data);
fftwf_free(out);
fclose(inp);
fclose(oup);
return 0 ;
}
the problem that I have is how can I implement the winding function in my code ?
and I don't think that result is accurate, since I'get a lot of zero in magnitude values ? ?
if somebody has an example I'll be thankful .
Here is a simple example of applying a "Hanning" window to your data prior to the FFT:
for (int i = 0; i < N; ++i)
{
data[i] *= 0.5 * (1.0 + cos(2.0 * M_PI * (double)i / (double)(N - 1)));
}

Resources