/* * utils.c * * Utility stuff * * Copyright © 2012 Deutsches Elektronen-Synchrotron DESY, * a research centre of the Helmholtz Association. * * Authors: * 2009-2012 Thomas White * * This file is part of CrystFEL. * * CrystFEL is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CrystFEL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with CrystFEL. If not, see . * */ #include #include #include #include #include #include #include #include #include #include #include "utils.h" #include "image.h" /** * SECTION:utils * @short_description: Miscellaneous utilities * @title: Utilities * @section_id: * @see_also: * @include: "utils.h" * @Image: * * Wibble */ /** * show_matrix_eqn: * @M: A matrix * @v: A vector * @r: The number of elements in @v and the side length of @M. * * Displays a matrix equation of the form @M.a = @v. * * @M must be square. **/ void show_matrix_eqn(gsl_matrix *M, gsl_vector *v, int r) { int i, j; for ( i=0; i=0; i-- ) { if ( (s[i] == ' ') || (s[i] == '\t') ) { s[i] = '\0'; munched++; } else { return munched; } } return munched; } void chomp(char *s) { size_t i; if ( !s ) return; for ( i=0; i 100.0 ) return fake_poisson_noise(expected); L = exp(-expected); do { double r; k++; r = (double)random()/(double)RAND_MAX; p *= r; } while ( p > L ); return k - 1; } /** * SECTION:quaternion * @short_description: Simple quaternion handling * @title: Quaternion * @section_id: * @see_also: * @include: "utils.h" * @Image: * * There is a simple quaternion structure in CrystFEL. At the moment, it is * only used when simulating patterns, as an argument to cell_rotate() to * orient the unit cell. */ /** * quaternion_modulus: * @q: A %quaternion * * If a quaternion represents a pure rotation, its modulus should be unity. * * Returns: the modulus of the given quaternion. **/ double quaternion_modulus(struct quaternion q) { return sqrt(q.w*q.w + q.x*q.x + q.y*q.y + q.z*q.z); } /** * normalise_quaternion: * @q: A %quaternion * * Rescales the quaternion such that its modulus is unity. * * Returns: the normalised version of @q **/ struct quaternion normalise_quaternion(struct quaternion q) { double mod; struct quaternion r; mod = quaternion_modulus(q); r.w = q.w / mod; r.x = q.x / mod; r.y = q.y / mod; r.z = q.z / mod; return r; } /** * random_quaternion: * * Returns: a randomly generated, normalised, quaternion. **/ struct quaternion random_quaternion() { struct quaternion q; q.w = 2.0*(double)random()/RAND_MAX - 1.0; q.x = 2.0*(double)random()/RAND_MAX - 1.0; q.y = 2.0*(double)random()/RAND_MAX - 1.0; q.z = 2.0*(double)random()/RAND_MAX - 1.0; q = normalise_quaternion(q); return q; } /** * quaternion_valid: * @q: A %quaternion * * Checks if the given quaternion is normalised. * * This function performs a nasty floating point comparison of the form * (modulus > 0.999) && (modulus < 1.001), and so should not be * relied upon to spot anything other than the most obvious input error. * * Returns: 1 if the quaternion is normalised, 0 if not. **/ int quaternion_valid(struct quaternion q) { double qmod; qmod = quaternion_modulus(q); /* Modulus = 1 to within some tolerance? * Nasty allowance for floating-point accuracy follows... */ if ( (qmod > 0.999) && (qmod < 1.001) ) return 1; return 0; } /** * quat_rot * @q: A vector (in the form of an %rvec) * @z: A %quaternion * * Rotates a vector according to a quaternion. * * Returns: A rotated version of @p. **/ struct rvec quat_rot(struct rvec q, struct quaternion z) { struct rvec res; double t01, t02, t03, t11, t12, t13, t22, t23, t33; t01 = z.w*z.x; t02 = z.w*z.y; t03 = z.w*z.z; t11 = z.x*z.x; t12 = z.x*z.y; t13 = z.x*z.z; t22 = z.y*z.y; t23 = z.y*z.z; t33 = z.z*z.z; res.u = (1.0 - 2.0 * (t22 + t33)) * q.u + (2.0 * (t12 + t03)) * q.v + (2.0 * (t13 - t02)) * q.w; res.v = (2.0 * (t12 - t03)) * q.u + (1.0 - 2.0 * (t11 + t33)) * q.v + (2.0 * (t01 + t23)) * q.w; res.w = (2.0 * (t02 + t13)) * q.u + (2.0 * (t23 - t01)) * q.v + (1.0 - 2.0 * (t11 + t22)) * q.w; return res; } /* Return non-zero if c is in delims */ static int assplode_isdelim(const char c, const char *delims) { size_t i; for ( i=0; i 0 ) { /* This is a deliminator after a sequence of * non-deliminator chars */ n = assplode_extract(&bits, n, n_captured, start, a); } n_captured = 0; if ( (flags & ASSPLODE_DUPS) && last_was_delim ) { n = assplode_extract(&bits, n, 0, start, a); } last_was_delim = 1; } else { if ( n_captured == 0 ) { /* No characters currently found, so this is the * start */ start = i; } n_captured++; last_was_delim = 0; } i++; } /* Left over characters at the end? */ if ( n_captured > 0 ) { n = assplode_extract(&bits, n, n_captured, start, a); } *pbits = bits; return n; } char *check_prefix(char *prefix) { int r; struct stat statbuf; char *new; size_t len; /* Is "prefix" a directory? */ r = stat(prefix, &statbuf); if ( r != 0 ) { /* "prefix" probably doesn't exist. This is fine - assume * the user knows what they're doing, and that "prefix" * suffixed with the actual filename will produce something * sensible. */ return prefix; } if ( !S_ISDIR(statbuf.st_mode) ) { /* Also fine, as above. */ return prefix; } /* Does the prefix end in a slash? */ if ( prefix[strlen(prefix)-1] == '/' ) { /* This looks sensible. */ return prefix; } STATUS("Your prefix ('%s') is a directory, but doesn't end" " with a slash. I'm going to add it for you.\n", prefix); STATUS("If this isn't what you want, run with --no-check-prefix.\n"); len = strlen(prefix)+2; new = malloc(len); snprintf(new, len, "%s/", prefix); free(prefix); return new; } char *safe_basename(const char *in) { int i; char *cpy; char *res; cpy = strdup(in); /* Get rid of any trailing slashes */ for ( i=strlen(cpy)-1; i>0; i-- ) { if ( cpy[i] == '/' ) { cpy[i] = '\0'; } else { break; } } /* Find the base name */ for ( i=strlen(cpy)-1; i>0; i-- ) { if ( cpy[i] == '/' ) { i++; break; } } res = strdup(cpy+i); /* If we didn't find a previous slash, i==0 so res==cpy */ free(cpy); return res; } /* Force the linker to bring in CBLAS to make GSL happy */ void utils_fudge_gslcblas() { STATUS("%p\n", cblas_sgemm); }